如何可视化的表达 DDD 的模型?

做完 DDD 的建模工作,或者事件风暴工作坊后,往往会有朋友会问,如何方便的表示模型和维护模型呢?

使用自己定义的图块,太过于随意;使用 UML 又显得繁琐,又有大量的人唱衰 UML。

我曾陷入无休无止的对工具的选择中,最终意识到克制和取舍才是问题的答案 —— 没有终极的解决方案。

模型,是用来表达和理解复杂的软件业务的,简洁明了意味着信息的丢失,追求准确和细致,必然需要面对繁复和难以维护的问题。

1. 如何取舍模型中的信息?

我想用 DDD 模型指导我的开发工作:数据库设计、代码分包、Restful API 设计等工作。

模型中的上下文会在单体中设计包,而聚合会和 Service 的组织有关系,于是我需要关心模型的上下文、模型的关系。

而属性不是我关心的,而且会干扰对模型的理解。

UML 是一个大的工具箱,如果我们想明白我们需要什么样信息,去 UML 找对应的工具即可。

想看清系统业务结构基本元素需要:

  • 上下文。可以使用 namespace 来表达,表示相对隔离的概念空间。
  • 模型。可以使用类图来表达,代表业务中可被操作的实体。
  • 关系。由于模型都是被动操作对象(业务客体),业务模型可以只使用组合即可,避免使用 UML 中的 6 种关系,弄得复杂。
  • 聚合。聚合代表一组强关联和具有一致生命周期的一组模型,可以使用 UML package 来表达。
  • 实体值对象。实体、值对象和聚合根本质是模型的不同形态,在编写代码时需要注意,在 UML 中可以不表达出来。

有一些信息会对模型的视图干扰,不推荐表达出来:

  • 属性。过于细节,不利于模型的维护,会让视图过大而看不清。
  • 工作坊的中间产物。比如事件、角色等信息,如果需要表达,可以使用其他图形来表达,否则含混不清。

2. PlantUML 简介

代码的维护和持续演进比“完美”的初始设计更为重要。

将模型文件放入代码仓库,随代码维护,并每个迭代演进,有非常重要的意义。但是需要让图形能用代码表示,做到 Diagram As Code,便于版本管理。

PlantUML 是一个用代码驱动绘图的 UML 工具,就这一点就足以够让其他的 UML 工具相形见绌。

PlantUML 使用 Java 编写, 可以通过命令行、Jar 包、插件等多种途径使用,不过一般常见的使用方式有两种:

  1. 使用在线绘图工具。用于临时和同事讨论问题,也可以把绘制好的内容通过链接发送给其他人。
  2. 使用 IDE 插件。直接将 UML 模型在 IDE 中渲染为图形。

使用在线绘图工具

使用官网的在线绘图工具 http://www.plantuml.com/plantuml/uml

编写 UML 表达式后点击 submit 即可生成 UML,并带有一个带有绘图信息的链接。

使用 IDE 插件

如果你使用的 IntelliJ IDEA,可以在 Preferences 菜单下的 Plugins 搜索 PlantUML integration,安装重启 IDE 即可。

image-20210204232444997

在项目中添加后缀为 puml 的文本文件即可使用。

3. 使用示例

这里使用一个互联网内容社区应用(UCG)作为示例,做了一些简化,设计好的模型大致为:

  • 用户上下文,包含用户聚合、角色聚合。
  • 内容上下文,包含专题、分类、文章聚合。

可以如下表示上下文、聚合和实体的关系,得到一个非常简洁的模型图。

@startuml
namespace UserContext {
    package User <<Aggregate>> {
        User  --> UserRole
        User --> UserAttribute
        User --> UserPreference
    }
namespace UserContext {
    package Role <<Aggregate>> {
        class Role
    }

namespace ContentContext{
    package Category <<Aggregate>> {
        Category  --> CategoryTag
    }
namespace ContentContext{
    package Topic <<Aggregate>> {
        Topic  --> TopicArticle
    }
namespace ContentContext{
    package Article <<Aggregate>> {
        Article --> ArticleMeta
    }
@enduml

渲染好的效果如下:

PlantUML diagram

可以清晰的看明白模型、聚合,以及他们所处上下文的关系,也可以在代码仓库中被很好的管理。

参考文档可以做出更多特性的图表来,比如增加模型之间的关系数量,是一对多还是多对多。

@startuml
namespace UserContext {
    package User <<Aggregate>> {
        User "1" --> "*" UserRole
        User --> UserAttribute
        User --> UserPreference
    }
@enduml

PlantUML diagram

评论已关闭