架构师训练营作业 2- 依赖倒置原则的思考
什么是依赖倒置原则?
在面向对象编程领域,依赖导致原则是解耦软件中模块间关系的一个重要手段。其要求:
High-level modules should not depend on low-level modules. Both should depend on abstractions (e.g. interfaces).
Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions.
即:
高层模块不应该依赖低层模块,两者都应该依赖抽象。
抽象不应该依赖于细节,细节应该依赖于抽象。
首先来看下不遵循依赖倒置原则可能会带来哪些问题?
许多传统软件开发思路中,如结构化分析与设计,总是倾向于创建一些高层模块直接依赖于低层模块、策略依赖于实现细节的软件架构。如下图所示:
这种层级结构在描述高层模块怎样调用低层模块时十分清晰易懂,但需要考虑一下在复杂多变的业务场景下,高层模块直接依赖低层模块细节时意味着什么?
首先需要明确的一点是,高层模块包含了一个应用程序的重要策略选择和业务模型,也可能是系统对外提供服务的接口层,从系统设计者或使用方的角度看,都希望更能重用高层的策略模块。而低层模块更多的是为高层实现业务逻辑提供支撑。然而如果高层依赖于低层模块的实现细节,那么低层的改动就会直接影响到高层,不同的上下文中重用高层模块也会变得十分困难。这就好比一个人考下了驾照,却只会开奔驰,不会开宝马一样荒谬。
如果高层模块独立于低层模块,那么高层模块就可以非常容易被重用。
对上面的例子而言,如何使用依赖导致原则来改善设计呢?可以看下面这张图:
在这张图中,每个较高层次都为它需要的服务声明了一个抽象接口,较低的层次实现了这些抽象接口,每个高层类都通过抽象接口使用下一层,这样高层就不再依赖于低层。低层反而依赖于高层中声明的抽象服务接口,低层的任何内部改动都不会影响高层的逻辑实现,解除了不同层级之间的强耦合依赖关系。
为什么依赖倒置原则被称为好莱坞原则?
好莱坞原则的表述为:Don't call us. We'll call you. 在好莱坞中,演员把简历递交给演艺公司后就只有回家等待。由演艺公司实现对流程的完全控制,演员只能被动式的接受公司的差使。在特定演出环节中,完成自己的表演。
好莱坞原则强调高层对低层的主动作用,即低层应该只管好自己的工作(具体实现),而高层自有它自己的工作(业务的核心流程策略),在不需要到某个低层的时候,高层并不会调用到这个具体低层,低层永远不需要向高层作出表示。这与依赖倒置原则的核心思想不谋而合,基本所有框架设计的背后思想都是好莱坞原则。
依赖倒置原则的实现思路
最直接的一个启发性规则就是:“依赖于抽象”,也就是说,程序中所有的依赖关系都应该终止于抽象类或者接口,由此可以引申出:
类中的任何变量都不应该持有一个指向具体类的指针或者引用。
不同的实体类包之间必须仅通过接口或抽象类进行连接。如:
任何类都不应该从具体类进行派生。
任何方法都不应该覆写它的任何基类中已经实现的方法。
所有变量的实例化都要依赖于一类对象创建模式,如工厂模式,或使用依赖注入框架。
说起来容易,但在实际项目开发过程中,很难做到完全遵守这些原则。受限于:
业务和团队成员的快速迭代,原有的优良设计思路难以长时间持续,一个需求把控不严可能就导致整体代码结构进入腐化期。
缺乏系统性思考设计出来的接口往往形同鸡肋。初期过度设计,后期业务进入维护期,导致代码中大部分接口都只有一个实现类,变成为了面向接口而面向接口,反而降低了开发和调试效率。
个人感觉MVP(最小可用版本)+持续重构,可能是比较好的思路。上面依赖倒置的启发性原则可以作为一种极限思考场景,指导重构工作向正确方向进行。
Spring如何实现依赖倒置原则?
可参考:https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/html/beans.html
评论 (1 条评论)