SOLID oraz zasady projektowania Flashcards
Jakie są zasady SOLID ?
S - Single-responsiblity Principle
O - Open-closed Principle
L - Liskov Substitution Principle
I - Interface Segregation Principle
D - Dependency Inversion Principle
Na czym polega Single Responsibility Principle ?
Klasa powinna podlegać zmianie tylko z jednego powodu.
Spróbuj uczynić każdą klasę odpowiedzialną za jedną tylko część funkcjonalności oferowanej przez oprogramowanie i niech ta odpowiedzialność będzie całkowicie hermetyzowana.
Głównym celem tej zasady jest redukcja złożoności. Nie trzeba wynajdywać skomplikowanego projektu dla programu któryskłada się tylko z 200 linii kodu. Wystarczy tuzin ładnie napisanych metod.
Przykład Solid Responsibility Principle
- błędem jest że klasa pracownik może być zmodyfikowana z dwóch powodów:
- zarządzanie danymi pracownika
- drukowanie raportu ewidencji
- w przypadku zmiany raportu ewidnecji musisz zmienic kod klasy Employee
Open/Closed Principle
Klasy powinny być otwarte na rozszerzenie ale zamknięte na modyfikacje
- kluczem jest tworzenie abstrakcji, które są trwałe i rozszerzanie tych abstrakcji implementacjami
Open/Closed Principle - kiedy klasa jest otwarta ?
Klasa jest otwarta kiedy bez wpływu na obecny kod:
* można dodawać pola
* można dodawać metody
* tworzyć podklasy
Gdy jakaś klasa jest już opracowana, przetestowana, opisana izawarta w jakimś frameworku lub w inny sposób w aplikacji, to zmiana jej kodu niesie ryzyko. Zamiast zmieniać kod klasy bezpośrednio, tworzy się podklasę i nadpisuje te elementy pierwotnej klasy, których zachowanie chce się zmienić.
Open/Closed Principle - Przykład
- metoda getShippingCost() w klasie Order wymaga modyfikacji przy dodawaniu nowego sposobu przesyłki - klasa jest zamknięta
- tworząc interfejs Shipping oraz konkretne klasy obliczające koszt dla poszczególnych typów nie musimy modyfikować obecnego kodu
Liskov Substitution Principle
Rozszerzając klasę, trzeba pamiętać, aby było możliwe przekazywanie obiektów nowej podklasy w miejsce obiektów klasy bazowej bez psucia kodu klienta.
Nadpisując metodę, należy rozszerzać zachowanie klasy bazowej zamiast zamieniać je na coś zupełnie innego.
- relacje IS-A czasami jest za słaba i należy spojrzeć bardziej na zachowanie obiektów w przypadku dziedziczenia
Przykład - Liskov Substitution Principle
W matematyce kwadrat jest prostokątem, jeśli założymy że Square extends Rectangle może dojść do nieprawidłowego działania
public void resizeRectangle(Rectangle rect, double width, double height) { rect.setWidth(width); rect.setHeight(height); System.out.println("Pole powierzchni: " + rect.area()); }
Rectangle square = new Square(5); resizeRectangle(square, 10, 5); // Oczekujemy, że pole powierzchni będzie wynosić 50, ale faktyczny wynik to 100
Interface Segregation Principle
Klientom nie powinno się narzucać zależności od nieużywanych metod.
Staraj się tworzyć interfejsy na tyle wąsko wyspecjalizowane,żeby klienci nie musieli implementować zachowań których nie potrzebują.
Interface Segregation Principle Przykład
Dependency Inversion Principle
- Wysokopoziomowe klasy nie powinny być zależne od niskopoziomowych
- Obie grupy powinny być zależne od abstrakcji.
Abstrakcje nie powinny być zależne od szczegółów.
Szczegóły z kolei powinny zależeć od abstrakcji. - odseparowanie logiki binesowej od szegółów implementacyjnych
Dependency Inversion Principle - przykład
Zasady dobrego projektowania
- Hermetyzuj to co się różni - identyfikuj aspekty które ulegają zmianą i rodziel je od tego co stałę
- Programuj pod interfejs a nie implementację - opieraj się na abstrakcjach zamiast konkretnych klasach
- Preferuj kompozycje ponad dziedziczenie -
Hermetyzacja na poziomie klasy
- wyekstrachowanie dużej metody do osobnej klasy getTaxRate() -> TaxCalculator
Hermetyzacja na poziomie metody
- rozdzielenie rozbudowanej metody na kilka mniejszych