写点什么

面向对象设计的逆向建模方法和开源工具

作者:高鹏
  • 2023-06-26
    北京
  • 本文字数:3666 字

    阅读完需:约 12 分钟

面向对象设计的逆向建模方法和开源工具

导读

软件开发不仅仅是业务交付的生产过程,本质上是系统化的知识工程,大型复杂软件开发的核心难点是如何处理隐藏在业务知识中的核心复杂度,除了清晰地理解业务诉求之外,还需要通过建模的方式对这种复杂度进行简化与精炼。作为软件交付最终产品的代码,由于具有(可运行,包含完全细节,演进过程完整追溯,自我修复)特点而成为业务的唯一事实真相,但代码如何以易于理解的形式直观反映业务知识一直是业界难题。本文提出了一种低成本易实施的逆向建模方法,目标是让业务开发从模型中来回到模型中去,并提供了 Java 版开源工具进行快速实施。

一、背景及相关工作

1.1 普遍痛点

业务系统在人员交替,资料不全,代码堆砌,业务野蛮扩张的过程中,不断加深了软件复杂度的治理难度,从产品讲不全业务背景,沟通不全产品能力,研发对于业务逻辑看不懂改不动,到上线频繁出现业务场景缺失验证等问题。不仅加剧了产研交付周期,从需求吞吐量来说也逐步下降,只留下产研团队在艰难的维护,制约了创新产品和业务的发展。

在业务开发过程中,普遍重视实现思维,轻视认知思维:在拿到需求后,不去深度思考并还原业务真相,而是基于碎片化的 PRD 进行基于表象的Functional Decomposition,这加重了代码的腐化,后果就是:复用性差,不具有可组合性,封装性差,代码里看不到业务,只看到大量技术抽象出来的过程方法等实现逻辑细节,基于代码梳理业务的过程苦不堪言。

1.2 认识业务建模

解决复杂度的根本方法是系统思维,系统思维是一种综合性的思考方法,它强调整体性、关联性和长期性,可以帮助人们更好地理解和处理复杂的问题。系统思维的核心是将问题看作一个系统,系统由多个元素组成,这些元素之间存在着相互作用和反馈,它们共同构成一个复杂的整体。业务建模是系统思维的重要组成部分,是普遍认可的解决复杂度的有效方法。

建模(Modeling),是通过可视化抽象,将客观事物或规律转换为模型表达,从而便于进一步研究、传播、讨论的过程。

业务建模,是站在企业高度,抛弃无关细节、认清问题域本质、揭示其内在规律的过程,并把这些规律以易于理解、传播、讨论的简化、直观、精炼形式显性表达,从而提升决策效率和解决未来变化的问题。把握规律可以看到业务全貌,改进优化,预测未来,挖掘隐性需求,进而引领业务。

DDD 的模型本质上是领域知识模型,功能是表象,模型才是内在。好的模型可以改善我们的认知,降低复杂性,提升对于变更的适应性,提升演进能力。领域知识是指在特定领域内所需要的知识和技能,具体包括了:领域背景(历史,发展,趋势,文化,社区),领域业务(业务流程/流程间依赖关系,业务对象、对象间关系、业务规则、应用场景等),领域技术,领域人员。业务规则是对企业或组织业务过程的约束条件,它描述了业务流程的各种限制、规范和条件。业务规则通常是由法律、政策、行业标准、企业内部规章制度等产生的,可以用来约束业务流程的各种行为和决策。


业务建模(Business Modeling)是以软件模型方式描述企业管理和业务所涉及的对象和要素、以及它们的行为、属性和彼此关系,业务建模强调以体系的方式来理解、设计和构架企业信息系统。─ 百度百科

1.3 正向和逆向建模

  • 正向建模:从需求到代码的过程

  • 传统的建模方法(事件风暴,四色建模,流程建模,对象建模,ER)等都属于正向建模

  • 但它们无法保持与代码的持续一致

  • 逆向建模:从代码到模型的过程

  • 自动生成业务洞见,还原架构和设计,识别代码设计缺陷为重构提供依据和方向,知识管理和传承

  • 为需求分析提供依据


基于代码的逆向建模是一种软件开发中的技术,主要用于分析、理解和改进现有代码。

1.4 业界研究

二、开源工具

2.1 schemaspy

schemaspy,能连接数据库并自动生成 schema 报告,生成的报告示例:


它只能说是一个数据库的逆向分析工具,还不能称为逆向业务建模工具,此外,表之间的关系是依靠外键约束来识别的,而互联网行业普遍在业务代码里实现约束,而不是数据库,即它无法识别出表之间关系。

2.2 OpenTracing

