DDD分层架构实践

如果无法正常显示,请先停止浏览器的去广告插件。
分享至:
1. DDD分层架构实践 吴仁润 2022.08 美团优选事业部
2. 个人介绍 吴仁润 美团技术专家 2016年加入美团,负责过多个业务商品系统建设,有 较丰富的复杂业务建模及系统建设经验
3. 面向领域的分层架构 API API 图例: 工程模块 三方组件 依赖关系 数据交互 DTO Server BO BO Domain BO Domain Model Infrastructure Thrift Application 单元测试 Domain 单元测试 Application Domain Model Spring 集成 BO Application 组件1 Server Mybatis Kafka (mock) (无需mock) 组件2 Infrastructure Infrastructure Redis 测试 ES 以业务为核心,业务和技术关注点分离的分层架构 …… Mike Cohn 《Scrum 敏捷软件开发》 • 明确分层架构各层的职责,规范分层依赖关系 • 业务逻辑不依赖技术细节,业务逻辑高度可测 • 多组件模式解决复杂展示和丰富领域逻辑的冲突
4. 目录 1. 传统分层架构 2. DDD 分层架构 3. 分层架构实践
5. 传统分层架构 Server层 Server层 Service层 Business层 Dao层 Service层 Dao层 三层架构 四层架构 大多数Jave EE应用的实际架构标准
6. 传统分层架构特点 用户接口层 Controller Value Object 业务逻辑层 Service Business Object 数据访问层 Mapper Persistent Object 数据存储层 MySQL Redis • 各层相互隔离 • 请求自上而下 特点:各层间关注点分离
7. 传统分层架构痛点 用户接口层 用户接口层 3 层?4 层?还是? 业务逻辑层 业务逻辑层 业务服务层 • 层太多会增加不必要的开支 数据访问层 难点:建立哪些层次及每层的职责 数据访问层 MySQL • 层太少导致关注点不够分离 MySQL
8. 传统分层架构痛点 用户接口层 分层架构的原则:每层只能与其下方的层耦合 业务逻辑层 业务服务层 数据访问层 MySQL • 严格分层架构 • 松散分层架构 问题:传统分层架构各层间存在依赖传递
9. 传统分层架构新问题 技术复杂度 业务复杂度 业务逻辑 技术实现 团队规模 技术实现 交付周期 软件复杂度 人员流动 问题:MongoDB 下线导致线上故障 原因:业务逻辑和 MongoDB 的读写耦合在一起导致修改出问题 技术复杂度和业务复杂度会以不同速率发生变化
10. 传统分层架构总结 用户接口层 集成测试 单元测试 业务逻辑层 (不做mock) 成本 单元测试 (mock) 业务服务层 Alister Scott 「冰淇淋蛋筒」反模式 数据访问层 单测覆盖率极低,质量很难保证 MySQL 存在问题 • 分层标准缺少 • 各层传递依赖 适用场景 • 业务逻辑简单 • 技术组件稳定 • 发布频率不高
11. 目录 1. 传统分层架构 2. DDD分层架构 3. 分层架构实践
12. DDD分层架构-明确层次职责 用户接口层 明确各层的职责 层次 应用层 用户接口层 领域层 基础设施层 Eric Evans 《领域驱动设计》 职责 负责向用户(人或其他服务)展现信息以及解释用户命令 应用层 负责协调应用的活动,它不包含业务逻辑、不保留业务对象的状态,但它可以保 有应用任务的进度状态 领域层 负责表达业务概念、业务状态信息以及业务规则,本层是业务软件的核心。业务 对象及它们状态的持久化由基础设施层实现,但是反映业务情况的状态是由本层 控制并且使用的 基础设施层 负责为应用层传递消息,为领城层提供持久化机制,为用户界面层的提供支撑 库,本层作为其他层的支撑库存在 问题:传递依赖导致业务对象依赖于外部系统或框架
13. DDD分层架构-明确层次依赖 基础设施层 用户接口层 应用层 + 依赖倒置 = 用户接口层 领域层 基础设施层 Eric Evans 《领域驱动设计》 应用层 领域层 Vaughn Vernon《实现领域驱动设计》 高层模块不应该依赖于低层模块,两者都应该依赖于抽象
14. DDD 分层架构实现-面向接口设计 用户接口层 Controller RPCService SpringController ThriftService 应用层 ApplicationServic e Producer MafkaProducer 领域层 Model 抽象 Repository • 输入依赖 基 础 设 施 层 MySQLRepository 细节 抽象不应该依赖于细节,细节应该依赖于抽象 • 不太稳定 • 输出依赖 • 相对稳定
15. DDD 分层架构实现-职责拆分 用户接口层 Controller RPCService SpringController ThriftService 应用层 ApplicationServic e 单一职责 Producer MafkaProducer 领域层 Model 抽象 接口 实现 层 Repository MySQLRepository 细节 用户接口和基础组件的变化速率不一致 基础 设施 层
16. DDD 分层架构实现-总结 domain domain application infrastructure api server 后端服务 infrastructure application server WEB服务 分层架构应用于单体服务,使用 jar 作为分层的最小单位 图例: 依赖 实现
17. 目录 1. 传统分层架构 2. DDD 分层架构 3. 分层架构实践
18. 领域层 代码组织形式 PK • 数据模型 + Service • id brand_id feature_id feature_value_id … PK 1 : n n • 贫血模型 + Service 充血模型(领域模型) brand brand_feature_relation : 1 brand_feature brand_feature_value PK id feature_id feature_value_id feature_value_name … id feature_id feature_value_name … PK n : 1 id feature_id feature_name …
19. 数据模型 + Service 优点 数据模型 • 数据驱动,模型简单 • 映射数据库表成本低 缺点 • 灵活性与可扩展性欠缺 业务逻辑就是操作数据 一个模型代表数据库中的一个表
20. 贫血模型 + Service 优点 数据 业务逻辑 setter 更新对象 对象只包含数据 业务逻辑通过 Service 类实现 通过 setter 方法更新领域对象 • 模型可重用、可扩展 缺点 • 映射数据库表成本高 • 业务逻辑代码重复
21. 充血模型(领域模型) 数据 行为 优点 • 业务逻辑收敛 数据 行为 缺点 • 建模复杂度高 每一个对象都承担一部分业务逻辑 通过对象方法更新领域对象的数据 • 需要转变思维模式
22. 抉择 决策点 数据模型 贫血模型 增 加 的 工 作 量 领域模型 业务逻辑的复杂度 Martin Fowler 《企业应用架构模式》 • 业务逻辑的复杂度 • 开发人员 OOP 熟练度
23. 应用层 1. 处理基础设施问题 • 应用层校验 • 事务 • 错误处理和错误转换 • 日志、指标和监控 • 认证和授权 • 通信 2. 协调完整的业务用例 关键点:应用服务中不能包含业务规则
24. 应用服务 领域逻辑 VS 应用逻辑 应用服务是⻔面(Facade)模式的体现 • 应用服务里的步骤能否分开 发布商品信息 三个领域行为需同时执行, 组合逻辑为领域逻辑 发布商品 组 合 发布价格 • 应用服务是对领域逻辑的编排 三个领域行为可各自执行, 组合逻辑为应用逻辑 发布商品 领域层 组 合 发布价格 发布库存 发布库存 应用层 发布商品信息 应用层 领域层
25. 传统分层架构演进 用户接口层 用户接口层 业务逻辑层 应用层 接口+业务模型 依赖 实现 接口+业务模型 用户接口层 应用层 业务逻辑层 接口+业务模型 依赖 领域层 业务服务层 接口+领域模型 依赖 实现 数据访问层 接口+领域模型 依赖 依赖 实现 接口+业务模型 实现 实现 接口+领域模型 基础设施层 用户接口层 领域层 接口+领域模型 数据访问层 实现 基础设施层 实现 实现 保持依赖关系不变,分离业务与技术实现 保持依赖关系不变,拆分领域逻辑与应用逻辑,同时分离业务与技术实现 将技术实现迁移至基础设施层,改变模块依赖关系 将应用逻辑与领域逻辑拆分到应用层与领域层 将技术实现迁移至基础设施层,改变模块依赖关系
26. 复杂业务读写冲突 同一个领域模型难以同时满足读写场景 • 查询需求(读)可能与事务性操作(写)的模型不一致 • 查询的使用频率比写入端高 领域模型是为了在处理事务性操作(写)时强制执行该领域的不变条件
27. 解决之道 - CQRS CQRS CRUD 操作 R CUD 命令/领域模型 聚合 事件 查询模型 事件处理 程序 聚合 CUD命令端 数据库 写 模 型 查询端数据库 读 模 型 读 写 模 型 分 离
28. 读写分离的分层架构 API 图例: 工程模块 三方组件 依赖关系 数据交互 DTO Server BO Application • 读模型可以绕过领域模型直接读取数据库以 Application 提供更好的性能 BO Domain 写 • 创建读写两个上下文(模型),关注点分离 层次依赖 BO Domain Model 单一职责 BO Domain Model Infrastructure 读 Infrastructure 保障单体到微服务架构的平滑演进 Spring Thrift Mybatis Redis Kafka ES ……
29. 总结 接口层 应用层 业务层 集成测试 单元测试 (不做mock) 单元测试 (mock) 接口层 集成 测试 应用层 单元测试 (mock) 领域 单元测试 (无需mock) 业务层 基础设施层 DDD分层架构 传统分层架构 • 分层标准缺少 • 各层传递依赖 • 业务逻辑不可测 • 分层标准明确 • 技术业务分离 • 业务逻辑高度可测 提升系统的稳定性和扩展性
30. Q&A
31. 更多技术干货 欢迎关注“美团技术团队” 【后台开发&系统开发】岗位 正在热招

Home - Wiki
Copyright © 2011-2024 iteam. Current version is 2.137.1. UTC+08:00, 2024-11-17 18:49
浙ICP备14020137号-1 $Map of visitor$