Open-Closed Principle – zasada Otwarte- zamknięte. “Encje oprogramowania (klasy, moduły, funkcje, metody, itp.) powinny być otwarte na rozbudowę ale zamknięte dla modyfikacji”.
Kod powinien być tak napisany, by w przypadku rozwoju systemu i pojawiających się kolejnych wymagań biznesowych, nie trzeba było zmieniać istniejącego kodu. Ma on być otwarty na rozszerzanie i dodawanie nowych „klocków”. Wymaganie to zmusza nas do dokładnego przemyślenia realizowanych zadań i wprowadzenia od początku na tyle ogólnych rozwiązań, by były one przygotowane pod dalszą rozbudowę.
Jeżeli pojedyncza zmiana powoduje lawinę zmian w modułach zależnych to jest to projekt trudny do zmiany (ang. rigidity – sztywność). Zasada OCP mówi o napisaniu programu w taki sposób aby wprowadzane zmiany w projekcie nie powodowały kolejnych zmian. Gdy zasada ta jest zachowana to dodajemy nowy kod, ale nie zmieniamy tego już istniejącego.
Przyklad: Implementując eksporter plików przygotowujemy metody, które będą abstrakcyjne i zapewnią możliwość wprowadzania kolejnych implementacji w postaci nowych klas w przyszłości. Każda taka klasa będzie dostarczać własną implementację eksportu. Inaczej będzie wyglądało wykonywanie eksportu do pliku csv, a inaczej do pliku xls, niemniej wszystkie eksporty będą posiadały ogólny zbiór podobnych zadań, takich jak pobranie danych, ich przetworzenie oraz eksport do pliku. Wspólne dla wszystkich będą pewne cechy, na przykład nazwa pliku, czy jego rozszerzenie.
Nawet jeśli w pierwszej fazie projektu musimy przygotować eksport tylko do pliku csv, warto wprowadzić ogólny mechanizm eksportu, a implementacje metod dostarczyć w osobnych klasach. Jeśli nagle pojawi się wymaganie dodania eksportu xls, wówczas do wykonania pozostanie nam tylko przygotowanie klasy dedykowanej temu typowi. Nic nie zmieniamy w kontekście samego procesu (jego uruchomienia, obsługi błędów, czy obsługi zakończenia). Wszelkie zmiany nie mają również wpływu na kod eksportu csv (nie musimy go zmieniać).
Dla zasady OCP można stosować wzorzec Strategia i Metoda szablonowa. Są to najbardziej popularne wzorce przy zasadzie OCP. przykład zasady OCP:
public interface MessageLogger { void log(String message) throws Exception; }
Każdy ze sposobów logowania umieścimy w odrębnej klasie. Pierwszą z klas będzie klasa ConsoleLogger, która będzie logować komunikaty na konsole.
public class ConsoleLogger implements MessageLogger { @Override public void log(String message) { System.out.println(message); } }
Druga z klas czyli FileLogger będzie logowała dane do pliku.
public class FileLogger implements MessageLogger { @Override public void log(String message) throws Exception { Files.write(Paths.get("file.log"), Arrays.asList(message), StandardOpenOption.APPEND); } }