领域驱动模型(DDD)学习笔记

本文详细探讨了领域驱动设计(DDD)在业务中的应用,涵盖了DDD架构风格、模块划分、关键概念如领域实体、值对象和事件,以及基础设施层的实现。通过实例和学习资源,帮助读者理解和实现场景中的DDD设计。

在复杂的业务中,DDD正在逐步取代MVC模型,下面就让我们一起来认识一下领域驱动模型(DDD)。

一、DDD架构风格

DDD架构

COMMUNITY系统架构整合了六边形架构、RESTful架构风格、CQRS架构风格三种架构风格,并遵循经典的分层架构思想。

  • User Interface —— 用户接口层。对外提供各种协议形式的服务,并提供Validation参数校验,authenticate权限认证,业务实体组装器Assembler等。图中标绿组件。
  • Application —— 应用服务层。组合多个业务实体、基础设施层的各种组件完成业务服务。图中标黄部分。
  • Domain —— 业务领域层。DDD概念中的核心业务层,封装所有业务逻辑,包含entity、value object、domain service、domain event等。图中标蓝部分。
  • Infrastructure —— 基础设施层。提供公共组件,如:Logging、Trascation、HttpClient等。图中标灰部分。

二、DDD架构实现图

架构实现

1. User Interface层

1.1 DTO

包括request和response两部分,通过它定义入参和出参的契约,在dto层可以使用基础设施层的validation组件完成入参格式校验;

1.2 controller

支持不同访问协议的控制器实现,比如:http/restful风格、tcp/二进制流协议、mq消息/json对象等等。

controller使用基础设施层公共组件完成许多通用的工作:

调用RequestMapping(SpringMVC公共组件)完成servlet路由;
调用checklogin完成登录态/权限校验;
调用logging组件完成日志记录;
调用message-resource组件完成错误信息转义,支持I18N;

2. Application层

2.1 service

应用服务层,组合domain层的领域对象和基础设施层的公共组件,根据业务需要包装出多变的服务,以适应多变的业务服务需求。

应用服务层主要访问domain领域对象,完成服务逻辑的包装。

应用服务层也会访问基础设施层的公共组件,如rabbitmq,完成领域消息的生产等。

2.2 assembler

组装器,负责将多个domain领域对象组装为需要的dto对象,比如查询帖子列表,需要从Post(帖子)领域对象中获取帖子的详情,还需要从User(用户)领域对象中获取用户的基本信息。

组装器中不应当有业务逻辑在里面,主要负责格式转换、字段映射等职责。

3. Domain层

业务领域层,是我们最应当关心的一层,也是最多变的一层,需要保证这一层是高内聚的。确保所有的业务逻辑都留在这一层,而不会遗漏到其他层。按照ddd(domain driven design)理论,主要有如下概念构成:

3.1 domain entity

领域实体。有唯一标识,可变的业务实体对象,它有着自己的生命周期。比如社区这一业务领域中,‘帖子’就是一个业务实体,它需要有一个唯一性业务标识表征,同时他的状态和内容可以不断发生变化。

3.2 domain value object

领域值对象。可以没有唯一性业务标识,且一旦定义,他是不可变的,它通常是短暂的。这和java中的值对象(基本类型和String类型)类似。比如社区业务领域中,‘帖子的置顶信息’可以理解为是一个值对象,不需要为这一值对象定义独立的业务唯一性标识,直接使用‘帖子id‘便可表征,同时,它只有’置顶状态‘和’置顶位置‘,一旦其中一个属性需要发生变化,则重建值对象并赋值给’帖子‘实体的引用,不会对领域带来任何负面影响。

3.3 domain factory

领域对象工厂。用于复杂领域对象的创建/重建。重建是指通过respostory加载持久化对象后,重建领域对象。

3.4 domain service

领域服务。区别于应用服务,他属于业务领域层。

可以认为,如果某种行为无法归类给任何实体/值对象,则就为这些行为建立相应的领域服务即可。比如:转账服务(transferService),需要操作借方/贷方两个账户实体。

传统意义上的util static方法中,涉及到业务逻辑的部分,都可以考虑归入domain service。

3.5 domain event

领域事件。领域中产生的一些消息事件,通过事件通知/订阅的方式,可以在性能和解耦层面得到好处。

3.6 repository

仓库。我们将仓库的接口定义归类在domain层,因为他和domain entity联系紧密。仓库用户和基础实施的持久化层交互,完成领域对应的增删改查操作。

仓库的实际实现根据不同的存储介质而不同,可以是redis、oracle、mongodb等。

鉴于现在社区服务的存储介质有三套:oracle、redis、mongodb,且各个存储介质的字段属性名不一致,因此需要使用translator来做翻译,将持久化层的对象翻译为统一的领域对象。

3.7 translator

翻译器。将持久化层的对象翻译为统一的领域对象。

翻译器中不应当有业务逻辑在里面,主要负责格式转换、字段映射等职责。

4. Infrastructure层

基础设施层提供公共功能组件,供controller、service、domain层调用。

4.1 repository impl

对domain层repository接口的实现,对应每种存储介质有其特定实现,如oracle的mapper,mongodb的dao等等。repository impl会调用mybatis、mongo client、redis client完成实际的存储层操作。

4.2 checkLogin

权限校验器,判定客户端是否有访问该资源的权限。提供给User Interface层的Controller调用。

4.3 exception

异常分类及定义,同时提供公共的异常处理逻辑,具体由ExceptionHandler实现。

4.4 transport

transport完成和第三方服务的交互,可以有多种协议形式的实现,如http+json、tcp+自定义协议等,配套使用的还有Resolver解析器,用于对第三方服务的请求和响应进行适配,提供一个防腐层(AnticorruptionLayer,DDD原书P255)的作用。

4.5 transcation

提供事务管理,交给Spring管理。

4.6 logging

日志模块,记录trace日志,使用log4j完成。

4.7 message resource

消息资源管理,交给Spring统一管理。

三、模块结构示例

1. 模块结构图

模块实例

  • factory是专职为model服务的,因此放入对应的entity的modle package中;
  • domain.repository包里面只有仓库的接口定义,实际的实现交给了infrastrcture中的repository module,该做法被称作"依赖倒置",好处在于确保domoain层语义完整,同时对确保业务领域的一致性也有帮助,再者可以在domain实现内存形式的repository哑实现,从而让domain可以真正脱离掉infrastructure;
  • translator module正常情况下不需要,但在重构老系统时,往往需要隔离掉存储模型对业务模型的影响,使用translator来讲存储模型翻译为业务模型;
  • infrastructure.repository作为仓库层,会将实体的增删改查操作委托给具体的存储层服务,如oracle对应的mapper实现,mongodb对应dao实现,还有redis的实现;
  • COMMUNITY中domain event的生产者和消费者实现均交给infrastructure.rabbitmq package实现。

2. 各层详解

2.1 UI层

UI层详解博客地址

2.2 Application层

Application层详解博客地址

2.4 Domain层

Domain层详解博客地址

四、案例资料

1. 学习资源

领域驱动设计实践

2. Github地址

使用DDD实现社区服务系统示例代码

五、结束语

非常感谢大佬倒骑的驴带给我们这么多资料,希望大家都能学有所成,向大佬学习!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郭建華

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值