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?
Odpowiedzi:
O ile wiem, na to pytanie odpowiedział sam Bertrand Meyer, a odpowiedź brzmi: to stwierdzenie nie jest dokładne. Z klasycznego podejścia do projektowania i programowania, tam rzeczywiście może być sposobem zapisu modułów, które są otwarte i zamknięte.
Aby się tego dowiedzieć, musisz przestudiować drugie wydanie tej książki (opublikowanej dziewięć lat później, w 1997 r.). Według przedmowy do drugiego wydania jest
W szczególności minęło stwierdzenie, które Cię myli. W rozdziale „§3.3 Pięć zasad” nadal znajduje się rozdział dotyczący zasad otwartych i zamkniętych , a dalsze omówienie tego tematu znajduje się w „§14.7 Wprowadzenie do dziedziczenia”, ale stwierdzenia z pierwszego wydania już go nie ma.
To, co tam jest, skupia się na tym, jak jest wygodniejsze i idiomatyczne w podejściu OO, w przeciwieństwie do wcześniejszych sposobów,
Ponieważ wydaje się, że zastanawiasz się także, co znaczyło tutaj „podejście klasyczne” Meyera, możesz je wyjaśnić w § 4.7 Tradycyjne konstrukcje modułowe . W tej sekcji wyjaśniono, że oznaczają one „biblioteki procedur” i „pakiety” (w tym drugim przypadku autor twierdzi, że termin pochodzi od Ady i wspomina o innych językach posiadających tę funkcję - klastry w CLU i moduły w Modula).
Jeśli się nad tym zastanowić, początkowo żadne z tych podejść nie miało na celu pomocy w pisaniu kodu zgodnego z zasadą otwartego zamknięcia. Może to doprowadzić autora do nieco przedwczesnej oceny, którą później poprawiono w drugim wydaniu.
Jeśli chodzi o to, co konkretnie skłoniło autora do zmiany zdania na temat tego stwierdzenia między pierwszym a drugim wydaniem, myślę, że można znaleźć odpowiedź w samej książce, a mianowicie w części F: Zastosowanie metody w różnych językach i środowiskach . ” w tym rozdziale autor omawia, w jaki sposób można stosować metody obiektowe w starszych językach:
W szczególności w tej części Meyer szczegółowo wyjaśnia, w jaki sposób można wprowadzić dziedziczenie (z pewnymi zastrzeżeniami i ograniczeniami, ale nadal) w C, a nawet w Fortranie.
Widzisz, to naprawdę wymaga rewizji tego stwierdzenia z pierwszego wydania. Praktycznie niemożliwe jest wyjaśnienie, jak pogodzić „z klasycznym podejściem ... nie ma mowy” z realistycznymi przykładami, jak dokładnie można to zrobić.
źródło