DDD之MEES架构设计方法

1,463 阅读5分钟

DDD在项目中能落地吗?在CQRS和Event Sourcing之外还有什么设计方法?InMemory和 InDatabase架构风格是什么?

InMemory架构风格

DDD领域驱动开发是一种In Memory架构风格,Memory架构风格的意思就是以计算机“内存”作为主要资源进行软件设计的方式,与之对应的就是Database数据库架构风格,典型的是以ER图(实体关系图)作为主要设计方式的设计方法。

架构风格特点
Memory架构风格以面向对象设计为基础,针对业务对象、数据实体或业务行为等进行业务建模,主要采用设计模式、DDD等设计方法
Database架构风格以数据关系设计为基础,针对业务过程中的数据结构和表关系等进行数据建模,主要采用ER图、关系数据库表等设计方法

DDD中的CQRS和Event Sourcing就是两种Memory架构风格的设计方法。

贫血模型VS富血模型

Memory架构设计风格中,最典型的冲突点就是贫血模型与富血模型,

模型描述
贫血模型强调符合JavaBean规范,Java数据对象符合JavaBean规范,业务行为放到Service类中实现,导致模型类只包含setter/getter无业务行为
富血模型强调面向对象设计方法,拿人作为类比,人是具有属性和行为的复合体,所以模型类应该既包含数据又包含业务行为

绝大多数的项目采用的都是“贫血模型”,在这个争论点提出来后,我们也怀疑过贫血模型是否是个问题,但是在项目实践中将数据与行为同时放到一个对象(类)中,会导致非常难于维护的代码和坏味道。甚至为了解决这个冲突点出现过动态Mix类属性和行为的方法,不过难以使用。

在经过长期实践后发现贫血或富血并不是一个问题,而是随着软件业务的复杂性提升和计算机硬件的成本降低,架构设计的长期趋势已经从数据库为中心转换为以内存业务模型为中心的设计。

MEES架构设计方法

MEES: Model Enhance Event Service。模型增强事件服务架构。 MEES是一种类似CQRS和EventSourcing并且基于InMemory架构风格的架构模式,该架构模式的设计视图如下。

image.png

MEES架构设计过程:

  1. 基于业务中抽象领域模型,定义为Model模型
  2. 每个Model模型对应单独ModelDecorator,装饰器类承载模型对象的业务逻辑行为
  3. 领域Gateway通过Model模型调用Decorator进行业务处理
  4. Event事件处理后通过发布订阅Pub/Sub方式通知相关Model模型进行状态State更新
  5. 通过Service实现技术功能逻辑,实现业务逻辑和技术逻辑的简单解耦,比如Service可以调用Database实现数据的持久化管理

基于DSL的MEES设计过程

MEES设计方法特别适用于使用DSL领域特定语言的开发场景,Dockerfile可以认为是一种DSL,下面用Dockerfile举例MEES架构设计过程。

任何业务如果可以使用一种DSL语言描述,都适用于此架构设计方法。

DSL业务定义语言

FROM centos
ENV NODE_VERSION 7.2.0
RUN yum -y install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz
RUN echo 'hello world'

模型Model设计

模型职责
领域GatewayDockerfile领域聚合根,命令执行入口
实体模型From模型定义
实体模型Run模型定义
实体模型Env定义

增强模型Decorator设计

装饰器主要业务行为
FromFromDecorator获取中央仓库镜像
RunRunDecorator执行参数本地命令
EnvEnvDecorator设置全局参数

事件Event设计

依据Dockerfile的业务执行过程,排除模型Build过程外,可以抽象如下几个事件用于触发模型运行。

事件业务行为
RunEvent模拟docker命令运行dockerfile
StateEvent获取容器运行状态

服务Service设计

服务技术行为
命令服务ShellService用于执行OS命令
仓库服务RepoService用于HTTP加载远程镜像
消息服务MsgService用于消息的发布订阅Pub/Sub

架构设计视图View

基于以上的设计过程,MEES开发架构定义如下 image.png

示例代码

MEES架构设计产生的代码样例如下,通过Builder模式加载DSL实例后,首先通过将Event传递给领域Gateway触发模型运行,然后Model模型通过注册表Registry查询对应Decorator,再次通过Decorator实现业务层面逻辑,最后调用Service实现技术功能层面逻辑。

var docker = DockerfileBuilder.builder(file).build(){
   from:Model
   env:List<Model>
   run:List<Model>
   registry:List<ModelDecorator>
   
   init(){
       from.subscribe(DownloadedMessage){
           for(r: run){
              var deco = registry.findDeco(r)
              deco.execute(this){
                 shellService.execute(cmd)
              }
           }
       }
   }
}
docker.handle(e:StateEvent){
   return this.run
}
docker.handle(e:RunEvent){
   var deco = registry.findDeco(this.from)
   deco.download(){
      repoService.download(from)
      if(downloaded){
         message.publish(DownloadedMessage())
      }
   }
}

总结

DDD方案技术方案特点
MEES基于结构模式,基于Model定义Decorator增强模型方案
CQRS基于行为模式,一般采用管道过滤器技术架构
EventSourcing基于数据模式,一般是定义事件数据链结构

结构化架构设计

  1. 架构设计是个问题
  2. 架构设计=架构+设计
  3. 模型映射设计方法
  4. 产出物是设计视图
  5. 架构风格和模式
  6. 领域模型服务
  7. 架构设计画板