Jeden prosty krok do SOLIDnego kodu - Klasy final w PHP

Słowo kluczowe `final`

Zastosowanie final w klasie, uniemożliwia zastosowanie dziedziczenia względem niej. Także może się wydawać że blokujemy rozszerzalność takiej klasy i zamykamy się na korzyści płynące z mechanizmu polimorfizmu. Ale czy na pewno?

Moim zdaniem `final class` to wspaniałe narzędzie wspierające SOLIDa, chociaż wymaga bardzo dużo samo zaparcia i warto mieć na uwadze że SOLID to tylko zestaw reguł, które można, ale nie trzeba wykorzystywać.

Zobaczmy więc co zyskujemy dzięki stosowaniu słowa `final`.


Liskov Subtition Principle

Zależnie od tego jak spojrzymy na tę regułę zyskujemy w obydwu przypadkach.

W "oryginalnej" regule Liskov, zastosowanie `final` zablokuje możliwości dziedziczenia takiej klasy, a więc całkowicie wyeliminuje potencjalny problem niepoprawnego dziedziczenia klas bazowych, które gdzieś w środku mógłby wpłynąć na poprawność działania aplikacji. Wystarczy przypomnieć sobie przykład z kołem i elipsą.

Natomiast Martin rozszerza tę regułę o koncept Design By Contract Bertranda Mayer, którą to można sprowadzić do:
"Klasa pochodna nie wymaga więcej i nie dostarcza mniej niż klasa bazowa" 

>Jak więc dodać funkcjonalności do klas gdy zablokowaliśmy sobie dziedziczenie?

 
Bez dziedziczenia jesteśmy zmuszeni do skorzystania z metod wspierających  "Kompozycje ponad dziedziczenie". Zwróć uwagę chociażby na wzorzec Dekoratora.

Utworzenie kompozycji klas. Sprowadzi się to do tego, że kontrakt każdej klasy w kompozycji zostanie zachowany, ponieważ kod tych klas nie został zmodyfikowany, ani w pliku klasy, ani poprzez użycie dziedziczenia i być może niepoprawnego nadpisania metody.

 

Interface Segregation Principle

Nic nie wymusi interfejsów bardziej niż klasa `final`.

Przestają w kodzie istnieć klasy które dziedziczą po czymś, i jeszcze dawały namiastkę tego że ten kod jest rozszerzalny w jakiś sposób. Ponieważ pozbyliśmy się tego mechanizmu. Chcąc nie łamać zasad OCP i DIP, jesteśmy zmuszeni skorzystać z interfejsów.

To pozwoli nawiązać wewnętrzny dialog, który mógłby wyglądać tak. Skoro nie przekaże tu całej klasy (bo złamię DIP), to w sumie jakich metod tej klasy potrzebuję, by stworzyć interfejs specyficzny dla tego typu klienta.

 

Dependency Inversion Principle

Już miałem okazję wspomnieć o tej zasadzie w tym artykule. Jak to w SOLIDzie bywa, łamiąc jedną zasadę, najprawdopodobniej łamiemy wszystkie inne.

Zgodnie z DIP powinniśmy wychodzić z założenia że każdy konkret jest ulotny i z tego powodu powinniśmy stawiać na zależności do abstrakcji. Klasy final wymusiły interfejsy, także zależność od abstrakcji jest na wyciągnięcie ręki.


Open Closed Principle

Chcąc uniknąć powiązania naszego kodu z konkretna implementacją, skorzystamy z technik dynamicznego polimorfizmu, czyli... tak znowu interfejsy.


Single Resposibility Principle

Tutaj chciałbym się dowiedzieć co Ty sądzisz o wpływie `final` na tę regułę. Specjalnie więc "zamilknę" i przejdzę do podsumowania.


Czy to sposób na SOLID w projekcie?

Stawiając na klasy final, mam wrażenie że faktycznie dostajemy sporego boosta do SOLIDa w naszym kodzie. Co sądzisz o takim podjeściu? Jestem tez ciekaw co sądzisz o wpływie na SRP.

Jeżeli uznałeś artykuł za ciekawy podziel się z innymi :)

Komentarze

Prześlij komentarz

Popularne posty z tego bloga

Dlaczego warto stosować wzorzec dekorator

Najważniejsza książka programisty - Mistrz Czystego Kodu