W Meyer Object-Oriented Software Construction (1988) definiuje zasadę otwartego / zamkniętego w następujący sposób:
- Mówi się, że moduł jest otwarty, jeśli jest nadal dostępny do rozszerzenia. Na przykład powinna istnieć możliwość dodawania pól do zawartych w nim struktur danych lub nowych elementów do zestawu funkcji, które wykonuje.
- Moduł zostanie uznany za zamknięty, jeśli będzie dostępny do użytku przez inne moduły. Zakłada się, że moduł otrzymał dobrze zdefiniowany, stabilny opis (interfejs w sensie ukrywania informacji).
Dalej mówi:
Jeśli ponownie otworzysz moduł, musisz również ponownie otworzyć wszystkich jego klientów, aby je zaktualizować, ponieważ korzystają ze starej wersji. … [Ten problem] pojawia się za każdym razem, gdy moduł musi zostać rozszerzony o nową funkcję lub element danych, powodując zmiany w bezpośrednich i pośrednich klientach. ... Przy klasycznym podejściu do projektowania i programowania nie ma możliwości pisania modułów, które są zarówno otwarte, jak i zamknięte.
Rozwiązaniem tego dylematu Meyera jest: nigdy nie rozszerzaj modułu biblioteki poprzez modyfikację istniejących klas; zamiast tego napisz nowy moduł, który podklasuje istniejące klasy, i spraw, aby nowi klienci byli zależni od tego nowego modułu.
Teraz, w 1988 roku, pisałem programy zabawkowe (proceduralne) w Turbo Pascal i Blankenship Basic, a moje doświadczenie zawodowe w XXI wieku dotyczy JVM, CLR i języków dynamicznych, więc nie wiem, co miał na myśli Meyer przez „klasyczne podejście do projektowania i programowania”.
Jeden konkretny przykład Meyera, dlaczego moduły klienta muszą zostać ponownie otwarte (instrukcja switch w wyliczeniu, która ma teraz więcej członków, wymagająca większej liczby przypadków) wydaje się dość rozsądna, ale nie uzasadnia prawie twierdzenia, że za każdym razem , gdy dodajesz funkcjonalność do biblioteki moduł, musisz zaktualizować wszystkich swoich klientów .
Czy istnieje historyczny powód, dla którego twierdzenie to wydawało się oczywiste w 1988 roku? Czy, powiedzmy, dodanie funkcji lub struktur danych do biblioteki statycznej C zmieniło układ tak, że nawet przy API kompatybilnych wstecz, klienci musieli zostać ponownie skompilowani? A może Meyer tak naprawdę mówi tylko o mechanizmie wymuszania wstecznej kompatybilności API?