架构将大问题分解为容易处理的小问题。——《架构师修炼之道 》
重量级 DDD 更多的是结合现状 + 未来出发,更多的人参与,提供准确的信息。轻量级 DDD 则是通过现状,只需要少数熟悉的人,没有完成一致的达成,通过持续性赋能 改善模型。
产品线 / 业务线来说,并非每一个子系统都是核心域,也不会投入大量的人和精力在上面。特别是,当你在重构的时候,投入的人员和精力不足以实施一个合理的事件风暴,以完成对应的领域驱动设计活动。所以,我们只能尽可能完善系统的设计。
高质量级 DDD 重构:演进驱动的事件风暴
它意味着,重构时需要有:
- 积极专注的团队参与
- 复杂的场景
- 领域专家参与协作
- 迭代式的模型设计
为此需要:
- 事件风暴
- 识别上下文
- 梳理上下文关系
- 划分问题子域
- 识别弹性边界
- 领域建模
- 分层架构
对应的我们需要:
- 重搭架构
- 编写集成测试
- 搬移代码
- ……
考虑到其复杂性,我建议采用《事件风暴设计工作坊》来完成相关的流程。
轻量级 DDD 重构:现状驱动的领域方案
有意思的一个现象是,在真正落地的时候,对于核心的系统往往会抱着比较谨慎的态度 —— 除非原来的模式真的有问题。又或者是,所处的部门不是系统的核心部门时,在投入在会出现一定的问题。
看图:
相应的步骤如下:
- 结合工具识别所有的接口
- 通过接口识别出领域名词(聚合、实体等)
- 分析接口设计是否合理
- 通过领域名词划分上下文边界
- 重新定义领域名词
- 结合领域名词划分新的 API
- 划分领域和分层架构
- 重新划分分层架构
- 重构 service 代码,剥离领域逻辑
- 重构代码到领域模型
对于未采用 Swagger 等 API 管理工具的项目,可以通过 coca api
生成 API 列表:
GET /aliyun/oss/policy
POST /aliyun/osscallback
GET /subject/list
GET /esProduct/search
GET /order/list
GET /productAttribute/list/{cid}
GET /productCategory/list/{parentId}
GET /brand/list
GET /esProduct/search/simple
...
限界上下文要素
包含相关上下文的:
- 实体(entity)。只要一个对象在生命周期中能够保持连续性,并且独立于它的属性(即使这些属性对系统用户非常重要),那它就是一个实体。它具有唯一标识和生命周期。
- 值对象(value object)。当你只关心某个对象的属性时,该对象便可作为一个值对象。它是实体的附加业务概念,用来描述实体所包含的业务信息。
- 领域服务(domain service)。封装了没有在模型中自然建模为值对象或实体的领域逻辑和概念。它的主要职责是使用实现和值对象编排业务逻辑。
- 领域事件(domain event)。它用于表明问题域中发生了一些业务人员关心的事情。在命名领域事件时,我们往往选择动词的过去分词,以明确表达事件的属性,其中文形式往往是『XXX已YYY』。
- 资源库(repository)。公开聚合根在内存中的集合的接口,提供聚合根的检索和持久化需要。
- 工厂(factory)。即在实体或者值对象创建复杂时,可以委托给工厂(模式)进行创建。。
- 聚合(aggregate)。是一种边界内的领域对象的集群,可以将其视为一个单元。可以封装一个到多个实体与值对象,用来维护该边界范围之内的业务完整性。
微服务重构
一旦涉及到对微服务进行重构的时候,我们有很大的可能性要对系统进行 API 的重构设计。它也意味着,我们可能会影响到 API 的使用方,如果 API 也是自己内部的系统,那么问题就不是太大;如果 API 的使用方是第三方团队的系统时,我们就需要考虑一下兼容方案。这种兼容方案会在一定程度上影响到我们的重构,甚至于我们有可能不对做这方面的重构。
重构到微服务是一个巨大的挑战。
微服务是一个生态系统,它需要大量的基础设施进行配合,如部署管道、服务注册与发现、日志和监控、负载均衡等。
如果团队本身没有相关的经验,并且尝试往上调整的话,那么需要在心理上做好大量的准备。
如果你的目标是重构到微服务架构,那么我建议你先重构到 DDD + 整洁架构,它是微服务架构的一个中间态。即,先看看容器架构重构。
……
待定。由于笔者在这方面的经验不是非常丰富,但是我知道这里仍然有非常多的内容,可以探索。
下一节:我在设计之初,想把标题改为容器架构重构,它对应上 C4 模型。纠结之后,我还是改为了服务架构。可见,命名之难。