Чому (/ зробив) Бертран Мейєр вважає, що підкласифікація - єдиний спосіб розширити «закритий» модуль?


19

У « Об’єктно-орієнтованій програмі» ( Майєр ) він визначає принцип відкритого / закритого типу :

  • Модуль, як кажуть, буде відкритим, якщо він ще доступний для розширення. Наприклад, має бути можливість додати поля до структур даних, які він містить, або нових елементів до набору функцій, які він виконує.
  • Кажуть, що модуль закритий, якщо він доступний для використання іншими модулями. Це передбачає, що модулю було дано чітко визначений стабільний опис (інтерфейс у сенсі приховування інформації).

Він продовжує говорити:

Якщо ви знову відкриєте модуль, ви також повинні знову відкрити всі його клієнти, щоб оновити їх, оскільки вони покладаються на стару версію. … [Ця проблема] виникає кожного разу, коли модуль повинен бути розширений новою функцією або елементом даних, викликаючи зміни у прямих та непрямих клієнтів. ... При класичних підходах до проектування та програмування неможливо написати модулі, які є відкритими та закритими.

Вирішенням цієї дилеми Мейєра є: ніколи не розширюйте модуль бібліотеки, змінюючи існуючі класи; натомість написати новий модуль, який підкласирует наявні класи та має нових клієнтів, залежать від цього нового модуля.

Зараз, у 1988 році, я писав іграшкові (процедурні) програми в Turbo Pascal і Blankenship Basic, і мій досвід 21 століття в JVM, CLR та на динамічних мовах, тому я не знаю, що мав на увазі Меєр "класичними підходами до проектування та програмування".

Конкретний приклад Мейєра, чому клієнтські модулі повинні бути повторно відкриті (заява переключення на перерахування, в якій зараз є більше членів, вимагає більше випадків), здається достатньо розумною, але він майже не виправдовує твердження, що кожного разу, коли ви додаєте функціональність до бібліотеки модуль, вам потрібно оновити всіх його клієнтів .

Чи є історична причина, що це твердження здавалося само собою зрозумілим у 1988 році? Чи, скажімо, додавання функцій або структур даних до статичної бібліотеки С змінило макет таким чином, що навіть із API-сумісними назад, клієнтів довелося перекомпілювати? Або Меєр насправді просто говорить про механізм забезпечення сумісності API назад?


