Zasady programowania SOLID, KISS, DRY : Pocałuj mnie na sucho, aczkolwiek solidnie, czyli wszystkie te akronimy.

Jeszcze jeden skrótowiec…

Uważasz, że Twój kod jest całkiem solidny, bo starasz się zawsze utrzymać go w czytelnej formie, dokładnie testujesz jego działanie, dbasz o jego wydajność? To nie znaczy, że stosujesz zasady programowania SOLID. Czytelny kod nie zawsze też będzie KISS, ale być może YAGNI, bo to tylko YAA. Nic z tego nie zrozumiałeś? Więc zapraszam do dalszej lektury wpisu.

Solidnie pracuj nad zasadami.

Wśród architektów, programistów i inżynierów krąży mnóstwo zasad dotyczących projektowania i inżynierii oprogramowania. Trzymając się tematyki dzisiejszego wpisu możemy je umieścić w skali od użytecznych do YAA – Yet Another Acronym, czyli w wolnym tłumaczeniu Znowu Kolejny Skrótowiec. Najmocniejszą pozycję w zbiorze zasad dotyczących programowania obiektowego ma jednak SOLID, który możemy rozwinąć na kolejne skróty:

  • S – SRP – Single Responsibility Principle – Zasada pojedynczej odpowiedzialności
  • O – OCP – Open/Closed Principle – Zasada „otwarty/zamknięty”
  • L – LSP – Liskov Substition Principle – Zasada podstawienia Liskowej (tak, Liskov jest kobietą)
  • I – ISP – Interface Segregation Principle – Zasada sekregacji interfejsów
  • D – DIP – Dependency Inversion Principle – Zasada odwrócenia zależności/odpowiedzialności (nie mylić z Dependency Injection)

Każdy zasługuje na osobny artykuł, co być może uda mi się osiągnąć w najbliższym czasie, ale póki co uchylmy tylko rąbka tajemnicy.

Jedna odpowiedzialność

Literka S, którą rozwijamy do zasady pojedynczej odpowiedzialności właściwie łatwo wyjaśnia się sama dzięki temu rozwinięciu. Według tej zasady każda klasa, metoda czy moduł naszego programu powinna mieć jedną odpowiedzialność, a bardziej formalnie: zawsze powinien istnieć jeden powód do jej modyfikacji. Zwiększa to ilość klas w projekcie, ale zmniejsza ilość klas typu „swiss knife”, czyli ogromnych klas wykonujących ogrom różnorodnych czynności. Najprostszym przykładem złamania zasady może być np. klasa użytkownika, która zawiera pola takie jak login, email, ale również metodę walidującą email, która nie powinna się tam znaleźć – przecież nie powinno być odpowiedzialnością obiektu użytkownika walidowanie własnego emaila.

Zamknij / otwórz

Pod literką O kryje się otwartość klasy (jak również modułu/funkcji) na rozszerzanie, ale jej zamknięcie na modyfikację. W momencie, kiedy zmienią się wymagania np. biznesowe, powinniśmy mieć możliwość dostosowania się do nich poprzez dodanie nowego kodu rozszerzającego zachowanie klasy, zamiast zmieniania starego, działającego.

Podstawienie Liskowej

Litera L pochodzi od nazwiska kobiety, która sformułowało tę zasadę – Barbara Liskov (nazwisko nieodmieniane, bo wbrew pozorom pochodzi z USA) twierdzi, że korzystanie z funkcji klasy bazowej musi być możliwe również z poziomu instancji jej klasy pochodnej. Klasę niższą w hierarchii dziedziczenia powinniśmy mieć możliwość podstawić wszędzie, gdzie oczekiwana jest jej klasa bazowa. Brzmi to bardzo skomplikowanie i faktycznie ta zasada jest chyba najtrudniejsza do zrozumienia z całego zestawu SOLID.

Tłumacząc to „na polski” przy użyciu przykładu: mając klasę Pracownik i bardziej wyspecjalizowaną klasę Manager – w każdym miejscu, gdzie oczekiwany jest Pracownik, powinniśmy mieć możliwość użyć instancji Managera – może to nie do końca działać zgodnie z logiką, ale powinno działać. Łamaniem tej zasady byłoby przede wszystkim, gdyby klasa bazowa wiedziała o swoich podtypach, tzn. w klasie Pracownik mielibyśmy instrukcje typu „jeśli jestem managerem to zrób tak, w przeciwnym wypadku inaczej”. Łamie to zresztą cały zestaw SOLID i jest po prostu nierozsądne. Inny przykład – pomarańcza powinna zachowywać się jak pomarańcza, nawet jeśli jest niebieska – w przeciwnym wypadku nie nazywajmy tego niebieską pomarańczą!

Segregacja Interfejsów

I jak Interfejs, mówi o zależnościach, i w pewnym sensie można tę zasadę nazwać odwrotnością zasady Liskovej. Mianowicie mówi ona, że klienci usług nie powinni zależeć od interfejsów, których nie używają, tzn. interfejsy powinny być rozbite na fragmenty, które są wykorzystywane w całości. Kontynuując motyw Pracownika, ale tym razem w kontekście interfejsów: mając interfejs Pracownik i rozszerzający go interfejs Specjalista – wykonując operacje na Pracownikach powinniśmy przekazywać interfejs Pracownika, a nie szerszy interfejs Specjalisty. A jeśli pomyślisz, że chciałbyś może później jednak wykorzystać możliwości specjalisty, to… no cóż, YAGNI, głuptasie!

Odwrócenie zależności

