Code Smells: Błędnie rozumiana odpowiedzialność klas

odpowiedzialność

Dzisiejszy wpis będzie wyjątkowo o dwóch code smellsach, które łączy wspólny mianownik – źle rozumiany zakres odpowiedzialności klasy.

Rozbieżna zmiana

Pierwszy – Rozbieżna zmiana – objawia się niezgodnością klasy z pierwszą zasadą SOLID czyli zasadą pojedynczej odpowiedzialności, którą można przedstawić tak: “Wszystkie zmiany w danej klasie powinny wynikać tylko z jednego powodu”. W kodzie, w którym występuje “Rozbieżna Zmiana” modyfikacje klasy występują często i z różnych przyczyn. Zazwyczaj nie wystarcza też zmiana w jednej metodzie, a w kilku – to jeden z łatwiej zauważalnych symptomów tego problemu. Jednym słowem klasa ma wiele odpowiedzialności. Jak sobie radzić z tym problemem? Nietrudno się domyślić, że kluczem będzie rozdzielenie zadań, którymi zajmuje się klasa czyli tzw. ekstrakcja klasy. Polega to na wydzieleniu odpowiedzialności (czyli zazwyczaj tego kodu który jest modyfikowany przy zmianach) do osobnej klasy. Po tej operacji kod naszej klasy powinien być już ukierunkowany na spełnianie SRP.

Chirurgia strzelbą

W tym miejscu dochodzimy do drugiego problemu czyli, jak pozwoliłem sobie przetłumaczyć nazwę “Shotgun Surgery”, do Chirurgii Strzelbą (u Fowlera tlumacz przetłumaczył to na “Falę uderzeniową”). Zasada pojedynczej odpowiedzialności może się wydawać jedną z najprostszych reguł projektowania zorientowanego obiektowo. Wymaga jednak pewnej intuicji bo nie trudno jest przesadzić z jej stosowaniem. Jeżeli w naszym kodzie zauważamy, że wprowadzając modyfikację jednej funkcjonalności jesteśmy zmuszeni zmieniać kod znajdujący się w wielu klasach to znaczy, że mamy do czynienia z Shothun Surgery. Od strony projektu wygląda to tak, że jedna odpowiedzialność jest rozbita na wiele klas. Innymi słowy kilka klas jest współodpowiedzialne za określone działanie, które powinno być zamknięte w jednej klasie. Co możemy zrobić jeżeli już zostaniemy dotknięci tą przypadłością? Na samym początku warto się zastanowić czy na pewno potrzebujemy wszystkich klas, które musieliśmy modyfikować podczas implementacji zmiany. Jeżeli (a wydaje mi się że taki przypadek występuje dosyć często) okaże się że nie, to powinniśmy przenieść funkcjonalność którą zapewniają do innej klasy (tzw. wchłonięcie klasy). W przeciwnym wypadku również przenosimy, zwracamy uwagę które składowe ulegają modyfikacją i przenosimy tylko je.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *