依赖分析之后,你的架构还好吗?
在过去的几周里,我一直在做一些重构相关的工作,也尝试着去做这方面的自动化。于是乎,就有了上一篇文章:《重构的自动化》。在这个过程中,有一个环节能反应出架构是否有良好的设计,那就是依赖。
对于一个系统来说,它存在下述的一些依赖类型:
按《架构金字塔》一文所说,它们各属于不同层级。设定好它们间的组织方式,决定了整个系统架构的良好性。
在架构的维度里,我们通过 MVC 架构、Clean Architecture 等不同的方式,进行分层架构的设计,以通过明确地职责划分、隔离关注点,来降低系统的维护成本。如果水平维度不能解决问题,那么就采用水平 + 垂直化的方式来解决。在依赖维度里,我们通过度量来观察设计的合理性。
对于类和包的依赖来说,一个有效的解决方案是:对于依赖关系的可视化。如下图(由 tequila + graphviz 生成):
在图中,我们可以看出类间的依赖关系,从而进一步分析他们的引用问题。虽然,对于采用分层架构的应用来说,这样的问题并不容易出现。但是,我们仍在一定的范围内,看到了 service 间的相互调用。
于是,在参考了公司大佬的开源依赖分析项目:
随之而后,我便也着手做了一个相关的 Java 依赖分析工具: https://github.com/phodal/coca 。当然在那之前,我已经有了一个 TypeScript 的版本: https://github.com/phodal/dilay ,只不过目的不一样,我的初衷是用于做架构守护。
对于这样的一个工具说,我们所要作的事情也不复杂:
一旦出现服务间的双向/循环引用,我们需要着力于关注如何去掉这种错误的引用。去掉的方式有多种多样,诸如于:合并包/服务、提取共用部分。
包大小,在出现性能或者网络问题之前,并不会成为我们关注的焦点。可一旦包的大小超过了预期,我们开始分析其中的原因。可视化,依然是解决这一类问题的最有效方式。
对于诸如 JavaScript/TypeScript 这一类的静态语言来说,它们引用包的方式与其它语言有很大的差距。前端领域的引用方式,多数以源码的方式,而诸如 Java 则是以 jar 包的方式。于是,前端应用在构建的时候,前端可以通过摇树优化来减少包大小。但是哪怕如此,一定数量的软件包只能引用全部的代码,这种模式通常出现在前端 UI 库中,如 Ant Design。
对于这些问题来说,前端有一个解决方案:webpack-bundle-analyer,它可以直接可视化软件包的大小:
当然了,对于后端来说,这也不是问题。只是对于我来说,我仍然在考虑是否有必要去做这样的事。不过呢,如果你引用了一个自己内部的软件包,那么我们有必要写一个软件来做这样的优化:
O 了。
不过,这个故事还涉及到一个 API 规范化的问题。所以在那之前,我们需要:
有了这个基本的的结果后,判定每个 API 的设计是否合理。与此同时,我们还可以: 通过调用关系,找到 API 对应的数据库表,生成相应的 Schema。
随后,再:
它可以固定作为我们测试的一部分。
TBD
这部分的内容,主要指的是依赖间的功能重复,如各类 Util,像 FileUtils,TimeUtils 诸如此类。
你呢,有什么建议?