3
Цікаве запитання! У мене є відчуття, що відповідь буде якимось чином пов'язана з принциповою різницею між абстрактними типами даних та об'єктно-орієнтованою абстракцією даних , які є двома домінуючими механізмами абстрагування даних у модульному програмуванні (те, що Бетранд Мейєр називає "класичними підходами" ") та об'єктно-орієнтоване програмування (читайте коментарі!) відповідно.
Йорг W Міттаг

Це дивно. Здається, це явно суперечить дійсності (навіть у 1988 році). Крім того, його захищений підхід спричинив би непосильне розповсюдження модулів.

@ dan1111: Підхід Ейфеля до спадкування, включаючи, але не обмежуючись, його підхід до багаторазового успадкування, відрізняється від C ++, Java, C # тощо, тому не дивно, що підхід інший. Зрештою, він розробив Ейфеля, щоб підтримати його погляди на ОО.
Йорг W Міттаг

Відповіді:


18

Наскільки я можу сказати, на це запитання відповів сам Бертран Мейєр, і відповідь, це твердження не є точним. При класичних підходах до проектування та програмування дійсно може бути спосіб запису модулів, які є як відкритими, так і закритими.

Щоб дізнатися це, потрібно вивчити друге видання цієї книги (опубліковану через дев'ять років, у 1997 році). Згідно з передмовою другого видання , це так

не оновлення, а результат ретельної переробки. Не абзац оригінальної версії не залишився недоторканим. (Навряд чи єдиний рядок, насправді.)

Зокрема, заява, яка вас бентежить, пішла. У "§3.3 П'ять принципів" все ще є розділ принципу відкритого закритого типу , і дане ретельне обговорення цієї теми є в "§14.7 Введення в спадщину", але твердження з першої редакції вже не існує.

Що замість цього, фокусується на тому, як зручніше та ідіоматичніше у підході до ОО на відміну від попередніх способів,

Завдяки успадковуванню розробники OO можуть скористатися набагато більш інкрементальним підходом до розробки програмного забезпечення, ніж раніше, ніж це можливо раніше) (§3.3)

Ця подвійна вимога (відкрита і закрита) виглядає як дилема, і класичні модульні структури не мають жодного підказки. Але спадкування вирішує це. Клас закритий, оскільки він може складатись, зберігатись у бібліотеці, базуватись та використовуватись клієнтськими класами. Але він також відкритий, оскільки будь-який новий клас може використовувати його як батьківський, додаючи нові функції та переосмислюючи спадкові функції; у цьому процесі немає необхідності змінювати оригінал або заважати його клієнтам ... (§14.7)

Оскільки вам також здається цікавим, що тут означав "класичний підхід" Мейєра, ви можете знайти пояснення цього в §4.7 Традиційні модульні структури . У цьому розділі пояснюється, що це означає «бібліотеки процедур» та «пакунки» (для останнього автор каже, що термін взято з Ада та згадує інші мови, що мають цю особливість - кластери в CLU та модулі в модулі).

Якщо ви подумаєте, жоден із цих підходів спочатку не мав на меті допомогти в написанні коду, який дотримується принципу відкритого закриття. Це може призвести автора до їх дещо передчасної оцінки, яка згодом була виправлена ​​у другому виданні.


Щодо того, що конкретно змусило автора змінити свою думку щодо цього твердження між першим та другим виданням, я думаю, що можна знайти відповідь, знову ж таки, у самій книзі, а саме у частині F: Застосування методу в різних мовах та середовищах " . У цій главі автор обговорює, як об’єктно-орієнтовані методи можуть бути використані у старих мовах:

Класичні мови, такі як Фортран, взагалі не є ОО, але люди, які все-таки повинні їх використовувати ... можуть захотіти застосувати стільки ідей OO, наскільки це можливо в межах цих старих підходів.

Зокрема, у цій частині Мейєр детально пояснює, як можна було б реалізувати успадкування (з деякими застереженнями та обмеженнями, але все-таки) у С та навіть у Фортран.

Розумієте, це дійсно вимагає переглянути цю заяву з першого видання. Здається, практично неможливо пояснити, як примиритись «з класичними підходами ... немає можливості» з реалістичними прикладами того, як саме це можна зробити.


Цікаво, і мені обов’язково доведеться спробувати отримати друге видання, але мені все одно не зрозуміло, чому навіть "класична" бібліотека, що не є "OO", не могла додати (принаймні певні види) функцій, не порушуючи її клієнтів.
Девід Молес

Справа @DavidMoles полягає в тому, що це могло , і остання частина моєї відповіді пояснює це, і що Меєр сам зрозумів, що (коли він переробляв для другого видання) і навіть наводив приклади, як це можна зробити. "Щодо того, що конкретно змусило автора змінити свою думку ..." тощо
gnat

Хм. Я не бачу "версії 2 цієї бібліотеки, яка замінює версію 1 і назад сумісна з нею, додає такі функції ..." як "успадкування", за винятком широкого можливого концептуального способу.
Девід Молес

(Спадщина для мене означає, що версія 1 все ще існує і називається версією 2.)
Девід Молес

@DavidMoles заміни версії 2 (як у, зміна вихідного коду та перекомпіляція ) не кваліфікуються як "закриті для модифікації", ви можете просто перевірити це у статті Вікіпедії : "Суб'єкт може дозволити розширити його поведінку без зміни свого вихідного коду ... "
гнат
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.