Zasada otwarte/zamknięte – druga zasada SOLID.
W programowaniu obiektowym podstawowym założeniem czystego kodu jest wymyślone przez Martin’a, 5 zasad dobrego programowania tzw. SOLID. Drugą z pięciu założeń SOLID, jest zasada otwarte/zamknięte mówiąca, że elementy systemu takie, jak klasy, moduły, funkcje itd. powinny być otwarte na rozszerzenie, ale zamknięte na modyfikacje. W tym artykule opisze tą metodę oraz przedstawię przykład kodu programu przed użyciem tej zasady i po.
Zastosowanie
Zasada otwarte/zamknięte z ang. Open/Closed principle jest jedną z zasad programowania obiektowego. Jak już wyżej wspomniałem klasy są otwarte na rozszerzenie, ale zamknięte na modyfikacje. Oznacza to, iż można zmienić zachowanie takiego elementu bez zmiany jego kodu. Jest to szczególnie ważne w środowisku produkcyjnym, gdzie zmiany kodu źródłowego mogą być niewskazane i powodować ryzyko wprowadzenia błędu. Program, który trzyma się tej zasady, nie wymaga zmian w kodzie, więc nie jest narażony na powyższe ryzyko. W praktyce powinniśmy zapewnić możliwość rozszerzenia klasy oraz unikać wprowadzenia zmian w klasie. Wprowadzenie zmian do klasy jest zawsze kosztowne i ryzykowne. Jeśli już musimy wprowadzać jakieś zachowanie to lepiej zrobić to przez rozszerzenie. Regułę tą można wdrożyć na różne sposoby np. przez dziedziczenie czy interfejsy. Zasada ta jest szczególnie ważna w dużych projektach, dla twórców wszelkich rozszerzeń, wtyczek oraz bibliotek programistycznych. Dzięki tej zasadzie projekty stają się bardziej elastyczne i łatwiejsze do rozbudowy.
Przykład
Mamy tutaj część programu do zapisywania raportów do różnych plików XML i JSON:
<?php
class ReportPrinter
{
public function print($filetype)
{
if ($filetype == 'XML') {
echo 'Zapisuje raport do pliku XML';
} elseif ($filetype == 'JSON') {
echo 'Zapisuje raport do pliku JSON';
}
}
}
$rp = new ReportPrinter();
$rp->print('XML');
?>
Kod 1. Kod bez zastosowania drugiej zasady SOLID
Klasa powyżej łamie tą zasadę ponieważ, gdy chcielibyśmy wprowadzić nowy filetype do zapisywania raportów np. TXT, to trzeba byłoby do tej klasy dodać kolejnego if z nowym filetype, jednak jest to bardzo ryzykowne i kosztowne zagranie. Dlatego trzeba zaplanować tak tą klasę, żeby można była ją rozszerzać o nowy typ pliku a nie modyfikować. Poniżej znajduje się poprawnie napisany program według zasady otwarte/zamknięte:
<?php
abstract class ReportPrinter
{
public abstract function print();
}
class XMLReportPrinter extends ReportPrinter
{
public function print()
{
echo 'Zapisuje raport do pliku XML';
}
}
class JSONReportPrinter extends ReportPrinter
{
public function print()
{
echo 'Zapisuje raport do pliku JSON';
}
}
$rp = new XMLReportPrinter();
$rp->print();
?>
Kod 2. Kod z zastosowaniem drugiej zasady SOLID
Podsumowanie
Jak można zauważyć wprowadziliśmy dodatkowa klasę abstrakcyjną ReportPrinter, w której znajduje się abstrakcyjna metoda. Klasę tą w ten sposób zamknęliśmy na modyfikacje. Wprowadziliśmy również dwie klasy dziedziczące z klasy ReportPrinter. Z powodu tego można w łatwy sposób dodawać inne typy plików do zapisu. Czyli jeśli chcemy dodać nowy typ pliku to już nie musimy wracać do klasy ReportPrinter, gdyż nasze nowe klasy są rozszerzalne. Podsumowując, druga metoda z SOLID jest również istotna dla programowania obiektowego, gdyż modyfikacja klas może przyczyniać się do wielu późniejszych problemów w programie. Aplikacja Personal Budget, także stosuje tą zasadę. Powinniśmy polegać na rozszerzaniu klas przez zastosowanie abstrakcji, interfejsów i polimorfizmu. Dzięki zastosowaniu się do reguły otwarte/zamknięte nasz system jest bardziej stabilny oraz jeżeli rozwijamy nasz system, minimalizujemy potrzeby modyfikacji istniejącego kodu w wielu miejscach.