Blog

Blog

PHODAL

自动化依赖分析

依赖分析之后,你的架构还好吗?

在过去的几周里,我一直在做一些重构相关的工作,也尝试着去做这方面的自动化。于是乎,就有了上一篇文章:《重构的自动化》。在这个过程中,有一个环节能反应出架构是否有良好的设计,那就是依赖。

依赖的类型

对于一个系统来说,它存在下述的一些依赖类型:

  • 类、包依赖
  • 第三方依赖
  • 服务间依赖

按《架构金字塔》一文所说,它们各属于不同层级。设定好它们间的组织方式,决定了整个系统架构的良好性。

  • 类、包依赖。通过职责来聚合服务,单一化类的职责。
  • 第三方依赖。通过 Adapter 模式封装三方依赖,隔离外部依赖的变化;还可以通过 Facde 模式来简化 API 的调用。
  • 服务间依赖。类似于第三方依赖,只是在接口统一不变时,是 Proxy 模式

在架构的维度里,我们通过 MVC 架构、Clean Architecture 等不同的方式,进行分层架构的设计,以通过明确地职责划分、隔离关注点,来降低系统的维护成本。如果水平维度不能解决问题,那么就采用水平 + 垂直化的方式来解决。在依赖维度里,我们通过度量来观察设计的合理性。

类包依赖:依赖关系可视化

对于类和包的依赖来说,一个有效的解决方案是:对于依赖关系的可视化。如下图(由 tequila + graphviz 生成):

在图中,我们可以看出类间的依赖关系,从而进一步分析他们的引用问题。虽然,对于采用分层架构的应用来说,这样的问题并不容易出现。但是,我们仍在一定的范围内,看到了 service 间的相互调用。

于是,在参考了公司大佬的开源依赖分析项目:

  • 基于 Antlr 进行 Java 依赖分析 https://github.com/XuefengWu/dependence_java
  • 基于 Doxygen 进行多种语言的依赖分析 https://github.com/newlee/tequila

随之而后,我便也着手做了一个相关的 Java 依赖分析工具:https://github.com/phodal/coca 。当然在那之前,我已经有了一个 TypeScript 的版本:https://github.com/phodal/dilay ,只不过目的不一样,我的初衷是用于做架构守护。

对于这样的一个工具说,我们所要作的事情也不复杂:

  • 编写特定语言的抽象语法树(AST)和 parser
  • 构建出每个类包含的所有声明,生成对应的映射
  • 识别出依赖相关的 method、type、class、constant 的使用
  • 生成对应的调用关系
  • 可视化调用关系

一旦出现服务间的双向/循环引用,我们需要着力于关注如何去掉这种错误的引用。去掉的方式有多种多样,诸如于:合并包/服务、提取共用部分。

第三方:包大小可视化

包大小,在出现性能或者网络问题之前,并不会成为我们关注的焦点。可一旦包的大小超过了预期,我们开始分析其中的原因。可视化,依然是解决这一类问题的最有效方式。

对于诸如 JavaScript/TypeScript 这一类的静态语言来说,它们引用包的方式与其它语言有很大的差距。前端领域的引用方式,多数以源码的方式,而诸如 Java 则是以 jar 包的方式。于是,前端应用在构建的时候,前端可以通过摇树优化来减少包大小。但是哪怕如此,一定数量的软件包只能引用全部的代码,这种模式通常出现在前端 UI 库中,如 Ant Design。

对于这些问题来说,前端有一个解决方案:webpack-bundle-analyer,它可以直接可视化软件包的大小:

当然了,对于后端来说,这也不是问题。只是对于我来说,我仍然在考虑是否有必要去做这样的事。不过呢,如果你引用了一个自己内部的软件包,那么我们有必要写一个软件来做这样的优化:

  1. 构建时识别软件引用的类与方法
  2. 依赖识别的类,将软件包不需要的部分自动去除
  3. 重新打包依赖软件包
  4. 构建整个应用

O 了。

服务间:API 规范化与服务间依赖

不过,这个故事还涉及到一个 API 规范化的问题。所以在那之前,我们需要:

  1. 通过扫描代码来寻找对外暴露的 API。生成对应的 API 与参数关系列表

有了这个基本的的结果后,判定每个 API 的设计是否合理。与此同时,我们还可以:通过调用关系,找到 API 对应的数据库表,生成相应的 Schema。

随后,再:

  1. 扫描调用的 API。生成调用服务的关系图
  2. 分析服务调用关系,及其调用是否合理。

它可以固定作为我们测试的一部分。

第三方依赖:依赖功能分析

TBD

这部分的内容,主要指的是依赖间的功能重复,如各类 Util,像 FileUtils,TimeUtils 诸如此类。

结论

你呢,有什么建议?

关于我

Github: @phodal     微博:@phodal     知乎:@phodal    

微信公众号(Phodal)

围观我的Github Idea墙, 也许,你会遇到心仪的项目

QQ技术交流群: 321689806
comment

Feeds

RSS / Atom

最近文章

关于作者

Phodal Huang

Engineer, Consultant, Writer, Designer

ThoughtWorks 技术专家

工程师 / 咨询师 / 作家 / 设计学徒

开源深度爱好者

出版有《前端架构:从入门到微前端》、《自己动手设计物联网》、《全栈应用开发:精益实践》

联系我: h@phodal.com

微信公众号: 最新技术分享

标签