SOLID – Zasada pojedynczej odpowiedzialności

Posted on by 0 comment

Jakiś czas temu pisałem ogólnie o praktykach w programowaniu, składających się na SOLID . Słowem wstępu przypomnę, że SOLID to zbiór pięciu dość luźno rozumianych reguł, które wspierają w tworzeniu wartościowych rozwiązań. Tutaj możecie przeczytać wspomniany artykuł.

SOLID - Zasada jednej odpowiedzialności

SOLID – Zasada jednej odpowiedzialności

Zasada pojedynczej odpowiedzialności

S – Single responsibility principle, czyli Zasada pojedynczej odpowiedzialności.

Jeśli można tak powiedzieć, to jest to jedna z podstawowych zasad w motywie SOLID. Choć jej założenia są bardzo oczywiste, to tak na prawdę stosowanie tej zasady nie jest trywialną umiejętnością, wymaga od programisty dobrego wyczucia i wysokiego stopnia samodyscypliny.

Ale zaraz, zaraz, o czym w zasadzie mówimy?

Tworząc interfejsy, klasy, czy nawet same metody, nadajemy im pewne wiodące przeznaczenie (z którego najczęściej wywodzi się ich nazwa).

Zasada jednej odpowiedzialności polega na umieszczaniu w interfejsie/klasie tylko takich funkcjonalności, które mają ścisłe połączenie, wpisują się w nurt przeznaczenia klasy/interfejsu. Np. tworząc klasę DziennikOcen, możemy umieścić w niej takie funkcjonalności jak: wpiszOcenę, poprawOcenę.

Załóżmy, że zbliża się wywiadówka i chcemy wydrukować karteczki z ocenami. Mogłoby się wydawać, że funkcja drukujRaportOcen pasowałaby idealnie do klasy Dziennika, ale nic z tych rzeczy, powinniśmy stworzyć dodatkową klasę do generowania raportów.

Wspomniałem także, że zasada pojedynczej odpowiedzialności odnosi się także do funkcji. Stosowanie jej w funkcjach jest podstawą do osiągnięcia czytelnego kodu. Mianowicie w hierarchii naszego systemu, wywołując metodę publiczną, poprzez łańcuch wywołań powinniśmy dotrzeć do najprostszej funkcji prywatnej, która będzie zwięzła, odpowiadała za prostą, najlepiej pojedynczą operację oraz w świecie idealnym, jej kod powinien być „wcięty”/zagnieżdżony 1/2 poziomy, czyli:

Powinno wyglądać to tak:

Przykład

Przedstawię teraz wyimaginowaną sytuację w kodzie. Dostaliśmy zlecenia oprogramowania komputera pokładowego najnowszego samochodu. Jesteśmy na etapie tworzenia oprogramowania dla silnika. Będąc dobrymi programistami zaczynamy od projektu interfejsu i mamy na uwadze praktykę SOLID, niech wygląda on tak:

Oczywiście zaimplementowaliśmy także klasę:

Pojawia się nam w głowie konieczność oprogramowania przekładni zmiany biegów, więc postanawiamy udostępnić funkcjonalności zmiany biegów w tym samym interfejsie:

Na pierwszy rzut oka wszystko do siebie pasuje. Silnik powiązany jest przecież ze zmianami biegów, ale było to działanie błędne, ponieważ spowodowaliśmy mnogość powodów, w których może wystąpić konieczność zmiany kodu należącego do jednej klasy (silnik, skrzynia biegów).

Jedna z wersji definicji zasady pojedynczej odpowiedzialności mówi, że powinien istnieć tylko jeden powód do zmiany klasy. Powinniśmy zatem stworzyć dodatkowy interfejs, definiujący skrzynie biegów i jego implementację:

Programowanie według tej praktyki, bardzo poprawia łatwość późniejszego utrzymania kodu i sam jego rozwój. Dzięki temu przeglądając oprogramowanie w późniejszym czasie, można z większą pewnością wnioskować o sposobie działania poszczególnych komponentów i uniknąć wielu zaskoczeń spowodowanych przez nieintuicyjne składników.

Trzymając się również tej zasady, niejako zmuszamy siebie do częstego tworzenia nowych komponentów, przez co automatycznie wystrzegamy się przed tworzeniem  „klas potworów” mieszczących się na kilku ekranach.

Podsumowanie

Myślę, że to wystarczy, nie ma co rozwlekać tak zwięzłego tematu. Chciałbym podkreślić, że wszystko wymaga doświadczenia i obycia. Idąc zasadą 10 000 godzin, żeby osiągnąć mistrzostwo w danym kierunku, potrzeba 10 000 godzin. Problem rodzi się, gdy przez 10 000 godzin robimy coś źle, wtedy osiągamy mistrzostwo w robieniu tego czegoś źle 🙂 Zapraszam do innych artykułów, w których pisze o innych składnikach składających się na SOLID.

Dodaj komentarz