
Często spotykam programistów, którzy nie słyszeli o zasadach SOLID (my . — Przyp. red.) lub programowaniu obiektowym (OOP), albo słyszeli, ale nie stosują ich w praktyce. W tym artykule przedstawiono korzyści z zasad OOP, które pomagają programiście w codziennej pracy. Niektóre z nich są dobrze znane, inne — mniej, więc artykuł będzie przydatny zarówno dla nowicjuszy, jak i doświadczonych programistów.
Przypominamy: Dla wszystkich czytelników "Habra" — zniżka 10 000 rubli przy zapisaniu się na dowolny kurs Skillbox z użyciem kodu promocyjnego „Habra”.
Skillbox poleca: Edukacyjny kurs online .
DRY (Nie Powtarzaj Się)
Bardzo prosta zasada, której istota jest jasna z nazwy: „Nie powtarzaj się”. Dla programisty oznacza to konieczność unikania duplikującego kodu oraz możliwość wykorzystania abstrakcji w pracy.
Jeśli w kodzie znajdują się dwa powtarzające się fragmenty, należy je połączyć w jedną metodę. Jeśli ustalone na sztywno wartości są używane więcej niż jeden raz, warto przekształcić je w publiczną stałą.
To potrzebne, aby uprościć kod i ułatwić jego wsparcie, co jest głównym celem OOP. Jednak również nie należy nadużywać łączenia, ponieważ ten sam kod nie przejdzie walidacji ani dla OrderId, ani dla SSN.
Inkapsulacja zmian
Produkty oprogramowania wielu firm nieustannie się rozwijają. Oznacza to, że kod musi być modyfikowany, a jego wsparcie jest konieczne. Można sobie ułatwić życie dzięki inkapsulacji. Pozwoli to na skuteczniejsze testowanie i utrzymanie istniejącej bazy kodu. .
Jeśli piszesz w Javie, to .
Zasada otwartości/zamknięcia
Tę zasadę można łatwo zapamiętać, czytając następujące stwierdzenie: „Jednostki programowe (klasy, moduły, funkcje itp.) powinny być otwarte na rozszerzenie, ale zamknięte na zmiany”. W praktyce oznacza to, że mogą pozwalać na zmianę swojego zachowania bez modyfikacji kodu źródłowego.
Zasada jest ważna, gdy zmiany w kodzie źródłowym wymagają jego przeglądu, testowania jednostkowego i innych procedur. Kod, który przestrzega zasady otwartości/zamkniętości, nie zmienia się przy rozszerzaniu, dlatego wiąże się z nim znacznie mniej problemów.
Oto przykład kodu, który narusza tę zasadę.

Jeśli będzie wymagana jakakolwiek zmiana, zajmie to dużo czasu, ponieważ trzeba będzie zmienić wszystkie fragmenty kodu, które są powiązane z potrzebnym fragmentem.
Zresztą, otwartość-zamkniętość to jedna z zasad SOLID.
Zasada pojedynczej odpowiedzialności (SRP)
Kolejna zasada z zestawu SOLID. Twierdzi, że "istnieje tylko jeden powód, dla którego klasa powinna być zmieniana". Klasa rozwiązuje tylko jedno zadanie. Może mieć kilka metod, ale każda z nich służy tylko do rozwiązania ogólnego problemu. Wszystkie metody i właściwości powinny służyć tylko temu.

Wartość tej zasady polega na tym, że osłabia ona powiązania między poszczególnymi komponentami oprogramowania a kodem. Jeśli dodasz więcej niż jedną funkcjonalność do klasy, wprowadza to powiązanie między dwiema funkcjami. W ten sposób, jeśli zmienisz jedną z nich, istnieje duża szansa, że zepsujesz drugą, związaną z pierwszą. A to oznacza zwiększenie liczby cykli testowania, aby zidentyfikować wszystkie problemy z wyprzedzeniem.
Zasada inwersji zależności (DIP)

