歪读《架构整洁之道》第七章之原则就是用来遵守的

        最近校园招聘,比较爱问的一个问题是:同学,你知道SOLID吗?比较多的同学一脸茫然,然后我就故作安慰道,没事,不知道也正常;如果有同学能回答上一二,则满脸欣慰,感叹,不错不错,阅读面还很广;如果每一个都能讲的头头是道,我反而会疑惑,同学,你是知道我要问什么,提前背的吧?哈哈,虽是玩笑,不过设计原则要死记本就较难,活用更是考验软件设计的基本功,能按自己的理解讲解出来确实就非常好了。

        实际上,软件设计原则在《敏捷软件开发:原则、模式与实践》这本书讲解的更为详细一些,不过好的软件架构,需要从整洁代码开始,就如好的建筑需要好的砖头一样,所以本书也对设计原则进行了详细的讲解。设计原则就好比《九阴真经》的总纲,偏向于理论知识,而模式则偏向于应用,是对原则的具体诠释。

    软件设计原则本身是来源于软件开发过程中的规则总结,就如武功秘籍,我们易按照先读后练,先死套再活用的方法,今天我们就先来读一读再套用一下,当然也仅止于此。

    首先说SOLID中的S,也就是单一职责原则(SRP),书上的标准定义“任何一个软件模块都应该只对一类行为负责”,很抽象的解说,举例来说,我们项目经理和HR都需要统计每个员工的工时,最初两者要求的一样的,就是大家的上下班打卡时间,刚开始我们用相同的方法来实现,结果有一天HR说,按国家规定,周六双倍工资,工时算两倍,按这个需求修改完成后,项目经理这边就出麻烦了,工时按双倍计算,工作进度没有双倍啊,工作进度就完不成了。所以单一职责就是要把服务不同对象的代码进行切分,避免代码修改的时候互相影响。

    第二个是OCP,开闭原则,书上的定义是“设计良好的计算机软件应该易与扩展,同时抗拒修改”。按我的理解,“开”即为变化,“闭”即不变的部分,开闭原则就是以不变应万变。比如我当前设计的一个度量系统,不变的是后端对流水线的运行数据收集、分析、存储,而前端的看板展示部分,我会根据需要设计出流水线实时看板,每日看板,后续陆续扩展出月度统计看板,年度统计看板,甚至还有不同维度的度量应用,但这些扩展的应用对我的数据收集中心是无影响的。组件层次划分清晰,且组件的依赖单向,即可以做到开闭随心而无所惧也。

    第三个为LSP,里氏替换原则,其中里氏是提出者Liskov女士的音译,所以该原则的核心应该是“替换”。书上定义为“继承必须确保超类所拥有的性质在子类中仍然成立”,也就是说,如果子类不能完全继承超类的所有性质,那么这样的继承就是不合理的。书上使用的是长方形/正方形的例子,按数学书上的讲解,正方形是一种特殊的长方形。但是如果长方形定义了setHight和setWide两种方法,那么正方形是不适合继承长方形的,否则正方形调用setHight和setWide就会造成定义失效,为了兼容这种问题,会造成软件架构极大的混乱。

    第四个为ISP,接口隔离原则,按字面解释,“要为各个类建立它们需要的专用接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用”。这个和单一职责原则很类似,可以说是接口的单一职责。说一个反例,有一个薪水管理的接口,salary(type,count),type可以为add,reduce,一个接口搞定两件事情,这样首先会造成salary的实现方法臃肿,其次,当add的逻辑修改,比如需要对工作满10年的同学双倍加薪,这样对调用reduce的地方也需要重新进行编译部署(静态语言),即便动态语言不需要重新编译,接口的耦合也会造成接口的修改难度加大,容易带来意料之外的麻烦。

    第五个DIP,依赖反转原则,定义如下:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。依赖倒置原则的目的是通过要面向接口的编程来降低类间的耦合性,所以我们在实际编程中只要遵循以下4点,就能在项目中满足这个规则。

每个类尽量提供接口或抽象类,或者两者都具备。

变量的声明类型尽量是接口或者是抽象类。

任何类都不应该从具体类派生。

使用继承时尽量遵循里氏替换原则。

软件设计原则还有迪米特法则以及合成复用原则,不过本书没有提及,也就不再赘述。另外本章确实有点上头,本想简单明了的介绍设计原则,但是个人本身理解就不深,自然无法深入浅出,姑且看之。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容