Menu Zamknij

SOLID: Zasada pojedynczej odpowiedzialności

zasada pojedynczej odpowiedzialności

Co mówi nam zasada pojedynczej odpowiedzialności?

Każda klasa powinna mieć tylko jedną odpowiedzialność, a ta odpowiedzialność powinna być w całości hermetyzowana przez klasę.

Nigdy nie powinno być więcej niż jednego powodu, aby modyfikować daną klasę.

Co to jest odpowiedzialność?

Odpowiedzialność to ściśle określony kontekst działania na konkretnym poziomie abstrakcji.

Niektórzy uważają, że odpowiedzialność sprowadza się do tworzenia jednej metody publicznej w klasie. To nie prawda, odpowiedzialność jest szerszym pojęciem. Wiele publicznych metod może się składać na jedną odpowiedzialność.

Odpowiedzialność, nie wynika bezpośrednio z kodu. Wynika ze specyfiki systemu, rozwiązywanych w nim problemów. Powinniśmy starać się łączyć te elementy, które będą się zmieniać razem, a separować te, których zmiany mogą wynikać z odmiennych przyczyn. Dobre uchwycenie kontekstu, w jakim funkcjonuje klasa i umiejscowienie w niej tylko metod zgodnych z jej przeznaczeniem, to klucz do sukcesu. Gdy, nadejdą zmiany, to również będą odnosiły się do któregoś z wielu kontekstów funkcjonowania systemu.

Ta sama klasa w wielu procesach

Jeżeli klasa bierze udział w większej ilości procesów, to istnieje duże prawdopodobieństwo, że zawiera dwie grupy metod realizujące zadania, które nie są ze sobą spójne i realizują całkowicie odmienne cele przy użyciu tych samych danych.

Można wtedy rozbić, klasę na dwie i zapewnić, mechanizmy konwersji między typami. Ewentualnie można wydzielić dane do osobnej struktury i opakowywać ją klasą z zachowaniami dla danego procesu.

Dane w klasie wynikają z zachowania, nie na odwrót

Jeżeli otoczenie wyznacza dla klasy zadania ze względu na zawarte w nim dane. To klasa taka może obfitować w wiele metod które, na nich operują, jednak w różnych kontekstach i poziomach abstrakcji. Metody typu wylicz, serializuj, wypisz, narysuj, wydrukuj, mogą realizować całkowicie odmienne cele przy użyciu tych samych danych.

Istotne powinny być tylko zachowania i ich następstwa. Zachowania powinny zaś reprezentować wspólny cel i jednolity poziom abstrakcji.

Wewnętrzne dane obiektu powinny być tajemnicą, nieistotnym szczegółem.  Jeżeli, obiekt będzie udostępniał swoje wewnętrzne dane na lewo i prawo, zacznie być wykorzystywany do innych zadań, niż wynikają z jego przeznaczenia. A wtedy, jakaś drobna zmiana dotycząca sposobu przechowywania tych danych może wywołać lawinę poprawek w całym systemie.

Nic nieznaczące szczegóły

Często w klasie jest umieszczona implementacja, która nie ma znaczenia dla bieżącego poziomu abstrakcji. Nie wnosi to żadnej przydatnej informacji, a wręcz przeciwnie zmniejsza czytelność kodu.

Może się też okazać, że kod ten powtarza się w innych klasach, ponieważ realizowane przez niego zadania, są na innym poziomie abstrakcji. Informacja o tym, w jaki sposób jest to zaimplementowane, może niepotrzebnie odwracać naszą uwagę od prawdziwych intencji tej klasy. Taką implementację powinno się wyodrębnić do osobnej klasy, a następnie delegować do niej zadania nadrzędnego poziomu abstrakcji.

Funkcjonowanie obiektu na wielu poziomach abstrakcji

Istnieje jednak taka możliwość, że z jakimś obiektem będziemy musieli pracować na różnych poziomach abstrakcji. Wtedy możemy się zdecydować na rozdzielenie klasy, na kilka zgodnie z poziomami abstrakcji i dziedziczenie metod. W takich przypadkach  warto jednak dobrze się zastanowić, czy agregacja nie byłaby lepszym rozwiązaniem problemu.

Zależności, a odpowiedzialność – Wskazówki w kodzie

Dobrym sposobem może być wyrysowanie na kartce pól i metod używanych w klasie i połączenie ich strzałkami wg zależności. Taki eksperyment, powinien wykazać grupy najbardziej powiązanych obiektów. To właśnie w tych grupach powinno się szukać odpowiedzialności.

zasada pojedynczej odpowiedzialności

Jakie są korzyści?

Stosowanie zasady pojedynczej odpowiedzialności, powoduje w projekcie wysoką hermetyzację danych i metod, a hermetyzacja jak wiemy leży u podstaw obiektowego paradygmatu programowania.

Spowoduje również, powstanie większej ilości klas, ale to nie powinno budzić, żadnych obaw, ponieważ klasy te będą posiadać prostą implementację, która powinna jasno określać, czym się zajmują.

zasada pojedynczej odpowiedzialności

Zasada pojedynczej odpowiedzialności daje nam również, większe szanse na re-używalność naszego kodu. Obiekty tych klas mogą przydać się do wykonywania tych samych obowiązków wynikających z ich specjalizacji równie dobrze w innych miejscu naszego projektu.

Kierowanie się tą zasadą chroni nas przed tworzeniem, tzw. klas-potworów, boskich obiektów, zajmującymi się wszystkim, klas z tysiącami linii proceduralnego bełkotu z bełkotliwymi komentarzami.

Tego po prostu nie chcemy. Praca z takim kodem powoduje, że czujemy się przytłoczeni, że trudno nam wstać rano do pracy, nasze ideały giną, a wypalenie zawodowe kładzie na nas swoje widmo. Tak więc dla dobra swojego i innych, warto stosować  tę zasadę.

Please follow and like us:
Skuteczna refaktoryzacja w 10 krokach!

Odbierz Darmowy Poradnik o Refaktoryzacji!

Poznaj kilka prostych technik i wprowadź nową jakość w swoim projekcie.

Dzięki za dołączenie do mojej listy.

Coś poszło nie tak :( Spróbuj jeszcze raz.