Powyżej jest przykład kodu, w którym AppManager zależy od EventLogWriter, który z kolei jest ściśle związany z AppManagerem. Jeśli potrzebny jest inny sposób wyświetlania powiadomień, czy to push, SMS, czy e-mail, należy zmienić klasę AppManager.
Problem można rozwiązać za pomocą DIP. Tak, zamiast AppManagera, żądamy EventLogWriter, który zostanie wprowadzony za pomocą frameworka.
DIP umożliwia bezproblemowe zastępowanie pojedynczych modułów innymi, zmieniając moduł zależności. To pozwala na modyfikację jednego modułu bez wpływania na pozostałe.
Kompozycja zamiast dziedziczenia
Podstawowe sposoby ponownego użycia kodu to dziedziczenie i kompozycja, z których każdy ma swoje zalety i wady. Zwykle preferuje się drugi, ponieważ jest bardziej elastyczny.
Kompozycja pozwala na zmianę zachowania klasy w czasie wykonywania poprzez ustawianie jej właściwości. Przy implementacji interfejsów wykorzystywany jest polimorfizm, co pozwala na bardziej elastyczną realizację.
Nawet "Effective Java" Joshuy Blocha zaleca preferowanie kompozycji zamiast dziedziczenia.
Zasada podstawienia Barbary Liskov (LSP)
Kolejna zasada z zestawu SOLID. Mówi ona, że podtypy powinny być wymienne dla nadtypów. Oznacza to, że metody i funkcje działające z nadklasą powinny móc działać bez problemu również z jej klasami pochodnymi.
LSP jest związana zarówno z zasadą pojedynczej odpowiedzialności, jak i zasadą podziału odpowiedzialności. Jeśli klasa zapewnia więcej funkcji niż jej podklasa, to ta ostatnia nie będzie wspierać niektórych funkcji, naruszając tę zasadę.
Oto fragment kodu, który narusza LSP.

Metoda area(Rectangle r) oblicza pole Rectangle. Program zakończy działanie po wykonaniu Square, ponieważ Square nie jest tutaj Rectangle. Zgodnie z zasadą LSP, funkcje, które używają odniesień do klas bazowych, powinny mieć możliwość korzystania także z obiektów klas pochodnych bez dodatkowych instrukcji.
Ta zasada, która jest specyficznym określeniem podtypu, została zaproponowana przez Barbarę Liskov w 1987 roku na konferencji w referacie głównym zatytułowanym „Abstrakcja danych i hierarchia” — stąd jej nazwa.
Zasada podziału interfejsu (ISP)
Kolejna zasada SOLID. Zgodnie z nią interfejs, który nie jest używany, nie powinien być realizowany. Przestrzeganie tej zasady pomaga systemowi pozostać elastycznym i odpowiednim do refaktoryzacji przy wprowadzaniu zmian w logice działania.
Najczęściej taka sytuacja występuje, gdy interfejs zawiera kilka funkcjonalności, z których klient potrzebuje tylko jedną.
Ponieważ napisanie interfejsu jest skomplikowanym zadaniem, po zakończeniu pracy jego zmiana, bez naruszania istniejącego kodu, może stanowić problem.
Zaletą zasady ISP w Javie jest to, że najpierw należy zaimplementować wszystkie metody, a dopiero potem mogą być one używane przez klasy. Dlatego zasada pozwala na zmniejszenie liczby metod.

Programowanie dla interfejsu, a nie implementacji
Tutaj wszystko jest jasne z nazwy. Zastosowanie tej zasady prowadzi do tworzenia elastycznego kodu, który będzie działał z każdą nową implementacją interfejsu.
Należy używać typu interfejsu dla zmiennych, typów zwracanych lub typu argumentu metody. Przykład — użycie SuperClass, a nie SubClass.
To znaczy:
List numbers = getNumbers();
A nie:
ArrayList numbers = getNumbers();
Oto praktyczna realizacja tego, o czym mowa powyżej.

Zasada delegacji
Powszechnym przykładem są metody equals() i hashCode() w Java. Gdy konieczne jest porównanie dwóch obiektów, akcja ta jest delegowana odpowiedniej klasie zamiast klienta.
Zaletą zasady jest brak duplikacji kodu i stosunkowo łatwa zmiana zachowania. Stosuje się ją również do delegacji zdarzeń.

Wszystkie te zasady pozwalają pisać bardziej elastyczny, estetyczny i niezawodny kod z wysoką spójnością i niskim sprzężeniem. Oczywiście, teoria jest dobra, ale aby programista naprawdę zaczął wykorzystywać zdobytą wiedzę, potrzebna jest praktyka. Następnym krokiem po opanowaniu zasad OOP może być nauka wzorców projektowych do rozwiązywania powszechnych problemów w rozwoju oprogramowania.
Skillbox poleca:
- Praktyczny kurs .
- Kurs online .
- Dwuletni praktyczny kurs .
Źródło: habr.com
