62 | 重新认识开闭原则 (OCP)
许式伟
该思维导图由 AI 生成,仅供参考
你好,我是七牛云许式伟。
架构的本质是业务的正交分解。
在上一讲 “61 | 全局性功能的架构设计” 中我们提到,架构分解中有两大难题:其一,需求的交织。不同需求混杂在一起,也就是存在所谓的全局性功能。其二,需求的易变。不同客户,不同场景下需求看起来很不一样,场景呈发散趋势。
我们可能经常会听到各种架构思维的原则或模式。但,为什么我们开始谈到架构思维了,也不是从那些耳熟能详的原则或模式谈起?
因为,万变不离其宗。
就架构的本质而言,我们核心要掌握的架构设计的工具其实就只有两个:
组合。用小业务组装出大业务,组装出越来越复杂的系统。
如何应对变化(开闭原则)。
开闭原则(OCP)
今天我们就聊聊怎么应对需求的变化。
谈应对变化,就不能不提著名的 “开闭原则(Open Closed Principle,OCP)”。一般认为,最早提出开闭原则这一术语的是勃兰特·梅耶(Bertrand Meyer)。他在 1988 年在 《面向对象软件构造》 中首次提出了开闭原则。
什么是开闭原则(OCP)?
软件实体(模块,类,函数等)应该对于功能扩展是开放的,但对于修改是封闭的。
一个软件产品只要在其生命周期内,都会不断发生变化。变化是一个事实,所以我们需要让软件去适应变化。我们应该在设计时尽量适应这些变化,以提高项目的稳定性和灵活性,真正实现 “拥抱变化”。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
开闭原则(OCP)是架构设计中的重要原则,强调软件实体应对功能扩展是开放的,但对修改是封闭的。这一原则推崇模块业务的确定性,鼓励设计“只读”业务模块,一经设计就不可修改,如果要修改业务就直接废弃它,转而实现新的业务模块。开闭原则的应用不仅适用于软件设计,还体现在CPU的设计中。文章还介绍了插件机制和单一职责原则,强调模块的业务要稳定,变化点通过回调函数或插件机制交给其他模块。插件机制让核心系统与周边系统耦合度降低,但也需考虑通用性和成本。单一职责原则强调每个模块只负责一个业务。文章内容深入浅出,为读者解读了开闭原则的本质和架构设计的思维哲学,对架构设计具有重要意义。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《许式伟的架构课》,新⼈⾸单¥68
《许式伟的架构课》,新⼈⾸单¥68
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(36)
- 最新
- 精选
- Jxin笔记: 将开闭原则上移到业务系统。业务对外只读,意味着不可变,但不变的业务生命周期是很短暂的,所以要可扩。要扩展还要不变,就倒逼着要做兼容,而兼容可能会导致现有的功能职责不单一,这又倒逼着要对现有的功能做再抽象,以适应更广的“单一职责”。 所以不改是不可能的,只是改的结果应当是让项目往更稳定去发展。然而这里面其实好难,无论是新的抽象的定义还是职责范围的扩张,这都需要有强大的分析能力和精湛的设计思维、重构手法、调优能力以及站在核心目标上的权衡来支撑。然而难亦是乐趣所在。
作者回复: 👍
2019-12-06422 - leslie老师的课程中提及的两方面是我觉得自己理解的最不好的:一方面"基础架构 + 业务架构,才是你设计的软件的全部",另一方面"一方面从中学习怎么做需求分析,另一方面也从中体悟做架构的思维哲学"。 如同老师所说的"架构课 的革命性,我自己从没怀疑过。它的内容是精心设计的,为此我准备了十几年",学习的过程中我其实同样在整体梳理自己作为DBA&&OPS十余年松散的知识体系。老师开课的这半年多不断的适度扩展梳理去破未知,完成了20余门功课的学习;除了画图部分的知识都是在不断的循环梳理。虽不断学习和梳理,但是依然觉得老师今天课程中提及的两方面其实是最难。如同前几天DevOps课程的石老师课程提出的Plan-Do-Check-Act时,我说这个顺序其实可以改变且石老师的回复中对此非常认可一样。这个认知其实是原来许老师课程的循环反复,梳理中悟出的东西。 结合老师上堂课所提及"任何功能都是可以正交分解的,即使我目前还没有找到方法,那也是因为我还没有透彻理解需求"-可以理解为业务方面的。《全局性功能的架构设计》和《重新认识开闭原则》两章内容在强调今天课程结束老师的"基础架构 + 业务架构,才是你设计的软件的全部"。 以上是个人结合这两节课的知识对于今天课程结束部分老师的理解:谢谢老师的分享和教诲。期待老师的下次分享。
作者回复: 作为架构师,要深刻认识到一点,光理解架构哲学不足以做好架构,它是让我们判断对与错的法则。要真正做好架构,需要做好业务需求分析,做好正交分解,做好模块边界定义。这些不断梳理清楚的“只读”的业务模块,是架构师真正的武器库。
2019-12-06222 - 风翱活字印刷术,也是开闭原则应用的一个例子。 字是稳定的,字的排序是变化的。
作者回复: 👍
2021-05-269 - K战神许大,希望出书。买来收藏。 时不时枕边翻阅体会大佬的思想。 多年以后,庆幸自己这段时间跟着许大的专栏,有了新的想法和思想。
作者回复: 后面应该会出书
2019-12-068 - Yayu如何理解“只读”模块?
作者回复: 不是代码只读,是业务范畴只读,接口尽可能只读(增加方法以兼容的方式进行)。
2019-12-0645 - swchen对于程序员而言,三种思维最为基础: 1.DRY (Don’t Repeat Yourself) 。 这是好程序员的根本追求,永久的驱动力。 2.分而治之。 这是人类解决复杂问题的普遍方式。 3.开闭原则。 这是应对变化(主动的变化如功能扩展,被动的变化如故障修复)的最佳手段。 其他各种原则/方法/模式/最佳实践,全部都是以此三者为基础,结合具体领域/场景/时代的更具操作性的推论。
作者回复: 👍
2022-05-2623 - 另存为……老师,最近在了解区块链相关的知识,感悟到了一些开闭原则上的应用,跟您探讨下: 比特币旨在构建新一代的数字货币,而以太坊的目标则是要成为新一代点对点的分布式计算基础服务(终极目标是成为 web3.0 的标准),基于此发展除了智能合约,所谓“智能合约”,实际就是可编程的合约,跟我们普遍理解的“智能”没啥关系,那既然是程序,必定会涉及到升级或修复,业务数据存储结构变更,而区块链的特性决定了“变更”是一项成本极其高昂甚至几乎无法完成,我们称之为不可篡改特性,因此现在做dapp涉及一般设计为数据合约和程序逻辑合约组合,做到程序和数据分离(由此也可以看出对比中心化的程序还是相当原始和初级的),这样在程序更新的时候直接弃用旧的合约地址,改用新合约,数据也不用迁移,但是当我们的需求需要持续更新合约的时候,如果能懂得运用开闭原则,这件事情会优雅很多,因为无论是 以太坊的 ERC20 还是 ERC721 标准等等,都规定了相当有限且简单的接口标准,这就是架构的不可变部分,我们不能把所有的逻辑都堆在这个我们针对于接口的实现上,而应该采用组合的方式,通过合理的架构设计,多个合约组合出强大的功能,我看了几条最新的以太坊社区提案,一些针对于 NFTs 的提案,比如 ERC-998,旨在让多个 NFT 组合的新 NFT 具备不可拆解的特性,使新的NFT可以整体交易,这会极大的简化物品转移的处理,其实都是可以遵循开闭原则通过良好合理的设计组合合约来实现,没必要升级为最基础的接口标准,当然这也会带来 gas 成本的增加,因为运行在区块链上的程序是需要支付 gas 费用的,所以币安推出 bsc 币安智能链的原因之一,降低 gas 费用。
作者回复: 挺好的思考👍
2021-12-253 - 何磊老师对于开闭原则,我也在思考这里的开、闭到底是针对什么的。 首先对于bug坑定是需要修复的;那么如文中提到的,对于需求的变化引起需要修改利用插件机制。但是实际的业务中,可能很多是需要在原有代码中增加一个if判断、或者类型转化、或者额外的数据处理。 针对这些问题,肯定不可避免要去对源代码产生修改。这里很难去控制什么时候可以改,什么时候该用插件
作者回复: 修改业务(需求)和改bug是完全不同的。修改bug不属于开闭原则的思考范畴。
2020-07-162 - Geek_adf1c9开闭的核心还是明确“变与不变”,这很难,需要大量的需求分析
作者回复: 是的
2022-05-1921 - Bravery168需求稳定点与变化点,正交分解,开闭原则,我理解内在本质是一脉相承的。这种架构看看作一种生命体,在基础构造上是稳定的,但又具备足够的柔性和灵活性。在业务变化时能够灵活适应,同时又不会散发臭味。有了这种特质,这种架构才可以说是有生命力的。
作者回复: 是这样
2020-02-281
收起评论