Single Responsibility Principle – SRP

Zasada pojedynczej odpowiedzialności

Zasada pojedynczej odpowiedzialności jest jedną z najprostszych zasad SOLID.
Robert C. Martin, czyli Wujek Bob jak już wspominałem wcześniej jest odpowiedzialny za jej wymyślenie, a jej definicja, jest następująca.

Każdy moduł oprogramowania powinien mieć jeden
i tylko jeden powód do zmiany.

Oznacza to, że nasze klasy czy metody powinny posiadać tylko jedną odpowiedzialność. Nie powinien istnieć więcej niż jeden powód abyśmy chcieli zmodyfikować naszą klasę. Nie możemy tworzyć fabryki, która produkuje wszystko statki, rowery, samochody i jednocześnie szyje spodnie. Każda klasa powinna być odpowiedzialna za jedną rzecz. Klasa Zamówienie powinna zawierać tylko i wyłącznie metody związane z zamówieniem. Nie powinna zawierać na przykład metod związanych z logowaniem błędów, tworzeniem statystyk itp.

A więc jeśli jedna klasa wykonuje jednocześnie obliczenia oraz wyświetla wyniki obliczeń nie spełnia zasady SRP. Odpowiada za dwie rzeczy a więc mogą wystąpić 2 powody do zmian. Mogą się zmienić zasady obliczania lub sposób wyświetlania wyników. A zasada pojedynczej odpowiedzialności nakazuje oddzielenie części obliczeń od części wyświetlania wyników. Obie funkcjonalności powinny być zaimplementowane w dwóch osobnych klasach, które komunikują się między sobą za pomocą publicznych interfejsów.

Z doświadczenia wynika, że jeżeli jakaś klasa jest odpowiedzialna za więcej niż jedną rzecz naszego projektu to jest to bardzo niekorzystne. Może się przecież zdarzyć tak, że modyfikując jedną rzecz mimowolnie wpłyniemy na zupełnie inną rzecz w naszym kodzie, która nie jest w żaden sposób związana z pierwszą. Dodatkowo, każdy taki związek wpływa negatywnie na cały projekt poprzez zmniejszenie jego elastyczności, a co za tym idzie prowadzi do nieoczekiwanych rezultatów wprowadzanych przez nas zmian.

Stosując tę zasadę unikamy problemów z pojedynczymi klasami, które są niczym szwajcarski scyzoryk. Mając do dyspozycji wiele obiektów zwiększamy czytelność naszego kodu i ułatwiamy zarządzanie kodem naszej aplikacji.

Czyli nasze Klasy powinny obejmować wykonywanie określonego pojedynczego zadania w określony sposób. Kiedy klasy mają jeden cel, to zwykle doskonale nadaje się do tego celu i są łatwe w użyciu. Klasy mogą delegować określone zadanie do innej klasy, która hermetyzuje wykonywanie tego zadania.

A Kiedy nasze klasy robią zbyt wiele rzeczy, łącząc te rzeczy ze sobą, które nie powinny być ze sobą powiązane, to często kończą się to tym że taka ogólna klasa będzie znacznie trudniejsza w użyciu. I taka próba udostępnienie narzędzia ogólnego przeznaczenia powoduje dodatkową złożoność, której nie wymagałoby narzędzie do jednego celu.

Podam tutaj jeszcze jeden przykład. Powiedzmy że nasza aplikacja a może tylko jedna klasa będzie miała do czynienia z przechowywaniem danych.

To czy używa do tego celu plików czy bazy danych?
A co z logowaniem w naszej aplikacji?
Czy jest używany do tego jakiś konkretny framework czy coś innego?

I Wszystkie te rzeczy mogą zawierać reguły biznesowe, które faktycznie definiują sposób działania systemu. I Zasada pojedynczej odpowiedzialności sugeruje, że moduły powinny mieć tylko jeden powód do zmiany. Być może każda z tych decyzji będzie musiała być ponownie oszacowana, rozpatrzona, zmodyfikowana w przyszłości. Na przykład przechowywanie danych może wymagać zmiany z plików na bazę danych. Początkowy wybór logowania może okazać się niewystarczające i może być konieczne dodanie nowego sposobu logowania albo zmiana tego sposobu.

I Obowiązki w Naszym kodzie reprezentują rzeczy, które mogą ulec zmianie w różnym czasie i z różnych powodów. Potencjalne źródło zmian w naszej aplikacji może pomóc nam określić, kiedy możemy naruszać Zasadę pojedynczej odpowiedzialności.

