DDD和功能解耦

如果无法正常显示,请先停止浏览器的去广告插件。
分享至:
1. DDD和功能解耦 京东 7FRESH 阎华
2. 1. 2. 3. 4. 5. 为什么选择DDD DDD和系统解耦 DDD和统一语言 总结
3. 我们为什么选择DDD Y轴扩展性成为瓶颈 领域模型不合理 这意味着Y轴的扩展要灵活 低内聚高耦合 影响Y轴扩展的两个因素
4. 我们为什么选择DDD 问题一:领域模型不合理 错误的 数据结 构 错误的 业务约 束 产品经理关注上层的业务流程和交互 缺乏业 务语义 的模型 没有发 现隐式 的概念 程序员关注技术实现
5. 我们为什么选择DDD 数据格式由 B来定义 问题二:系统功能间的各种耦合 A B不需要 B需要 B B A的数据 耦合的类型 A B Data Coupling Stamp Coupling A B需要 Content Coupling A B 全局数据 Common Coupling
6. 但是DDD落地很难
7. 让整个团队弄清楚复杂而抽象的方法论,太难了
8. 那怎么办? 简化,小步,例子多
9. 而是面向对象分析和设计 最先要普及的不是DDD
10. | 二十多年前人们就推崇用值对象了 | 那时DDD还没有诞生 丰富的表 达力 比如电话号码的 校验 https://riehle.org/computer- science/research/1998/ubilab-tr-1998-10-1.html 不可变性 带来的线 程安全 Primitive Obsession | 基本类型偏执 | 2000年 这种坏味道是指用基本类型 来表示领域概念,比如用字 符型来表示电话号码、邮政 编码等 解决办法是定义明确 ValueObject 。 集中的合 法性校验 和易测试 性 后面会有实际的 例子 封装带来 的设计柔 性 降低认知负担提升 可读性
11. | 实体和聚合早就被广泛认可了 富血模型 | Since |1997年 贫血模型
12. | 很多原则和模式在系统级别依旧有效 设计原则 •依赖倒置 •开放封闭 •单一职责 •信息隐藏 •…… 设计模式 •工厂 •适配器 •策略 •状态 •…… 架构模式 •分层架构 •整洁架构/洋葱模型 •端口适配器架构 •CQRS •……
13. | 面向对象富血模型没落史 | 背后的驱动力 专业的单机软件向以数据为中心的网络软件的演变 | 1980s,Smalltalk/C++ 带领下面向对象广泛流行 | 1991,Visual Basic 出现属性和属性列表功能 | 1992-1995,可视化工具和IDE遍地开花 | 1996,JDK1.0发布 | 1997,JavaBean规范发布 | 1998 -,Java和.NET平台出现大量的通过反射 | 机制处理对象属性的工具和框架 FROM 《实现领域驱动设计》
14. 理论上,使用DDD并不一定要通过面向对象, 但实战中,使用面向对象进行分析设计是最务实的。 那么,DDD在面向对象之外还带来了哪些新的东西?
15. 首先要理解的是 限界上下文 该了解些DDD 最核心的概念了
16. | 案例分析1:概念不能穿透上下文 1 3 2 除了更好的表意性外 有更好的扩展性
17. | 案例分析1:变化控制在局部 代码不用变 RPC API Controller 企业客户适配器 领域层 业务逻辑 数据库 用户适配器 RPC API适配器 企业客户适配器 u 只有适配器部分的代码需要变化,包含业务逻辑的领域层代码不需要变化 u 通过编译器的静态类型检查,适配器的变化点很容易识别 u 适配器充当防腐层(ACL),起到了概念隔离和功能解耦的作用
18. | 案例分析2:上下文关系和Common Coupling 读取订单上的标记 WMS TMS 交易服务 订单 订单生产 控制中心 餐饮 “订单标记委员会” 分布式大泥团系统的守护神 按各系统的需要 生产订单时 在订单上打标记 读取订单上的标记 读取订单上的标记 读取订单上的标记 购物卡 标记太多位,含义二义性, 新增需求改动的系统太多, 影响范围难以界定,沟通成 本非常高……
19. | 案例分析2:上下文关系和Common Coupling 自己领域的 守护神 U 交易服务 WMS D D U TMS U 订单 U D 订单生产控制 D 中心 U 餐饮 D U 自己领域的 守护神 自己领域的 守护神 自己领域的 守护神 U 购物卡 D,下游; U,上游 自己领域的 守护神 清晰的上下文映射关系, 下游理解上游的领域概念, 上游不理解下游的领域概念, 上游制定标准, 下游适配标准。 * 在 DDD 的上下文映射中,我们优先使 用这种 “ 客户 - 供应商 ” 的模式。
20. | 案例分析2:进一步要避免的问题 上游“老好人”,边界没守住,造成Stamp Coupling 下游要保持独立性,需要使用适配器/防腐层 数据 TMS 不需要 D WMS TMS 需要 D U TMS WMS TMS产品研发 WMS产品研发 U TMS TMS产品研发 WMS产品研发
21. | 案例分析1&2:系统间的依赖倒置/ACL保证Data Coupling 下游定义的接口 (D)下游 (U)上游 适配上下游接口的实现 领域层 业务逻辑 数据库 API Controller RPC 用户适配器 API适配器 领域层 业务逻辑
22. | 案例分析3:上下文级贫血和Control Coupling 1.获取订单数据 做逻辑判断 外部调用或消息 订单生产控制 中心 外部调用或消息 订单 订单生产控制 中心 2.设置订单状态 3.操作其它系统 1.给订单状态机 输入可枚举 的事件 2.监听得到订单 状态的变化 3.操作其它系统 订单
23. | 案例分析4:聚合根的作用 聚合根是一组实体和值对象的一致性边界。 在这个边界之内维护不变条件,即业务规则。 这不是DDD引入的新原则,聚合就该如此。 DDD的新原则包括: n 通过唯一标识引用其他聚合 n 在边界之外使用最终一致性(比如通过领 域事件),一个事务只能修改一个聚合 聚合的识别很难,领域事件、领域服务和 CQRS的正确应用可以减少技术因素对聚合 根识别的干扰。 这样做的好处是能更好地支持架构的演进
24. 其次要理解的是 统一语言 该了解些DDD 最核心的一些概念了
25. | 物理世界在不同上下文代表着 | 不同的概念 | 领域太复杂,只有在分割的上下文内 | 才可能形成统一的语言 店 仓 拣货打包车间 厨房
26. | 使用事件风暴形成统一语言 隐形概念的挖掘,聚合根的识别等都非常难且难以达成一 致,仅仅在方法论上达成一致还不够,我们需要一种容易 执行的工具 • • • • 让开发者做回正常人 控制节奏,慢下来很难但很重要 学会问问题,挖掘隐形概念 命名很难,那就随便给个名字先达成一致 统一语言的形成
27. | 代码和分析模型的低表示差异 业务模型和业务逻辑都在这里 值对象 聚合根 领域事件 普通实体 Repository接口 和技术相关的实现 Repository实现 应用服务 应用服务应该很“薄”
28. | 没有一个完美的ORM可以用 JPA/Spring-Data-JDBC 富血,但性能不可控 JDBC/MyBatis 性能可控,贫血 RoR/Domain注入Repo(AspectJ ),貌似解决以 上问题,但污染领域模型 | 用JPA来实现,好处/坏处: • • • 富血模型 ✔ 聚合根的原则 ✔ 但带来了糟糕的或不可控的性能 ✘
29. | 权衡 应用层 的方法 聚合根助手 的方法 聚合根的方 法 • 应用层尽可能薄,不包含领域层的业务逻辑 • 每个聚合根配一个无状态的助手,和聚合根一起体现 所有的领域业务逻辑 • 如果开始分不清代码放在哪一层,可以先实现然后通 过重构渐进下沉
30. 界定上下文并明确其间的关系 挖掘领域知识,识别隐型概念, 定义聚合根,形成团队理解一致的统一语言 让代码尽可能和分析模型保持一致 未必能尽善尽美,但可以不断趋近
31. THANKS

Home - Wiki
Copyright © 2011-2024 iteam. Current version is 2.139.0. UTC+08:00, 2024-12-22 14:36
浙ICP备14020137号-1 $Map of visitor$