Last but not least, zostało nam D jak Dependency Inversion. Zgodnie z tą zasadą moduły wysokopoziomowe nie powinny zależeć od modułów niskopoziomowych – ich zależność powinna wynikać bezpośrednio z abstrakcji. Umożliwia to uzależnienie od interfejsu, a nie od konkretnej implementacji – możemy wstrzyknąć różną implementację interfejsu. Czyli mówiąc w skrócie, Czytelniku drogi, używaj interfejsów gdzie to możliwe, a unikaj podawania konkretnej implementacji.

Nie powtarzaj się, a unikniesz powodzi problemów

Zasady programowania - DRY

Inną prostą zasadą, a wnoszącą naprawdę wiele do jakości tworzonego przez Ciebie kodu jest DRY. Rozwijamy to jako Don’t Repeat Yourself, czyli po prostu – Nie Powtarzaj Się. Solidny programista żyjący w świecie programowania obiektowego powinien nawet podświadomie starać się zawsze dopasować do tej zasady. Przecież po to mamy ten paradygmat programowania – żeby niepotrzebnie nie powtarzać kodu. Nie odnosi się to jednak tylko do samego pisania kodu – tak samo możemy odnieść to np. do procesu kompilacji (jeśli wymaga powtarzalnych czynności). Reguła pozwala na takie powtarzalne czynności, o ile są one zautomatyzowane przez komputer. Jeśli natomiast o sam kod chodzi, najczęstszą metodą unikania powtórzeń są funkcje/metody – powtarzany fragment kodu możemy wydzielić do funkcji, a następnie wywołać ją z praktycznie dowolnego miejsca wiele razy. Podobnie zaleca się wykorzystywać stałe zamiast tzw. magicznych stringów/liczb w kodzie, co również podnosi czytelność kodu dzięki nazwaniu wykorzystywanych wartości.

Zaletami stosowania DRY jest również oszczędność czasu (nie musimy powielać kodu wiele razy, a jedynie wywołać istniejący) i łatwiejsza obsługa błędów w kodzie (w przypadku błędu w powtórzonym fragmencie musimy wprowadzić zmiany w każdym jego wystąpieniu,w przypadku np. błędu w wywoływanej metodzie – tylko raz w ciele tej metody). DRY wymusza przy tym takie projektowanie interfejsów, żeby było jak najbardziej uniwersalne, prowadząc do powstania kodu, który jest bardziej reusable. Tak niewiele wysiłku, a tak wiele korzyści!

Pocałuj mnie, głuptasie!

Zasady programowania - KISS

Najbardziej słodki ze wszystkich technicznych skrótowców – KISS rozwijamy najczęściej jako Keep It Simple, Silly (dosłownie Nie Komplikuj, Głuptasku). Akronim doczekał się nawet polskiej wersji, równie urzekającej jak oryginał – BUZI, czyli Bez Udziwnień Zapisu, Idioto. Mimo lekko pejoratywnego brzmienia polskiego rozwinięcia oryginalnego skrótu, jego znaczenie jest jak najbardziej optymistyczne – reguła stworzona w kontekście projektowania samolotów znajduje zastosowanie również w programowaniu. Pohamuj więc, Czytelniku, chęć zaimponowania innym poprzez to jakimi skomplikowanymi strukturami potrafisz się posłużyć, a przysłużysz się przyszłemu sobie kiedy będziesz musiał utrzymywać kod, który piszesz. Ułatwia to również pracę w zespołach programistów, gdzie wykorzystanie najprostszej wersji działającego kodu ułatwia jego zrozumienie przez osoby inne, niż jego twórca. Zasada bezpośrednio związana jest z tą opisywaną powyżej (jedna prowadzi do drugiej), jak i poniżej.

Jagnię beczy, ale Ty nie musisz

Rozwinięcie skrótu YAGNI brzmi bardzo nowojorsko, szczególnie w często używanej wersji You Ain’t Gonna Need It. Skoro tego nie potrzebujesz w tym momencie, to prawdopodobnie nie będziesz tego potrzebował wcale. Nie dodawaj więc, Czytelniku, zbędnych funkcjonalności do swojego kodu, dopóki nie staną się niezbędne. Nie tylko możesz stracić czas swój, ale również programistów, którzy będą czytali ten kod po Tobie. Stosowanie YAGNI niewątpliwie przyczynia się do utrzymania KISS, co z kolei ułatwia też stosowanie DRY…

Czuj, czuj, czuwaj… nad jakością kodu

… co udowadnia nam, że nie musimy trzymać nad biurkiem przyklejonej listy wszystkich zasad tworzenia dobrego kodu, aby nasz kod taki był. Wystarczy, że zapamiętamy najprostsze reguły, które staną się filarami naszej filozofii tworzenia oprogramowania, a jakość kodu powinna się zwiększyć. Parafrazując słynne skautowskie/harcerskie powiedzonko – zawsze zostaw kod trochę lepszy, niż go zastałeś. Jeśli zauważysz, że coś jest zbyt skomplikowane, wprowadza niepotrzebne powtórzenia czy niepotrzebnie psuje architekturę całego rozwiązania – pochyl się nad tym na moment, a być może zaoszczędzisz w przyszłości pięć razy tyle, ile teraz poświęciłeś na to czasu. W końcu Value Added Work to najczęściej tylko 10% naszego czasu, a resztę poświęcamy na czytanie… ale o tym już kiedy indziej 🙂

1 thought on “Zasady programowania SOLID, KISS, DRY : Pocałuj mnie na sucho, aczkolwiek solidnie, czyli wszystkie te akronimy.”

Leave a Comment

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