Kurs Java

SOLID

Ten skrót już od kilku lat robi furorę w internecie oraz...podczas rozmów kwalifikacyjnych. Faktycznie to bardzo ważne, aby trzymać się zasad, które opisuje ten akronim. Co więc oznacza SOLID? Nie jest to wzorzec projektowy sam w sobie. Akronim opisuje zbiór reguł, których powinniśmy się trzymać podczas tworzenia kodu. Rozbijamy go na poszczególne litery, które tłumaczymy z angielskiego tak:
  • S - Single responsibility principle - Zasada jednej odpowiedzialności

    Klasy powinny mieć ściśle określoną odpowiedzialność. Nigdy nie powinien istnieć więcej niż jeden powód modyfikacji klasy.

    Przykład

    W przypadku gdy klasa odpowiada za tworzenie obiektów na podstawie zadanego interfejsu (fabryka), nie powinna zajmować się niczym innym. Nie może nagle stać się miejscem aktualizacji danych, czy też wykonawcą innych zadań niezwiązanych z jej specjalizacją (jakim jest tworzenie obiektów danego interfejsu).
  • O - Open/closed principle - Zasada otwartości na rozszerzenie i zakmniętości na modyfikacje

    Kod powinien być tak napisany, by w przypadku rozwoju systemu i pojawiających się kolejnych wymagań biznesowych, nie trzeba było zmieniać istniejącego kodu. Ma on być otwarty na rozszerzanie i dodawanie nowych "klocków". Wymaganie to zmusza nas do dokładnego przemyślenia realizowanych zadań i wprowadzenia od początku na tyle ogólnych rozwiązań, by były one przygotowane pod dalszą rozbudowę.

    Przykład

    Implementując eksporter plików przygotowujemy metody, które będą abstrakcyjne i zapewnią możliwość wprowadzania kolejnych implementacji w postaci nowych klas w przyszłości. Każda taka klasa będzie dostarczać własną implementację eksportu. Inaczej będzie wyglądało wykonywanie eksportu do pliku csv, a inaczej do pliku xls, niemniej wszystkie eksporty będą posiadały ogólny zbiór podobnych zadań, takich jak pobranie danych, ich przetworzenie oraz eksport do pliku. Wspólne dla wszystkich będą pewne cechy, na przykład nazwa pliku, czy jego rozszerzenie.

    Nawet jeśli w pierwszej fazie projektu musimy przygotować eksport tylko do pliku csv, warto wprowadzić ogólny mechanizm eksportu, a implementacje metod dostarczyć w osobnych klasach. Jeśli nagle pojawi się wymaganie dodania eksportu xls, wówczas do wykonania pozostanie nam tylko przygotowanie klasy dedykowanej temu typowi eksportu. Nic nie zmieniamy w kontekście samego procesu (jego uruchomienia, obsługi błędów, czy obsługi zakończenia). Wszelkie zmiany nie mają również wpływu na kod eksportu csv (nie musimy go zmieniać).
  • L - Liskov substitution principle - Zasada podstawienia Liskova

    Tworząc kod powinniśmy go budować tak, aby zawsze działał zarówno dla samej klasy bazowej, jak i każdej implementacji.

    Przykład

    W przypadku wspomnianego eksportera możemy zrealizować nasz szczytny cel wydzielenia klasy bazowej, a następnie dostarczenia kolejnych implementacji eksportu w postaci niezależnych klas, ale jeśli nie stworzymy odpowiednio wartościowych metod operujących na każdej z klas eksportujących, wówczas i tak możemy nie spełnić zasady podstawienia.

    Na przykład jeśli w trakcie tworzenia klasy menedżera plików założymy, że będzie on działał dla każdej klasy rozszerzającej klasę bazową, ale jednocześnie w kodzie takiego menedżera wprowadzimy operacje specyficzne tylko dla plików xls, wtedy uruchomienie metody dla innych implementacji (na przykład dla pliku csv) nie zadziała lub wygeneruje błąd. I to znaczy, że nasz kod nie spełnia w tym miejscu zasady podstawienia Liskova.
  • I - Interface segregation principle - Zasada segregacji interfejsów

    Każdy interfejs powinien mieć wąski zakres specjalizacji. Dodatkowo powinny one być zwięzłe tematycznie, tak by maksymalnie ograniczyć występowanie pustych implementacji metod.

    Przykład

    Wprowdzamy do naszego eksportera interfejs przygotowujący raport zawierający prostą statystykę na temat wyeksportowanych elementów. Prawdopodobne wystarczy nam interfejs zawierający metody addReportData i createReport. Wtedy każdy eksporter implementując taki interfejs ma do dostarczenia zwięzłą listę metod. Nie ma tutaj metod nadmiarowych. Każda klasa zaimplementuje obie metody.

    Natomiast, gdybyśmy chcieli do takiego interfejsu dodać jeszcze metodę w stylu writeReportToFile, to mogłoby się okazać, że nie wszystkie klasy jej potrzebują. O ile każda z nich musi dostarczyć implementację tworzenia raportu, o tyle niektóre mogą na przykład "chcieć" zapisać wynik takiego raportu do bazy, albo wysłać taki raport za pomocą żądania REST. Wtedy metoda writeReportToFile pozostałaby pusta, a w samym interfejsie należałoby dodać metody w stylu writeReportToDB lub sendReportToExternalSource. Te metody byłyby jednak puste w przypadku klasy dostarczającej zapis do pliku.

    Takich problemów staramy sie unikać. Segregujemy interfejsy i tworzymy osobny interfejs, nawet z jedną metodą generyczną definiującą możliwe formy zapisu raportu - na przykład storeResults.
  • D - Dependency inversion principle - Zasada odwrócenia zależności

    Wysokopoziomowe moduły (bardziej abstrakcyjne) nie powinny zależeć od modułów niskopoziomowych (bardziej specjalizowanych). Innymi słowy, abstrakacja nie powinna zależeć od implementacji.

    Przykład

    Co to oznacza w przypadku naszego przykładu? Jeśli po skonstruowaniu klasy bazowej z metodą export dodamy kilka klas dziedziczących, implementujących tę metodę, to wszystkie operacje doszczegóławiające export (czyli konkretne wykonanie exportu) powinny się odbywać w klasach dedykowanych każdemu z typów pliku.

    Jeśli nagle zaczniemy wprowadzać w metodzie export w klasie bazowej kod w stylu instrukcji if sprawdzającej czy mamy do czynienia z implementacją typu XlsExport czy CsvExport i tam dodamy wykonanie operacji zależnej od typu klasy, wówczas abstrakcyjna klasa bazowa zacznie zależeć od implementacji i nasza zasada nie będzie spełniona.
Tak naprawdę wielu programistów - często nawet nie do końca świadomie - stosuje się zwykle do części z wymienionych zasad, niemniej ważne jest, aby stosować się do nich wszystkich. Wtedy kod będzie dobrej jakości i nie sprawi większych problemów kolejnym programistom, którzy będą go rozwijać w przyszłości. Tworzenie kodu w ten sposób jest oznaką profesjonalizmu i na pewno zostanie docenione przez innych członków zespołu.
Zdjęcie autora
Autor: Jarek Klimas
Data: 03 stycznia 2024
Labele: Backend, Podstawowy, Java

Stale się rozwijamy, a więc bądź na bieżąco!
Na ten adres będziemy przesyłać informacje o ważniejszych aktualizacjach, a także o nowych materiałach pojawiających się na stronie.
Polub nas na Facebooku:
Nasi partnerzy: stackshare
Javappa to również profesjonalne usługi programistyczne oparte o technologie JAVA. Jeśli chesz nawiązać z nami kontakt w celu uzyskania doradztwa bądź stworzenia aplikacji webowej powinieneś poznać nasze doświadczenia.
Kliknij O nas .


Pozycjonowanie stron: Grupa TENSE