在Meyer的“ 面向对象的软件构造”(1988)中,他将开放/封闭原则定义如下:
- 如果模块仍可扩展,则称其为打开状态。例如,应该可以向其包含的数据结构添加字段,或者向其执行的功能集添加新元素。
- 如果某个模块可供其他模块使用,则将其称为已关闭。假设已为模块提供了良好定义的稳定描述(信息隐藏的界面)。
他接着说:
如果重新打开模块,则还必须重新打开其所有客户端以对其进行更新,因为它们依赖于旧版本。…[此问题]每当模块必须由新功能或数据元素扩展时触发,从而触发直接和间接客户端中的更改。...使用经典的设计和编程方法,无法编写打开和关闭的模块。
Meyer解决这个难题的方法是:永远不要通过修改现有的类来扩展库模块;而是编写一个新模块来对现有类进行子类化,并使新客户端依赖于该新模块。
现在,在1988年,我正在用Turbo Pascal和Blankenship Basic编写玩具(程序)程序,而我在21世纪的专业经验是使用JVM,CLR和动态语言,所以我不知道Meyer的意思。通过“经典的设计和编程方法”。
Meyer的一个具体示例说明了为什么必须重新打开客户端模块(枚举上的switch语句,现在有更多的成员,需要更多的情况)似乎很合理,但是他几乎没有断言每次向库添加功能时都会断言模块,您需要更新其所有客户端。
是否有历史原因使该主张在1988年显得不言而喻?例如,向C静态库添加函数或数据结构是否更改了布局,以至于即使使用向后兼容的API,也必须重新编译客户端?还是Meyer真的只是在谈论一种用于强制API向后兼容的机制?