理解开闭原则

Posted

技术标签:

【中文标题】理解开闭原则【英文标题】:Making sense of the open closed principle 【发布时间】:2017-07-11 17:05:27 【问题描述】:

我正在努力理解开放封闭原则:

模块应该对扩展开放,对修改关闭

就 java 而言,扩展是专门继承还是包括继承以及添加新方法或属性?

我也很难理解为修改而关闭,这似乎在暗示我,一旦编写了一个方法,它就无法改变。

这似乎与我将从 jira 接任务的实际工作不一致,这需要我更改代码库中的至少一种方法。

在过去的 24 小时内,我阅读了很多帖子和文章,但我仍然不完全确定这个原则试图传达什么。

任何简单的解释都会很有帮助。

【问题讨论】:

关闭修改意味着改变行为,你不应该改变类/方法内的代码。并且对扩展开放意味着你可以传递不同的参数来改变行为。 它确保您不必在每次要向系统添加用例时修改添加逻辑的方法。因为如果你不得不这样做,你最终可能会得到一个完成系统所有逻辑的怪物方法。而且这样的方法是不可维护的(我从经验中知道) 如何通过不更改代码而是传递“不同的参数来改变行为”来改变行为?我知道您可以扩展该类,但正在使用多层继承来实现它的含义?在有效的 Java 中,建议优先使用组合而不是继承。 @berimblo 您传递了一个具有不同实现的类。您不需要多层继承,只需 1 像一个具有许多不同实现的接口。我说的是作曲 好吧,所以对接口进行编程有助于实现这种关闭。 【参考方案1】:

您应该编写足够好的代码,而不必修改现有代码。曾经。如果您需要现有方法的功能,您应该能够调用该方法,因为它应该具有高内聚性和极低的耦合性。

这样想,一旦你建了房子,是把浴室的面积加倍更好(移动厕所和重新铺设地板,新墙......等)还是更容易建造房子前面的日光浴室有一个新的入口?

你应该拒绝修改卧室,虽然这不是不可能的,但做一个阳光房会更容易创造新的空间。

【讨论】:

好吧,等等,您工作/曾经工作过的系统,除了解决错误之外,您不需要更改方法行为? 正确,您不必更改任何现有方法。您会接受它们正在工作,没有错误,您正在使用的方法,并且任何新错误都会由于您的新代码(类型不匹配)或运行时错误而发生。 再想一想,我想这个问题更适合软件工程堆栈交换softwareengineering.stackexchange.com 好吧,我还是不明白,因为需求和代码一样一直在变化。也许这只是我研究过的系统。我正在开发的当前系统有超过 100 名开发人员和 100,000 名用户,因此许多不断变化的需求和方法也经常变化。 在引用其他网站时,指出cross-posting is frowned upon 通常会有所帮助【参考方案2】:

开放扩展

模块的合理扩展应该是可能的。如果不是,则潜在用户将改为编写自己的实现,从而导致重复。

什么是合理扩展通常是设计中最难的部分 - 设计师必须预测最终用户将需要哪些扩展。

关闭修改

模块的扩展不能破坏模块的内部工作/声明的功能。如果模块未能保护其内部工作不被修改,那么确保(甚至考虑)模块的正确性将变得更加困难。基本上,通过允许用户修改您的模块,您向模块的 contract 添加了一个要求,即扩展不会以会破坏它的方式修改您的模块 - 这种要求通常如果没有用户对模块的详细了解,则没有文档且无法实现。

【讨论】:

这是可以理解的。我更多地考虑了代码一旦编写就永不更改的原则。以数据库映射器为例,它从 db 结果集中获取属性,添加了一个新列,因此它必须更改。同样,映射器使用构建器来构建 dto,它们都必须更改以反映新数据库字段的要求。这是扩展吗?好像是。现在,在这种情况下,这个新属性将需要更改传入请求的验证器,即 validate() 方法中的逻辑更改。似乎破坏的多次代码更改永远不会更改代码.. 在上面的场景中,显然所有单元和集成测试都会改变以反映这些变化。 这个原则对于有野心/可能被重用的模块很重要。如果您希望在示例中支持这两个版本(有和没有新列),那也是重用。否则,这些可能是太次要、单一用途的模块,无法尝试应用该原则,这样做可能会导致设计过于复杂。 重用是指将在多个项目中使用的模块吗?我工作过的所有系统我们都不拥有客户使用的软件,所以我们不倾向于以这种方式编写库,所以也许这就是为什么没有如此强调这一原则的原因?我们确实像使用 spring 一样使用设计模式和接口代码。 该原则有意谈论“模块”,而不是“框架”、“库”、“类”等。它可以在任何规模上应用——如果你有一个可以在多个上重用的类在您的(单个)项目中放置,最好考虑这个原则。如果你正在编写一个别人会使用的库,它就变得更加重要。

以上是关于理解开闭原则的主要内容,如果未能解决你的问题,请参考以下文章

设计模式开闭原则

开闭原则——面向对象程序设计原则

手撸golang 架构设计原则 开闭原则

面向对象原则之一 开放封闭原则(开闭原则)

开闭原则

设计模-设计原则-开闭原则