软件设计原则的应用

在上一篇《软件设计原则》中我们介绍了面向对象原则、组件设计原则以及其他一些原则,本篇主要介绍这些软件设计原则的具体应用。主要以组件设计原则在Dubbo中的应用来展示软件设计原则中的分包原则如何在一个分布式服务器框架中发挥指导性的设计作用。

Dubbo(http://dubbo.io/)是Alibaba开源的一个分布式服务框架,在互联网行业应用和扩展十分广泛。Dubbo的核心功能为我们进行分布式系统设计提供了两大方案,即高性能和透明化的RPC实现方案和服务治理方案。

(1)组件设计原则背后的量化标准

在组件设计原则中我们提到一个稳定抽象原则,即组件的抽象程度应该与其稳定程度保持一致。组件的稳定度可以用以下公式来衡量:

I = Ce / (Ca + Ce)

其中Ca代表Afferent Coupling,即向心耦合,表示依赖该组件的外部组件数量,而Ce代表Efferent Coupling,即离心耦合,表示被该组件依赖的外部组件的数量。I代表Instability,即不稳定性,它的值处于[0,1]之间。如果一个组件的Ce=0那么不稳定性I=0,说明它非常稳定。相反,如果一个组件的Ce=3,Ca=0,那么它的不稳定性I=1,说明它非常不稳定。下图展示的是一种更常见的场景,沿着依赖的方向,组件的不稳定性应该逐渐降低,稳定性应该逐渐升高。如果已经处于稳定状态的组件就不应该去依赖处于不稳定状态的组件。

另一方面,组件的抽象度也同样存在类似的计算公式:

A = Na / Nc

其中A代表Abstractness,即抽象度。Na表示组件中抽象类的数量,而Nc表示组件中所有类的总和,这样通过对比Na和Nc就能简单得出该组件的抽象度。

正如上图所示,一个系统中多数的组件位于依赖链的中间,也就是说它们即具备一定的稳定性也表现出一定的抽象度。而在下图中,如果一个组件的稳定度和抽象度都是1,意味着该组件里面全是抽象类且没有任何组件依赖它,那么这个组件就没有任何用处。相反,如果一个组件稳定度和抽象度都是0,那么意味着这个组件不断在变化,不具备维护性,这也是我们不想设计的组件。所以,在稳定度和抽象度之间我们应该保持一种平衡,在下图中间的那个线就是平衡线。

我们用距离的概念来量化这种平衡,距离(Distance)的计算公式:

D = abs(1 - I - A) * sin(45)

距离的图形化表示参考下图。

(2)Dubbo中的分包原则

Dubbo在设计过程中同样采用的是稳定抽象和稳定依赖等原则,下图展示的就是Dubbo中各个包之间的依赖关系,除了dubbo.common通用工具包之外,处于依赖关系底层的dubbo.remoting包和dubbo.rpc包是整个框架中的高层抽象。

通过JDepend等工具对Dubbo中的这些包依赖关系进行分析,我们可以得出下图中所示的距离效果。我们可以看到Dubbo中的多数包结构在稳定性和抽象性之间达到了一种平衡。

基于以上结果,我们再对Dubbo的代码结构做进一步分析,Dubbo的代码结构对应于下图中的组件分层。其中,protocol层和proxy层放在rpc模块中,构成rpc核心,不考虑集群环境,可以只使用这两层完成RPC调用;remoting模块实现Dubbo协议,transport层和exchange层都放在remoting模块中,如果不使用dubbo协议,则该层不会使用;serialize层放在common模块中以便更大程度复用;registry和monitor实际上不算一层。

Dubbo的组件体现了功能演进思想,首先protocol是核心层,构成RPC基础组件,如果不需要达到透明化调用效果,使用protocol层就可以实现低层次的远程方法调用;在protocol基础之上,添加proxy封装透明化动态代理,调用远程方法就如同调用本地方法;透明化调用实现之后,就需要考虑负载均衡和集群容错机制,cluster层承载了这方面的功能;registry和monitor提供服务路由和治理相关辅助功能。而在现有各种序列化工具的基础上为了提升网络传输性能和扩展功能,remoting层实现了自定义dubbo协议作为整个框架的一大扩展点。

 

如果对文章感兴趣,可以关注我的微信公众号:程序员向架构师转型,或扫描下面的二维码。

我出版了《系统架构设计:程序员向架构师转型之路》、《向技术管理者转型:软件开发人员跨越行业、技术、管理的转型思维与实践》、《微服务设计原理与架构》、《微服务架构实战》等书籍,并翻译有《深入RabbitMQ》和《Spring5响应式编程实战》,欢迎交流。

发布了92 篇原创文章 · 获赞 9 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/lantian08251/article/details/98948336