Menu Zamknij

SOLID: Zasada otwarte zamknięte

Zasada otwarte zamknięte, to zasada, która powinna zmienić nasze myślenie o wprowadzaniu do systemu nowych reguł i zachowań.

Elementy systemu takie, jak klasy, moduły, funkcji itd. powinny być otwarte na rozszerzenie, ale zamknięte na modyfikacje.

Pisz raz, nie zmieniaj nigdy!

Zasada otwarte zamknięte

Każdy pewnie przerabiał taki scenariusz. Nowa funkcjonalność. Szukamy miejsca, gdzie, można się wpiąć z naszą logiką. Dodajemy if. Trochę kodowania i wszystko śmiga. Po pewnym czasie okazuje się, że w klasie jest mnóstwo zagnieżdżonych warunków logicznych, z dodatkowymi flagami, które nic nam nie mówią. Przed tym właśnie uchroni nas zasada otwarte zamknięte, znanej też jako open/closed principle .

Ifologia jest szybka, ale na krótką metę

Jeżeli, przyjmiemy długofalową strategię dodawania nowych reguł i zachowań, poprzez sterowanie warunkami logicznymi, to projekt naszego systemu szybko ulegnie degradacji, a realizowanie w nim kolejnych wymagań będzie coraz trudniejsze. Zamiast dobrego design’u będziemy mieć spaghetti code. A w projekcie gdzie wszystko jest powiązane ze wszystkim, łatwo zepsuć coś, co nie ma nic wspólnego z bieżącymi pracami.

Co zamiast if?

Jeżeli zachowanie może być odmienne, to należy je wyabstrahować do osobnego interfejsu. Wtedy wprowadzenie nowych reguł, które zmieniają to zachowanie, wymagać  będzie tylko implementacji w nowym kodzie. W ten sposób inne fragmenty kodu pozostaną nienaruszone.

Zasada otwarte zamknięte

Co jest przyczyną? Co jest typem?

Jeżeli chodzi o sposób wyabstrahowania odmiennych zachowań, to należy zastanowić się, co jest przyczyną tej odmienności, z czym związane są te różnice. Czy przyczyną są przetwarzane parametry, czy specyfika obiektu który, je przetwarza.

zależności od tego, który element jest „winny”, możemy spróbować poddać jego zachowanie polimorfizmowi.

To nie własność obiektu, to typ obiektu

Przykładowo, jeżeli obiekt wywołuje różne zachowanie w zależności od wartości własnych pól, to całkiem możliwe, że jest swego rodzaju specyficznym typem  tego obiektu, który wymaga osobnej implementacji w nowej klasie.

Tak naprawdę, to zachowanie argumentu

Jeżeli np. obiekt przedstawia różne zachowania w zależności od wartości zewnętrznych parametrów, np. argumentu metody. To należy zastanowić się, czy zachowanie nie powinno być cechą tego argumentu, i nie powinien powstać dla niego interfejs oraz implementacje specyficznych zachowań.

To wina środowiska zewnętrznego

Jeżeli różnice w zachowaniach, będą wynikać ze stanu otoczenia, w jakim znajduje się nasz obiekt, to zastosowanie wzorca strategi, będzie prawdopodobnie najlepszym rozwiązaniem.

Fabryka

Może się też zdarzyć sytuacja, w której zachowanie, niby zależy od jakichś specyficznych wartości, ale odpowiedzialności są różne. Wtedy można utworzyć fabrykę, która dostarczy obiekt z odpowiednim zachowaniem.

Wiele różnych zachowań, z wielu różnych powodów

W takich drastycznych, choć częstych przypadkach, można na początku pomyśleć, czy architektura rozwiązanie nie jest po prostu kiepska, i idzie to zrobić lepiej. Być może łączą się tu dwie opisane wcześniej przyczyny:

  • To nie własność obiektu to typ obiektu.
  • To tak naprawdę zachowanie argumentu.

Jeżeli nie, to można utworzyć obiekt, który zawiera metodę sprawdzającą, czy to zachowanie powinno być wykonane, jak i samo zachowanie. Można iterować po liście takich obiektów i wywoływać ich zachowania w zależności od spełnienia warunku.

Różny zakres zachowania w zależności od parametru

W przypadku gdy odmienność zachowania polega na różnym zakresie wykonywanych zadań, możemy pokusić się o zastosowanie wzorca – łańcuch zobowiązań. Należy wtedy jednak pamiętać o pułapce cykli, które mogą się pojawić w tym wzorcu.

Kiedy stosować tę zasadę

  • Jeżeli, zauważasz, że pewne reguły zmienia się  często.
  • Bieżące założenia nie są wystarczająco dopracowane.

Pozbądź się if, zastąp go dziedziczeniem i polimorfizmem typów. Warto też zapoznać się, ze wzorcami projektowymi takimi jak strategia, dekorator, czy łańcuch odpowiedzialności, value object.

Jakie zalety?

  • Nienaruszalność tego, co już działa.
  • Gotowość na nowe dodanie nowych reguł.
  • Unikamy kaskadowego wprowadzania zmian we wszystkich modułach.
  • Możliwość osobnych testów w kontekście każdej z reguł.
  • Większa elastyczność.
Please follow and like us:
Skuteczna refaktoryzacja w 10 krokach!

Odbierz Darmowy Poradnik o Refaktoryzacji!

Poznaj kilka prostych technik i wprowadź nową jakość w swoim projekcie.

Dzięki za dołączenie do mojej listy.

Coś poszło nie tak :( Spróbuj jeszcze raz.