架构师训练营第 2 期 第二周总结
软件设计的目的
强内聚,低耦合
1、易扩展。增加新功能,意味着对原代码的改动越少越好。
2、更强壮。不容易被其他程序员“一不小心”破坏。
3、可移植。在多样的环境下运行。
4、更简单。容易阅读理解,方便维护。
糟糕的代码具备的特征
1、僵化性。代码僵硬,不容易改变,某些个别的改动,会引起后续联动。
2、脆弱性。改变A的时候,意外改变了与当前业务无关紧要地方的B。为了修正该问题,又会引发各种连锁反应,导致成本急剧升高。
3、不可移植性。
4、牢固性。代码过于个性化。已经很难抽象成公共方法。进一步导致复制粘贴代码频
繁,即不必要的重复性。
5、粘滞性。导致错误的陷阱。让后续开发人员无奈得发现,将错就错的成本反而最低
的。
6、晦涩性。难以让接手的开发理解代码,甚至时间一长,原开发者也无法理解。
7、不必要的复杂性。开发时会预测部分需求,并写入那些处理潜在变化的代码,但这
个逻辑始终未应用。
设计原则
如何避免写出包含这些特征的代码。软件开发总结了一些设计原则。
一、开闭原则OCP
软件应对扩展开放、对更改封闭。新增新的类型、新的功能时不修改已完成的类、功能模块。
核心思想:抽象。
二、依赖倒置原则 DIP
依赖倒置原则
高层不依赖于低层,双方都依赖于高层定义的抽象(接口、配置、规则),进行面向接口编程。
依赖倒置倒置了什么?
非依赖倒置: 低层实现具体方法,然后依旧由低层抽象出接口,提供给高层调用。
依赖倒置: 高层定义抽象接口,低层完成这个接口的具体实现。
对比二者描述,具体倒置以下几点。
1、“抽象依赖实现“变更为 “实现依赖抽象”。
2、接口变更为由高层进行设计。
3、团队的依赖关系倒置。 具体变更为低层模块开发人员依赖于高层模块的开发人
员。
4、开发顺序倒置。最先进行的工作变更为:高层开发人员设计抽象接口。
三、里式替换原则 LSP
里式替换原则是用来解决继承的问题的。
若每个类型T1 的对象o1,都存在一个类型T2的对象o2,使得在所有针对T2编写的程序P中,用o1替换o2后,程序P的行为功能不变,则T1是T2的子类。
可能违反里式替换原则的征兆
1、子类中的方法功能退化。如继承后重写方法,不执行任何逻辑。
2、子类中抛出了父类原本不会产生的异常。
判断符合里式替换原则的标准
1、在场景中看:能使用父类的地方,一定能使用子类。
2、在Java语法中看:子类一定拥有父类的整个接口。子类的访问控制不能比父类严格。(例如父类方法控制为 public,子类覆盖写为private,代码将无法通过编译)。
当遇到违反里式替换原则的处理方法
当出现违背里式替换的现象时,说明当前子类没有完全跟从父类的意愿,但借用了父类的部分方法。那我们无需通过继承,而是改用组合的方式借用所需要的方法。
四、单一职责原则 SRP (内聚性原则)
一个类,只能有一个引起他变化的原因。
违反单一职责会使得代码具备脆弱性与不可移植性。
操作中心思想:拆。遇到一个类太大的时候,集合了一大堆方法。我们可以把方法拆分出去到不同的处理类。同时,会遇到另一个问题,比如这些个方法间有联系,比如共享变量,拆分到不同的类中,可能得不偿失,
那么,我们可以遵循下一个原则: 接口分离。
五、接口分离原则 ISP
不应强迫客户程序,依赖它们不需要的方法。从客户的角度出发,不要让他们看到不需要的方法。
以上面单一职责最后描述的场景为例,一个类对外提供2个方法fun1与fun2,这两个方法内部有所联系,无法拆分。但fun1是用户调用的方法,而 fun2是提供给管理员的。用户与管理员在业务上无需使用对方的方法。接口分离优化的目的是让双方都看不到对方的方法,避免错误的调用导致不可预料的错误。
如何实现接口隔离?即调用者将只能看到,他调用的接口上,对应着的类方法
1、根据类方法的调用来源,抽象出不同接口(表现为类实现了这些接口),分别暴露给调用者。
2、利用适配器关联原类,在适配器调用原类的方法,并额外实现接口A(包含原类没有的方法)。调用原类的用户,不会看到接口A中包含的方法。调用适配器的用户,能看到所有的方法。
评论