Nawet jeśli pracujemy w małej firmie czy nad własnym domowym projektem, możemy pomyśleć o żądaniach zmian które pochodzą od różnych kierowników w dużej firmie. Na przykład kierownik ds. Informatyki może wymagać zmiany dostawców baz danych w całej firmie. Kierownik ochrony może wymagać zainstalowania bardziej niezawodnej struktury logowania, aby ułatwić wykrywanie i ochronę przed atakującymi.

Zasada pojedynczej odpowiedzialności jest ściśle związana z koncepcją sprzężenia.

I Gdy mamy dwa lub więcej szczegółów zmieszczonych w tej samej klasie, to wprowadza to ścisłe sprzężenie między tymi szczegółami. I Jeśli te szczegóły zmienią się w różnym czasie z różnych powodów, to prawdopodobnie spowoduje to w przyszłości problemy z zmianą kodu w klasie.

Luźne sprzężenie odnosi się do podejścia, które można wykorzystać do obsługi różnych szczegółów a aplikacja współdziała ze sobą w sposób modułowy. Zwykle jedna klasa będzie odpowiedzialna za rzeczy wyższego poziomu i będzie delegować inne rzeczy do innych klas, które są odpowiedzialne za szczegóły, jak wykonać operacje na niższym poziomie.

I Wynika to z innej zasady, oddzielenia obowiazków (separation of concerns). Rozdzielenie obowiązków sugeruje, że programy powinny być podzielone na odrębne sekcje, z których każda dotyczy odrębnego problemu lub zestawu informacji, które mają wpływ na program. I Kluczowa korzyść z separacji obowiązków dotyczą tego, że logika biznesowa wysokiego poziomu pozwala uniknąć konieczności zajmowania się kodem niskiego poziomu.

I idealnie było by gdyby kod, na wysokim poziomie nie wiedział, jak wdrażane są szczegóły implementacji niskiego poziomu, ani nie powinien być ściśle połączony z konkretnymi szczegółami.

Inne pojęcie ściśle związane ze sprzężeniem jest spójność.

Spójność opisuje, jak ściśle powiązane są elementy, klasa lub moduł są ze sobą. Klasy, które mają wiele obowiązków, będą miały mniejszą spójność niż klasy, które mają jedną odpowiedzialność.

Dobrze wystarczy już tych rozważań teoretycznych tego nudzenia i przejdźmy do praktycznego zastosowanie a wszystko stanie się jasne i proste, a najlepszy jest praktyczny, życiowy przykład, który będzie w kolejnym wpisie :).

13 comments

  1. Hej,
    Dzięki za dobrypost! W czasach kiedy byłem jeszcze juniorem było mi ciężko wyrobić sobie intuicję co do sformułowania „Robi jedną rzecz”, bo przecież przetwarzanie wiadomości albo edycja profilu użytkownika to w końcu jedna rzecz, prawda? Z pomocą przyszła mi definicja „Istnieje tylko jeden powód do zmiany w klasie”. Zatem widać, że zmiana w dwóch różnych obszarach aplikacji generuje zmianę w tej samej klasie. Zatem naruszyliśmy tutaj SRP.
    Pozdrawiam,
    Henryk

    1. Dziękuje za komentarz i miłe słowa, dziękuje 🙂

  2. To wspaniały artykuł! Dziękuje za podzielenie się swoimi doświadczeniami i przemyśleniami !!!

    1. Dziękuje za komentarz i miłe słowa, dziękuje bardzo 🙂

    1. Dziękuje za komentarz i miłe słowa, dziękuje 🙂

  3. To jeden z najlepszych artykułów, jakie czytałem od dłuższego czasu. Temat pojedynczej odpowiedzialności jest zawsze interesujący i ciekawy. To wspaniały temat do pisania. Dobra robota!

    1. Dziękuje za komentarz i miłe słowa, dziękuje 🙂

  4. Świetny artykuł. Uwielbiałem zagadnienia dotyczące projektowania oprogramowania, najlepszy artykuł opisujący „pojedynczą odpowiedzialność”

    1. Dziękuje za komentarz i miłe słowa, dziękuje

    1. Dziękuje za komentarz i miłe słowa, dziękuje

  5. Pingback: Jak Zastosować 5 Zasad SOLID ? – DEV – HOBBY

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *