网站首页 > 博客文章 正文
"在实际项目中,领域驱动设计(DDD)往往像'对对对'设计 —— 道理我都懂,但落地还是迷糊。"
作为一名后端开发者,你是否曾经有过这样的困惑:DDD概念听了一堆,事件风暴、聚合根、领域服务、防腐层...术语记了一大堆,但真正写代码时却不知从何下手?
本文将从一线研发的角度,为你梳理DDD架构的实战落地方法。
一、解构DDD的核心价值
在开始详细讨论各层职责前,我们需要明确DDD的核心价值:它不仅仅是一种架构模式,更是一种思考问题的方式。
传统的开发往往按技术职责分层(控制器、服务、DAO),而DDD则按业务领域进行划分。这种思路转变带来的好处是:
- 代码结构与业务语言保持一致,新人可以更快理解业务逻辑
- 降低跨领域耦合,避免意大利面条式代码
- 面向对象设计的回归,告别贫血模型
二、DDD项目层次解构
Alibaba COLA架构给我们提供了一个很好的DDD实践模板,下面让我们剖析每一层的职责和代码归属。
1. 领域层 (Domain) - DDD的核心
"如果系统只能保留一层,那么就保留领域层。"
领域层包含核心业务逻辑,与技术实现无关,具有以下特性:
public class WorkOrder {
private String workOrderId;
private String initiatorId;
private WorkOrderContent content; // 值对象
private WorkOrderStatus status; // 值对象
// 领域行为
public static WorkOrder start(String initiatorId, WorkOrderContent content) {
// 业务逻辑实现...
return new WorkOrder(...);
}
public void handle() {
this.status = WorkOrderStatus.HANDLING;
this.processTime = new Date();
}
public void finish(WorkOrderHandleResult result) {
// 状态转换逻辑...
}
}
领域层设计要点:
- 业务对象分为实体(有ID和生命周期)和值对象(无ID,不可变)
- 实体和聚合根拥有业务行为,不是简单的getter/setter
- 定义仓储接口,但不实现
- 不依赖任何外部模块
2. 基础设施层 (Infrastructure)
基础设施层负责与技术细节打交道,实现领域层定义的接口。主要包含:
@Repository
public class WorkOrderRepositoryImpl implements WorkOrderRepository {
@Autowired
private WorkOrderMapper workOrderMapper;
@Override
public void save(WorkOrder workOrder) {
// 将领域对象转换为数据库实体并保存
WorkOrderDO workOrderDO = converter.to(workOrder);
if (workOrderDO.getId() == null) {
workOrderMapper.insert(workOrderDO);
} else {
workOrderMapper.updateById(workOrderDO);
}
}
@Override
public WorkOrder get(String workOrderId) {
// 查询并转换回领域对象
return converter.from(workOrderMapper.selectById(workOrderId));
}
}
基础设施层要点:
- 实现领域层定义的仓储接口
- 处理ORM映射、中间件交互
- 只依赖领域层,不依赖应用层
- 隐藏技术实现细节
这一层的设计让系统核心业务逻辑不会因为技术选型变化而改变 —— 想从MySQL换到MongoDB?只需修改基础设施层实现。
3. 应用层 (Application)
应用层是系统的指挥中心,协调各领域完成业务用例:
@Service
public class WorkOrderAppService {
@Autowired
private WorkOrderService workOrderService;
@Autowired
private NotificationService notificationService;
@Transactional
public WorkOrderDTO createWorkOrder(WorkOrderCreateCommand command) {
// 1. 调用领域服务创建工单
WorkOrder workOrder = workOrderService.startOrder(
command.getUserId(),
new WorkOrderContent(command.getType(), command.getDescription())
);
// 2. 发送通知
notificationService.notifyNewWorkOrder(workOrder);
// 3. 转换结果
return converter.toDTO(workOrder);
}
}
应用层要点:
- 定义系统用例和业务流程
- 协调多个领域服务
- 处理事务边界
- 依赖领域层和基础设施层
4. 适配层 (Adapter)
适配层负责处理外部请求,相当于传统MVC中的Controller:
@RestController
@RequestMapping("/api/workorders")
public class WorkOrderController {
@Autowired
private WorkOrderAppService workOrderAppService;
@PostMapping
public Result createWorkOrder(@RequestBody @Validated WorkOrderCreateRequest request) {
WorkOrderCreateCommand command = converter.toCommand(request);
WorkOrderDTO dto = workOrderAppService.createWorkOrder(command);
return Result.success(dto);
}
}
适配层要点:
- 参数校验
- 权限控制
- 异常处理
- 结果封装
- 只依赖应用层
5. 客户端层 (Client)
客户端层主要用于SDK封装,供其他系统调用:
public interface WorkOrderClient {
WorkOrderDTO createWorkOrder(WorkOrderCreateRequest request);
WorkOrderDTO getWorkOrder(String workOrderId);
}
客户端层要点:
- 定义RPC接口
- 封装请求和响应模型
- 不依赖其他层
- 可以包含错误码定义
三、实战案例:工单管理系统
让我们通过一个工单系统的例子,看看DDD是如何落地的:
1. 领域建模
首先识别关键概念:
- 实体:工单(WorkOrder)
- 值对象:工单内容(WorkOrderContent)、工单状态(WorkOrderStatus)、处理结果(WorkOrderHandleResult)
- 领域行为:发起工单、处理工单、完成工单、驳回工单
2. 聚合设计
// 工单聚合根
public class WorkOrder {
private String workOrderId; // 唯一标识
private String initiatorId;
private Date startTime;
private WorkOrderContent content; // 值对象
private WorkOrderStatus status; // 值对象
private WorkOrderHandleResult result; // 值对象
// 工厂方法
public static WorkOrder start(String initiatorId, WorkOrderContent content) {
// 创建工单逻辑
}
// 领域行为
public void handle() {
// 处理工单逻辑
}
public void finish(WorkOrderHandleResult result) {
// 完成工单逻辑
}
public WorkOrder reject() {
// 驳回工单逻辑
}
}
3. 领域服务
public interface WorkOrderService {
WorkOrder startOrder(String userId, WorkOrderContent content);
void processOrder(WorkOrderHandleResult result, String handlerId, String workOrderId);
void completeOrder(String workOrderId);
WorkOrder rejectOrder(String workOrderId, String reason);
}
4. 仓储接口
public interface WorkOrderRepository {
void save(WorkOrder workOrder);
WorkOrder get(String workOrderId);
List findByStatus(WorkOrderStatus status);
}
四、DDD落地实践指南
经过多个项目的实践,我总结了几点关键经验:
1. 循序渐进的领域建模
不要试图一开始就做完美的领域模型。先从核心业务场景出发,识别主要实体和值对象,逐步完善:
- 列出核心业务术语和概念
- 确定实体和值对象
- 定义实体间的关系
- 划分聚合边界
- 确定领域服务
2. 聚焦业务语言
确保代码中的命名与业务专家使用的术语一致,这是DDD的精髓之一:
// 不好的命名
public void process(String id, int type) {}
// 好的命名(体现业务语义)
public void approveExpenseReport(String reportId, ApprovalLevel level) {}
3. 避免过度设计
不是所有概念都需要用上:
// 过度设计
class ExpenseReportFactory {
public static ExpenseReport create() {
return new ExpenseReport();
}
}
// 简单直接
ExpenseReport report = new ExpenseReport();
4. 关注边界上下文
识别系统中的不同上下文,并在上下文之间建立防腐层:
五、DDD常见误区
- 过度使用贫血模型:实体类只有getter/setter,业务逻辑全部放在服务中
- 领域层依赖基础设施:在实体中直接调用Repository
- 混淆DTO和领域对象:直接将DTO传入领域层
- 忽略值对象:所有概念都建模为实体
- 过度拆分微服务:盲目按DDD划分的聚合来拆分服务
总结
DDD不是银弹,也不需要在所有项目中全面应用其概念。关键是根据项目复杂度选择合适的实践程度:
- 对于简单CRUD系统,完全可以采用轻量级的分层架构
- 对于复杂业务系统,充分利用DDD的聚合、领域服务等概念
最后,记住Eric Evans的一句话:"DDD关注的是解决领域复杂性,而非技术复杂性。"
正如文章《从Alibaba-Cola到DDD,一线研发对领域驱动的思考》中所说,没有最好的架构,如果能通过合理编排层次实现代码解耦,代码易读,这就是一种好设计,好架构。
你的团队在实施DDD时遇到过哪些挑战?欢迎在评论区分享你的经验!
猜你喜欢
- 2025-04-05 云计算(3)- python routes URL映射管理
- 2025-04-05 每一个软件或者网站都会有这个让人恶心但又不可或缺的功能
- 2025-04-05 彻底理解Java反射以及动态代理中对反射的应用
- 2025-04-05 自定义代码生成器(上)(自定义代码块的作用)
- 2025-04-05 使用 Spring AI 和 DeepSeek 快速构建本地 AI 对话系统
- 2025-04-05 从数据库行锁到分布式事务:电商库存防超卖的九重劫难与破局之道
- 2025-04-05 SpringBoot系列-项目常用分层结构
- 2025-04-05 MyBatis的SQL执行流程不清楚?看完这一篇就够了
- 2025-04-05 如何深度理解mybatis?(如何深度理解两个必然与两个绝不会的科学性和合理性)
- 2025-04-05 高并发下实现幂等的几种方式(并发和幂等)
你 发表评论:
欢迎- 07-07Xiaomi Enters SUV Market with YU7 Launch, Targeting Tesla with Bold Pricing and High-Tech Features
- 07-07Black Sesame Maps Expansion Into Robotics With New Edge AI Strategy
- 07-07Wuhan's 'Black Tech' Powers China's Cross-Border Push with Niche Electronics and Scientific Firepower
- 07-07Maven 干货 全篇共:28232 字。预计阅读时间:110 分钟。建议收藏!
- 07-07IT运维必会的30个工具(it运维工具软件)
- 07-07开源项目有你需要的吗?(开源项目什么意思)
- 07-07自动化测试早就跑起来了,为什么测试管理还像在走路?
- 07-07Cursor 最强竞争对手来了,专治复杂大项目,免费一个月
- 最近发表
-
- Xiaomi Enters SUV Market with YU7 Launch, Targeting Tesla with Bold Pricing and High-Tech Features
- Black Sesame Maps Expansion Into Robotics With New Edge AI Strategy
- Wuhan's 'Black Tech' Powers China's Cross-Border Push with Niche Electronics and Scientific Firepower
- Maven 干货 全篇共:28232 字。预计阅读时间:110 分钟。建议收藏!
- IT运维必会的30个工具(it运维工具软件)
- 开源项目有你需要的吗?(开源项目什么意思)
- 自动化测试早就跑起来了,为什么测试管理还像在走路?
- Cursor 最强竞争对手来了,专治复杂大项目,免费一个月
- Cursor 太贵?这套「Cline+OpenRouter+Deepseek+Trae」组合拳更香
- 为什么没人真的用好RAG,坑都在哪里? 谈谈RAG技术架构的演进方向
- 标签列表
-
- ifneq (61)
- 字符串长度在线 (61)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)