分布式链路追踪,像 Zipkin/Skywalking/Pinpoint 等开源项目,都能在运行时绘制 call graph,在问题追踪、宏观了解应用间交互时是很好的工具。

但它不能称为逆向业务建模工具,无法体现业务知识,只能反映出技术视角。

2.3 DddDiagram

DddDiagram,是一个 IntelliJ IDEA 插件,分析代码里的 ValueObject、Entity、DomainEvent、Specification、Repository、DomainService、Factory 等元数据并自动生成类图,它要求代码严格使用 DDD 开发,目前只是一个原型。

2.4 DDDplus

DDDplus,是一个开源的轻量级 DDD 增强框架,它同时提供了正向和逆向业务建模支撑,本文只涉及逆向建模部分。

It captures DDD missing concepts and patches the building block. It empowers building domain model with forward and reverse modeling. It visualizes the complete domain knowledge. It connects frontline developers with (architect, product manager, business stakeholder, management team). It makes (analysis, design, design review, implementation, code review, test) a positive feedback closed-loop. It strengthens building extension oriented flexible software solution. It eliminates frequently encountered misunderstanding of DDD via thorough javadoc for each building block.


In short, the 3 most essential plus are:

  1. provide extension point with multiple routing mechanism, suited for complex business scenarios

  2. patch DDD building blocks for pragmatic forward modeling, clearing obstacles of DDD implementation

  3. offer a reverse modeling DSL, visualizing complete domain knowledge from code

三、DDDplus 逆向建模

DDDplus的逆向建模,是以DSL为基础的,通过代码里加DSL标注来指导自动生成业务模型,它是基于 Java AST 静态分析的过程。

3.1 DSL 的模型表达性

是否能完整表达业务知识,是核心。

3.1.1 粒度问题

  • 技术上,支持包级、类级、方法级、字段级的细粒度

  • 业务上,表达了业务对象、业务对象关系、业务属性,业务行为、业务规则、业务事件、业务流程、用户交互、业务边界等业务模型要素

业务属性示例,DDDplus 把字段进行了分类:

业务行为示例:

业务对象关系示例:

业务规则示例:

业务边界示例:

业务事件示例:


3.1.2 召回率问题

DDDplus 自动生成 DSL 标注的覆盖率,以发现重要业务模型要素被遗漏。

3.1.3 持续一致问题

DSL 毕竟是代码之外的元数据,仅为逆向模型使用,因此在项目演进过程中可能出现:代码改了,而对应的 DSL 标注忘记修正。

3.1.4 Garbage in Garbage out 问题

代码写的很差,就无法建立好的逆向模型吗?这是DDDplus要解决的首要问题。它通过面向对象思想把行为与业务对象在模型层面进行绑定,而不受限于代码结构。

3.1.5 成本问题

DDDplus逆向建模的成本体现在:

  1. 通过DSL进行标注的成本

  2. 标注后的维护成本

笔者在一个 20 万行代码的项目上进行逆向建模,花了近 1 天时间,主要时间花在对代码进行模型修正上。

3.1.6 对代码的假设

DDDplus逆向建模对代码的唯一假设是 Java 语言,是否使用 DDD、是否面向对象并无要求。

3.2 如何集成

git clone https://github.com/funkygao/cp-ddd-framework.git dddpluscd dddplusmvn install
复制代码

本地安装好后,集成到你的代码库:

<dependency>    <groupId>io.github.dddplus</groupId>    <artifactId>dddplus-visualization</artifactId>    <version>2.0.0-SNAPSHOT</version>    <scope>test</scope></dependency>
复制代码

通过单元测试自动触发逆向建模是常用的方法:

class ReverseModelingTest {    @Test    void reverseModeling() {        DomainModelAnalyzer domainModelAnalyzer = new DomainModelAnalyzer();        ReverseEngineeringModel domainModel = domainModelAnalyzer.scan("{your module root}")            .analyze();        new PlantUmlBuilder()            .build(domainModel)            .renderSvg("myModel.svg"); // 相比png,svg支持文本搜索    }}
复制代码

至此,集成工作就完成了。为了让你的代码更忠实体现出你的业务模型,接下来需要在代码里通过DSL进行标注。

3.3 正逆一体流程

DDDplus 的逆向建模,会生成两个文件:

  • svg 文件:使用者包括(业务方,架构师,产品经理,测试,研发)

  • 纯文本文件:使用者包括(架构师,研发)

通过这个过程,实现我们的目标:让业务开发从模型中来回到模型中去

3.4 实际项目效果

基于隐私考虑,这里无法提供详细的细节。

用户头像

高鹏

关注

Explore, Define and Solve problems 2018-10-18 加入

还未添加个人简介

评论

发布
暂无评论
面向对象设计的逆向建模方法和开源工具_架构_高鹏_InfoQ写作社区