В Построении объектно-ориентированного программного обеспечения Мейера (1988) он определяет принцип открытия / закрытия следующим образом:
- Модуль будет считаться открытым, если он все еще доступен для расширения. Например, должна быть возможность добавить поля к структурам данных, которые он содержит, или новые элементы к набору функций, которые он выполняет.
- Модуль считается закрытым, если он доступен для использования другими модулями. Это предполагает, что модуль получил четкое, стабильное описание (интерфейс в смысле скрытия информации).
Он продолжает говорить:
Если вы снова откроете модуль, вы также должны снова открыть все его клиенты, чтобы обновить их, так как они полагаются на старую версию. … [Эта проблема] возникает каждый раз, когда модуль должен быть расширен новой функцией или элементом данных, вызывая изменения в прямых и косвенных клиентах. ... При классических подходах к проектированию и программированию нет возможности писать модули, которые бы были как открытыми, так и закрытыми.
Решение этой проблемы Мейера состоит в следующем: никогда не расширять библиотечный модуль, изменяя существующие классы; вместо этого напишите новый модуль, который подклассирует существующие классы, и у которых новые клиенты зависят от этого нового модуля.
Теперь, в 1988 году, я писал игрушечные (процедурные) программы на Turbo Pascal и Blankenship Basic, и мой профессиональный опыт 21-го века связан с JVM, CLR и динамическими языками, поэтому я не знаю, что имел в виду Мейер. по "классическим подходам к дизайну и программированию".
Один конкретный пример Мейера о том, почему клиентские модули должны быть открыты вновь (оператор switch для перечисления, в котором теперь больше членов, требующих большего числа случаев), кажется достаточно разумным, но он почти не оправдывает утверждение, что каждый раз, когда вы добавляете функциональность в библиотеку Модуль, вам необходимо обновить все его клиенты .
Есть ли историческая причина, по которой это утверждение казалось самоочевидным в 1988 году? Скажем, добавление функций или структур данных в статическую библиотеку C изменило макет так, что даже с обратно совместимыми API-интерфейсами клиенты должны были перекомпилироваться? Или Мейер действительно просто говорит о механизме обеспечения обратной совместимости API?