← 全部书单 / 软件工程

《领域驱动设计》

《领域驱动设计》封面
作者: 埃里克·埃文斯
出版社: 人民邮电出版社
出版年: 2016-6-1
原作名: Domain-Driven Design: Tackling Complexity in the Heart of Software
7.9
★★★★☆
豆瓣评分 · 522 人评价
未标记阅读状态
在一团乱麻的复杂业务里,用“模型”把业务理清楚、让代码跟上业务的设计方法论。

总体观点

2003 年,埃里克·埃文斯针对老大难问题:很多企业软件死掉不是技术不行,是业务太复杂——规则盘根错节、需求天天变,代码最后变成谁也看不懂的粥。

核心论点:软件真正的复杂性不在技术,在业务本身;对抗它的唯一武器,是真实反映业务的“领域模型”。模型不能只活在文档里,必须活在代码里、活在团队每天的对话里。战略上划分业务边界(限界上下文),战术上建模(实体、值对象、聚合),团队和业务专家用同一种语言说话(通用语言)。

它预言了未来:十几年后微服务大火,“服务按什么边界拆”最难的问题,答案早在这本书里——按限界上下文拆。今天的中台、微服务、业务架构,骨子里都是 DDD。难啃,但啃下来看业务系统的眼光完全不一样。

核心观点

  1. 1. 通用语言:全团队说同一种话

    业务专家和程序员必须用同一套词汇说话,且这套词汇原样出现在代码里(类名方法名就是业务词汇)。很多项目的病根是“翻译腔”:业务说“客户”,开发写 user,测试叫“用户”——三个人开会各说各的,代码和业务对不上。

    一家人装修:你说“玄关”,工头听成“门口那块”,设计师画成“门厅”,鞋柜尺寸全错。统一叫“玄关”指进门 1.5 米区域,图纸合同聊天都这么叫,就不会错。
  2. 2. 限界上下文:同一个词,出了这个门意思就变了

    任何业务概念只在明确边界内清晰无歧义,出了边界意思就变。“商品”在销售那指“可卖的东西”,在仓储那指“占库位的货”。硬搞“统一商品”模型包打天下,最后一定四不像。承认一词多义,给每个含义划地盘。

    “苹果”在水果店指能吃的水果,在手机店指电子产品。你不会要求全世界只用一个意思,业务系统也一样,各自有定义,再谈怎么协作。
  3. 3. 实体 vs 值对象:看身份,还是看内容

    实体看“身份”:两个人同名同姓也是两个人,靠身份证号区分。值对象看“内容”:两张 100 元钞票编号不同但没人关心。值对象做成不可变(改就是换新的),天然线程安全,代码一下清爽很多。

    订单是实体:订单号 2024001 和 2024002 是两个订单,哪怕内容一样。订单里的“收货地址”是值对象:改地址直接换新的,不用追踪“这个地址对象”的身份。
  4. 4. 聚合:一次只改一簇,守住一致性边界

    一组互相咬合的业务对象,必须作为整体来改,对外只通过“聚合根”说话。银行转账:扣款和入账要么一起成功要么都不,绝不允许只扣不入。聚合就是业务一致性的“保险丝盒”。

    订单和订单明细删订单必须连明细一起删。把“转出账户、转入账户、转账记录”圈成聚合,对外只暴露“转账”一个入口,里面怎么折腾都行。
  5. 5. 模型就是代码,代码就是模型

    领域模型不能是 PPT 里的方框图,必须直接长在代码里:类名就是业务概念,方法就是业务动作,代码读起来像讲业务故事。模型和代码是两张皮,时间一长各说各话,模型就死了。

    菜谱写“宫保鸡丁”,端上来也得是宫保鸡丁,不能端盘“不明炒物”说“反正能吃”。代码里有 Order 类带 pay()、cancel() 方法,读代码就知道“这是订单,能付款能取消”。
  6. 6. 防腐层:别让烂代码污染你的模型

    干净模型必须跟老旧混乱的外部系统对接时,中间加一层翻译,脏东西只脏在这一层,不许渗进模型。没有防腐层,外部系统的怪概念怪字段会慢慢污染代码,最后你的模型也一样烂。

    家里装净水器:自来水管可能有杂质,但你喝的水必须干净。净水器装在入户处,脏水只脏到滤芯,绝不进水杯。跟第三方支付、老 ERP 对接时,这一层能救命。
  7. 7. 把最好的力气,花在核心域上

    业务里不是所有部分都一样重要。核心域(决定竞争力的部分)值得最好的设计师和最多的时间;支撑域和通用域能买就买、能凑合就凑合。在“员工请假审批”上雕花、核心“交易撮合引擎”写得稀烂,是本末倒置。

    开餐厅:招牌菜值得请大厨反复打磨;收银系统直接买现成的;考勤用 Excel 就行。把三个月花在自研考勤上,招牌菜让学徒随便炒,这餐厅必倒。
树状思维导图

全书思维导图 · 知识脉络树

💡 拖拽平移 · 滚轮缩放 · 点击分支圆点折叠/展开
已复制思维导图大纲到剪贴板!

