• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Dobre praktyki-interjesy w javie

Object Storage Arubacloud
0 głosów
149 wizyt
pytanie zadane 30 sierpnia 2018 w Java przez eskimos Nowicjusz (120 p.)
Kłaniam się,

Byłbym bardzo wdzięczny za pomoc w zrozumienie jeden rzeczy. Czytam o dobrych praktykach w programowaniu, np. o SOLID i mam pytanie odnosnie zasady jeddnej odpiwedzielnosci i pytanie ogolne ziwazane z interfejsami.

1)jedna odpowiedzialnosc- dla przykladu, mamy prosty program do obsugi bibioteki. Jest klasa book ktora bedzie przechowywala pola potrzebne ksiazce. Fajnie byloby tez zeby do biblioteki mozna bylo ksiazki dodawac, usuwac, podmieniac, ale tez wyswetlic wszstkie tytulu, szczególy wybranej pozycji, konkretne informacje jak autor, tytul itp itd. Teraz pojawia sie moje pytanie, czy zgodznie z zasada jedej odpowiedzialnosci powinismy nie trzymac tych metod w jednej klasie library tylko lepiej stowrzyc (przynajmniej) 2; library, gdzie bede metody jak add, remove, change i druga ShowLibraryContent gdzie bede metody showBooks, BookDetails itp? Czy dobrze rozumiem zasade jednej odpowiedzialności?

2) Pytanie ogolne o interfejsy, Uzyjmu tego samego przykladu co w pierwszym pytaniu. Czy w takiej sytuacji powinnismy miec tylko jeden interfejs library i klasy library i librarydetails beda go implementowac, czy mozne lepiej bylo by miec 2 interfejsy, jeden dla klasy library a 2 dla librarydetails? Pytanie pojawilo sie w mojej glowie gdy zaczlem sie zastanawiac czy dobra jest sytuacja, gdy mamy jeden interfejs ktory implementuja np 2-3 klasy i w tej syatuacji ten interfejs ma w sobie mnostwo metod, a kazda z implemetujacy go klas ma bardzo duzo niepotrzebnego kody w postacji przslonietych metod z ktorych i tak nie uzywa ale musi je niec zeby moc implementowac intejfejs?

Z gory dziekuje za wszelkie rady i wskazówki!

1 odpowiedź

+2 głosów
odpowiedź 30 sierpnia 2018 przez RafalS VIP (122,820 p.)
edycja 30 sierpnia 2018 przez RafalS

1) W przypadku, który podałeś trzeba rozróżnić jedną rzecz. Czym innym jest zarządzanie kilkoma klasami (wywoływanie ich metod) a czym innym implementacja tych metod. Klasa łamie zasade jednej odpowiedzialności jeśli za dużo implementuje. Nie łamie tej zasady jeśli jedynie zarządza klasami implementującymi poszczególne moduły funkcjonalności. W myśl tej zasady wyodrębnij z klasy biblioteka grupy metod i składowych odpowiedzialnych za konkretne funkcjonalności i zrób z nich oddzielne klasy. Później te klasy zawrzyj w klasie biblioteka, która będzie jedynie wywoływać ich metody. Wtedy co prawda Biblioteka odpowiada za wiele funkcjonalności, bo jest to logiczne i rozbicie jej na kilka odrębnych klas pogorszyłoby czytelność, ale biblioteka nie będzie implementować tych funkcjonalności. Zasada SRP spełniona.

Mówię o takiej sytuacji:

class Library{
    void printAll(){
        // dluga implementacja ladnego sformatowania
        // ksiazek do stringa i ich wypisanie
    }
    void print(int index){
        //implementacja...
    }
    void add(Book b) {
        //implementacja
    }
    // i cala reszta metod
}

Taką klase powinno się zrefactorować do czegoś takiego:

class LibraryContentPrinter {
    void printAll(){
        //implementacja
    }

    void print(int index){
        //implementacja
    }
}
class Library{
    LibraryContentPrinter printer;
    void printAll(){
        // delegacja
        printer.printAll();
    }
    void print(int index){
        //delegacja
        printer.print(index);
    }
    void add(Book b) {
        //implementacja
    }
}

Widzisz, że klasa Biblioteka logicznie pozbyła się części implementacji zastępując ją oddelegowaniem zadania do swoich składowych.

Ten przykład nie jest najlepszy na wytlumaczenie tej zasady, ale mam nadzieje, że coś przybliżyłem. Generalnie wypisanie ksiazki czy jej stringowa reprezentacja to odpowiedzialność samej klasy Book, ale na potrzeby przytoczonego przykładu zrobiłem tak jak chciałeś.

2) Jest w solidzie taka zasada: 

interface-segregation principle (ISP) states that no client should be forced to depend on methods it does not use.

która odpowiada na Twoje pytanie. Generalnie interfejsy powinne być porozdzielane tak, żeby:

  • zminimalizować zależności między klasami, co daży jednego wielkiego interfejsu ze wszystkim, bo wtedy nie ma żadnych zależnośći :D
  • zmaksymalizować spójność interfejsów, co daży do interfejsów z jednymi metodami, bo kilka metod musi mieć jakiś logiczny powód żeby trafić do interfesu, a co za tym idzie im jest ich wiecej tym powód jest bardziej naciągany i spójność spada.

Musisz znaleźć złoty środek. Tak, żeby nie natworzyć milona zależności pomiędzy malutkimi klasami / interfejsami z pojedyńczymi metodami, ale jednocześnie żeby interfejsy nie były za duże; żeby metody, które trafią do jednego interfejsu łączyło logicznie jak najwięcej.

Wyczucie w kwesti segregacji interfejsów przychodzi z czasem. Ciężko nauczyć się tego z teorii

1
komentarz 30 sierpnia 2018 przez mbabane Szeryf (79,280 p.)
class Library{
    LibraryContentPrinter printer = new LibraryContentPrinter();
.
.
.
.
}

Takiego czegoś należy unikać ponieważ całkowicie uzależnia jedną klasę od drugiej. Najlepiej zdaje się jest robić to przez konstruktor:

class Library{
    LibraryContentPrinter printer = new LibraryContentPrinter();

public Library(LibraryContentPrinter printer)
{
      this.printer = printer;
}

}


new Library( new LibraryContentPrinter() );
komentarz 30 sierpnia 2018 przez RafalS VIP (122,820 p.)
Ale wtedy pasowałoby też zrobić z tego pola interfejs. To nie był przykład na dependency injection, ale przyznaje racje. Usuwam zatem zły przykład inicjalizacji.
komentarz 31 sierpnia 2018 przez mbabane Szeryf (79,280 p.)
Pewnie tak - też trochę zależy od sytuacji, jeśli jest dobry argument żeby to była konkretna klasa to czemu nie - ważne jest że ma się do niej jakiś dostęp, przez co zależna klasa staje się bardziej testowalna.

Podobne pytania

0 głosów
0 odpowiedzi 138 wizyt
pytanie zadane 27 maja 2017 w OpenGL, Unity przez KubenQPL Maniak (62,820 p.)
+1 głos
1 odpowiedź 363 wizyt
pytanie zadane 1 kwietnia 2021 w PHP przez michal_php Stary wyjadacz (13,700 p.)
+1 głos
2 odpowiedzi 351 wizyt
pytanie zadane 11 marca 2021 w SQL, bazy danych przez CSSoup Mądrala (6,460 p.)

92,579 zapytań

141,432 odpowiedzi

319,657 komentarzy

61,963 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...