DDD战略建模在重构业务系统时的实践

2020-02-23 256浏览

  • 1. DDD战略建模 在重构业务系统时的实践 韩宇斌 罗辑思维-得到后端业务线Leader
  • 2.
  • 3.
  • 4. 韩宇斌 • Business Dev 现就职于罗辑思维得到后端,听书方向的技术负责人,擅长利用 DDD 和 OO 思想 对业务需求进行分析建模与设计开发。 • 在好大夫在线负责电话咨询业务时,创新了“不挂机切换会议室”的业务流程并技 术实现,极大提高了运营的工作效率并节省成本,荣获优秀员工。 • 在 ToB 类软件公司担任过开发和项目经理,具有从客户原始需求转换成可落地的技 术设计并实施的经历;在 ToC 类互联网公司一线负责过许多类型各异的业务系统, 能够深入理解业务目标并落地。
  • 5. 得到App && 听书
  • 6. • DDD战略建模在重构业务系统时的实践 一. 用领域驱动来把握真正的业务需求 二. 领域驱动设计指导架构设计与建模 三. 用限界上下文来保护领域
  • 7. 领域驱动设计帮住我解决了工作的难题 无路可退 :入职第一个任务 左右为难 :实现技术重构的目标,满足不了业务需求! 不去实现,又不知道该做什么?
  • 8. 背景知识:商家视角的电商业务基本流程 卖货 收钱 发货 算账
  • 9. 得到app电商业务涉及的组织和系统 卖货 收钱 发货 算账
  • 10. 得到app目前如何确认收入 下单 收钱 发货 订单记录 支付记录 权益记录 OrderId ✅ 损失或呆账 OrderId 严格匹配 OrderId ✅ 确认收入
  • 11. 谁还没有个过去 收钱 支付记录 收了钱没发货? ✅ 损失或呆账 严格匹配? 发货 权益记录 财务:没有 订单,出了 问题我信谁? 发货了没收钱? ✅ 确认收入
  • 12. 没有订单时,听书业务实现售卖流程的调用关系
  • 13. 没有订单时,听书业务实现所有售卖流程的调用关系
  • 14. 财务: 必须记录订单及交易状态 下单 CreateOrder 订单记录 OrderId ✅ 损失或呆账 收钱 PayOrder 支付记录 OrderId 严格匹配 发货 SignOrder 订单化 权益记录 OrderId ✅ 确认收入
  • 15. 实现了“订单化”后的调用关系
  • 16. 实现了“订单化”后,依赖与耦合加剧
  • 17. 原系统架构的问题很快暴露 订单加个“签收时间”字段 20多天才能上线 投入与收益不匹配!
  • 18. 财务:尽快把所有交付内容都接入“订单化” 如果再有修改, 怎么办? 内部实现个系统, 代理全部“订单化”相关的功能, 这样再有修改,只改这个代理服务就行了! 实现隔离变化!
  • 19. 接到的重构任务: 订单代理(订单化)系统 实现 一个代理服务, 对接 交易平台组的订单系统和基础平台组的支付系统, 推动 若干个业务系统改造,改成调用新的代理服务。
  • 20. 订单代理系统如何隔离变化
  • 21. “同时满足”了业务需求和技术目标 业务需求:所有的商品都实现“订单化” 技术:不光都实现“订单化”,我们还实现个“订 单化的代理系统”,应对外部系统的变化。
  • 22. 方案确定了! 但这是业务的目标吗?
  • 23. 实现“订单化”并不是业务的真正需求 开发最关心的是 业务关心的是 完成全部商品的订单化, 一定要正确的交付(面向现在), 实现订单代理系统, 能够高效准确的算账(面向未来), 降低业务系统与外部系统的耦合 把过去的账给解释 清楚(面向过去) 订单代理系统的目标在财务那里只是个过程! 真正的业务需求是什么???
  • 24. 面临的挑战 无路可退 :入职第一个任务 左右为难 :实现“订单代理系统”,满足不了业务需求! 不去实现“订单代理系统”,那该做什么?
  • 25. 没有把握真正需求的原因
  • 26. 领域驱动设计的工作方式 • 全程强调“领域”的开发过程 • 需求 = 问题域+业务期望 • 统一语言:领域通用语言 • 用领域模型指导设计及编码实现
  • 27. 一定要正确的交付权益(面向现在) 能够高效准确的算账(面向未来) 把过去的账给解释 清楚(面向过去) • 问题域:电商的发货与算账 • 业务期望:精确交付
  • 28. 理解“订单化”在需求中的作用和意义
  • 29. 提炼和理解一些“统一语言”
  • 30. 领域驱动设计,找到真正的业务需求 订单代理系统 财务核算级别的精确交付
  • 31. 一. 用领域驱动来把握真正的业务需求 二. 领域驱动设计指导架构设计与建模 三. 用限界上下文来保护领域
  • 32. 电商的基本业务模型 付钱 订单 收钱 卖货 算账 收货 签收 发货
  • 33. “个体户”或“小商贩” 订单 收钱 卖货 算账 上货 发货
  • 34. 订单代理系统架构的弊端 • 每个业务依然是个“小商贩”,相同功能的代码依然会重复 • 改成调用订单代理系统,交付数据的准确性依然达不到财务要求
  • 35. 需求:财务核算级别的精确交付 “小商贩”模式能解决技术问题,但不能满足业务需求 交易领域中缺少 一个专注交付的子领域
  • 36. 重新理解和确定了领域问题 • 得到后端的核心子领域问题:是“履约”,是交付 订单交付系统
  • 37. 指导建模 :把握领域并识别限界上下文 • 目标:让业务方从“小商贩”入驻“超市”
  • 38. 订单交付系统接管业务的交易行为
  • 39. 订单交付系统满足了业务和技术的目标 卖货 收钱 发货 • 业务方不再是“小商贩”,入驻“超市”成为“卖家” • 交付的数据达到财务精准核算的要求 算账
  • 40. 一. 用领域驱动来把握真正的业务需求 二. 领域驱动设计指导架构设计与建模 三. 用限界上下文来保护领域
  • 41. 强调上下文的重要性 由机场“登机流程上下文”业务规则调度,和乘客去主动触发登机所需要的 动作,完全可以表现为两种设计,伪代码如下。 前者 登机流程上下文.排队(乘客) 登机流程上下文.安检(乘客) 登机流程上下文.摆渡(乘客,航班) 登机流程上下文.登机(乘客,航班) 后者 乘客.排队(机场) 乘客.我要安检(机场) 乘客.我要坐摆渡车(摆渡车) 乘客.我要上飞机(航班) 前者是有序的安全的,不会给机场制造意外,后者机场是不可控的。
  • 42. 确定了领域和限界上下文后,就要保护 保护是手段 •目的:边界内的“完美世界”不可侵犯 •依据:边界,限界上下文内的规则
  • 43. 这样保护了订单交付领域
  • 44. 保护领域:规范可以进入上下文内的对象模型 进入机场上下文的时,“人物”要变为“乘客” 进入订单交付上下文的时,“业务对象”要变为“商品”
  • 45. 保护领域:规范可以进入上下文内的对象模型 之前,进入各业务上下文的模型,由业务自己决定 客户端通过场景来判断该进入哪个业务上下文 If 听书 { 准备听书的参数(tid) ,请求听书的接口 } else if 课程{ 准备课程的参数(cid+ctype) ,请求对应的接口 } else if 电子书{ 准备课程的参数(bid) ,请求对应的接口 } else …… 课程 听书 电子书
  • 46. 保护领域:规范可以进入上下文内的对象模型 老版本APP 新版本APP 商品模型 课程 ProductID ProductType 听书 网关转发 商品 商品 商品 防腐层 电子书
  • 47. 保护领域:用领域事件解耦与其它上下文的关系 • 发布统一的领域事件;由外部系统的上下文来修改适配。
  • 48. 保护领域:把握领域的职责 • 领域之外的事少管。节操币并不属于订单交付上下文内的商品。
  • 49. 保护领域:把握领域的职责 • 领域之外的事少管。把节操币充值的交付,“让”给交易中心,
  • 50. 保护领域:使用上下文隔离相同事物的不同内涵 • 之前,用户一次购买,却产生两笔订单
  • 51. 保护领域:使用上下文隔离相同事物的不同内涵 • 一次购买,产生两笔订单的适用用场景 商家B 商家A 下单(订单B) 卖货 收钱 下单(订单A) 卖货 收钱 发货
  • 52. 保护领域:使用上下文隔离相同事物的不同内涵 • 商城上下文 和 业务交互上下文 是合作关系,接力完成一笔订单的交付 卖货 收钱 发货
  • 53. 保护领域:使用上下文隔离相同事物的不同内涵 • 商城同步的订单交付不再创建新订单
  • 54. 保护领域:保护业务抽象行为的一致性 实现层面的设计
  • 55. 保护领域:保护业务抽象行为的一致性 • 推进破坏“业务抽象行为一致性”的产品下线 • 某产品权益:有效期内可零元购买“得到”内容 • 所有购买场景,增加if……else…… • 破坏设计,污染代码
  • 56. 保护领域:保护业务抽象行为的一致性 • 推进破坏“业务抽象行为一致性”的产品下线 财务和老板们确认 特殊的技术驱动 法务确认法律风险 产品经理修改规则 客服部门去面对用户
  • 57. 结语1:DDD指导的设计建模带来的几个长尾收益 • 可以快速支持商城售卖各种商品 • 可以快速接入书单等多商品打包的购买 • 可以快速接入各种产品的赠送功能 • 客户端可以封装统一的结算台组件 • 从每月核查财务数据的工作中解放了 ……
  • 58. 结语2:不要把DDD只当做一门技术来学习 ta可以是指导开发过程的方法论
  • 59.
  • 60.
  • 61. 希望对大家有所启发!