全书结构

  1. 第1章 消化知识

    业务专家与开发人员紧密协作,提炼核心业务规则,持续过滤无关细节,将深层业务认知沉淀为领域模型。

    开发印刷制版系统时,工程师深入车间理解工人排版术语,将原本复杂混乱的手工计算抽象为清晰的“版面布局”模型。
  2. 第2章 交流与语言的使用

    团队必须建立统一语言(Ubiquitous Language),在日常沟通、需求文档与代码实现中使用完全一致的领域术语。

    杜绝业务说“核保通过”而开发在代码里写 `status = 2`;直接将类名和方法名命名为 `Policy.approveUnderwriting()`。
  3. 第3章 绑定模型和实现

    模型驱动设计(MDD),让代码直接反映领域模型,杜绝业务模型在分析与实现之间断层脱节。

    领域模型中定义的概念在代码里必须有对应的类或枚举,修改业务模型时能够直接映射并重构代码结构。
  4. 第4章 分离领域

    采用分层架构隔离用户界面、应用层、领域层与基础设施层,确保核心领域逻辑不受技术框架与数据库细节污染。

    无论底层持久化用 MySQL 还是 Mongo,领域层里的核心计息算法完全不引用任何数据库驱动或 HTTP 请求对象。
  5. 第5章 软件中所表示的模型

    明确区分实体(拥有唯一生命周期标识)、值对象(仅看重属性且不可变)、领域服务与聚合模块。

    用户(User)由唯一身份证或用户ID标识为实体,而家庭住址(Address)只要省市区完全相同即为可直接替换的值对象。
  6. 第6章 领域对象的生命周期

    聚合(Aggregate)划定事务强一致性边界,工厂(Factory)负责复杂聚合创建,仓储(Repository)提供持久化透明访问。

    订单聚合(Order)作为根实体统一管理多条订单项(OrderItem),外部只能通过 Order 根修改订单项,严禁直接跨聚合更新。
  7. 第7章 使用语言:一个扩展的示例

    以跨国货物运输系统为例,完整演示从梳理统一语言、分离实体与值对象、划定聚合边界到代码落地的全景实践。

    将货物(Cargo)、运输规格(DeliverySpecification)与装卸事件(HandlingEvent)串联成完整的领域业务闭环。
  8. 第8章 突破

    重构不仅是修补坏味道,当现有模型无法顺畅承载新业务诉求时,通过思维跃迁发现更深层次的本质业务模型。

    原本把“贷款”当成简单还款记录,陷入复杂例外处理泥潭;后来突破性将其重新建模为“资金流时间切片”,逻辑瞬间平顺。
  9. 第9章 将隐式概念转变为显式概念

    倾听业务人员口头讨论中隐藏的约束与概念,将隐式业务规则提取为独立的规约(Specification)或领域事件对象。

    把分散在十几个 if 判断里的“该客户是否有资格申请低息房贷”,显式封装为 `MortgageEligibilitySpecification` 独立规约类。
  10. 第10章 柔性设计

    采用意图清晰的接口、无副作用函数(Side-Effect-Free Functions)和前置断言构建易于组合测试的柔性模型。

    设计颜料配色计算方法时,输入红黄颜料只返回新生成的橙色配方,绝不暗中修改传入的原颜料对象状态。
  11. 第11章 应用分析模式

    借鉴 Martin Fowler 等专家在财务、组织或记账等领域沉淀的高成熟度分析模式,加速复杂领域建模。

    在设计复杂财务分账系统时,直接引入“复式记账法分析模式”将所有变动显式转化为借贷分录,彻底规避账目不平。
  12. 第12章 将设计模式应用于模型

    运用策略模式(Strategy)与组合模式(Composite)等经典设计模式,让领域模型能够灵活适配复杂多变的分支规则。

    将不同国家复杂的关税计税规则建模为可热插拔的 TariffCalculationStrategy 策略类,新增国家无需改动订单核心逻辑。
  13. 第13章 通过重构得到更深层的理解

    领域建模是一个持续探索与迭代的科学过程,抓住每次设计摩擦与危机将其转化为模型深化升级的突破契机。

    当发现某个计算每次加需求都要改动四个类时,停下来与业务方深聊,发现遗漏了关键的“计费周期”概念并据此重构。
  14. 第14章 保持模型的完整性

    战略设计的核心:划分限界上下文(Bounded Context),绘制上下文映射图(Context Map),建立防腐层(ACL)隔离外部腐蚀。

    “商品”在电商营销上下文中关注活动价与促销标签,而在仓储上下文中关注重量、体积与库位,两个上下文各自维护模型并用防腐层转换。
  15. 第15章 精炼

    界定核心域(Core Domain),清晰剥离通用子域(Generic Subdomain)与支撑子域,把团队最顶尖的资源倾斜在核心竞争力上。

    在线打车平台把精力倾注在核心的“派单匹配与动态定价算法”上,而将通用的“短信通知与用户账单导出”直接使用通用组件。
  16. 第16章 大型结构

    在超大型复杂系统中确立演化式秩序(Evolving Order)、系统隐喻或职责分层,保持全局架构宏观协调与清晰边界。

    全公司推行统一的“操作层-调度层-决策层”三层宏观职责划分,避免几十个跨业务线系统在交互协作时乱成一锅粥。
  17. 第17章 领域驱动设计的综合运用

    战略设计把方向,战术设计打基础;根据业务生命周期动态平衡架构严谨度与交付速度,实现战略与代码的统一。

    新孵化业务初期保持较小限界上下文快速试错,待业务模式跑通后立即引入严格的聚合与防腐层进行架构深耕沉淀。
返回 软件工程 目录

观点与结构均为转述总结,非原文摘录。封面图片来自豆瓣读书,仅作展示。

豆瓣评分与评价人数为逐本人工核实当天的数值。 · GitHub 仓库 · v1.0.0