{"schemaVersion":"drillso.agent.session.v1","scope":"node","resource":{"type":"shared-session","shareId":"tZyOEtBDn_om","title":"常见大型软件架构设计快速入门101","canonicalUrl":"https://drillso.com/en/share/sessions/tZyOEtBDn_om/ddd-c064d8e7","agentUrl":"https://drillso.com/en/share/sessions/tZyOEtBDn_om/agent.json?node=ddd-c064d8e7","ownerName":"pyth0nb3st","updatedAt":"2026-04-27T16:17:48.260Z"},"currentNode":{"id":"c064d8e7-744f-45c2-8914-60333bc05d20","slug":"ddd-c064d8e7","title":"DDD","type":"page","url":"https://drillso.com/en/share/sessions/tZyOEtBDn_om/ddd-c064d8e7","agentUrl":"https://drillso.com/en/share/sessions/tZyOEtBDn_om/agent.json?node=ddd-c064d8e7","text":"## DDD 是什么：把“业务复杂度”放回软件设计中心\n\n**DDD（Domain-Driven Design，领域驱动设计）**不是某种框架或微服务模板，而是一套在**复杂业务**下更容易保持“可理解、可演进”的建模与架构方法。它的核心思想是：  \n> 软件的结构应当围绕“领域（业务）”来组织，而不是围绕技术层（Controller/Service/DAO）或数据库表来组织。\n\n在你提供的文章语境里，DDD 被放在“可维护性”“清晰边界与稳定契约”“为未来拆分铺路”这些目标之下，因此它更像一种**划分模块边界、控制复杂度、降低协作摩擦**的手段。\n\n---\n\n## DDD 解决的典型痛点\n\n在大型系统里，最难的是“长期变化”。DDD 常用来对抗这些问题：\n\n- **业务语言不统一**：产品说“订单关闭”，研发说“状态=9”，测试说“取消”，最后代码里出现三套概念。\n- **模型失真**：代码结构跟业务不一致，新增功能只能“到处 if/else”。\n- **边界模糊**：一个需求要改 10 个模块，且彼此互相直接引用数据库或内部类。\n- **一致性失控**：为了一个功能跨表跨服务强事务，导致性能和可用性风险。\n\n---\n\n## 两大支柱：战略设计 vs 战术设计\n\n### 1) 战略设计（Strategic Design）：先把边界划清楚\n战略设计关心“系统怎么拆、团队怎么协作、模型在哪些边界内成立”。\n\n- **限界上下文（Bounded Context）**  \n  同一个词在不同上下文含义可能不同，DDD 允许它们并存，但要求**边界内自洽**、边界间通过契约连接。  \n  例：  \n  - 在“交易上下文”里，`Order` 关注支付、履约状态  \n  - 在“客服上下文”里，`Order` 关注投诉、补偿、工单关联  \n  两边都叫 Order，但字段、规则、生命周期可能完全不同。\n\n- **上下文映射（Context Mapping）**：上下文之间怎么集成  \n  常见方式包括：API 调用、事件订阅、共享内核（谨慎）、防腐层（ACL）等。  \n  其中 **防腐层（Anti-Corruption Layer）** 很关键：用一层适配把外部系统的“脏模型”隔离开，避免污染自己的领域模型。\n\n### 2) 战术设计（Tactical Design）：在边界内把模型做好\n战术设计关心“代码怎么写更贴近业务模型”。\n\n- **实体（Entity）**：有身份（id），生命周期中属性会变  \n- **值对象（Value Object）**：无身份、不可变，靠值相等（例如 Money、Address）  \n- **聚合（Aggregate）与聚合根（Aggregate Root）**：一致性边界  \n  聚合根是唯一对外入口，外部不能随意改聚合内部对象。\n- **领域服务（Domain Service）**：不适合放在某个实体里的业务规则  \n- **领域事件（Domain Event）**：领域里发生了“重要事实”，用于解耦和异步扩展  \n- **仓储（Repository）**：以“聚合”为单位的持久化抽象（不是表级 CRUD）\n\n---\n\n## 聚合：文章里提到的“事务一致性边界”如何理解？\n\n**聚合的本质**：你愿意为哪些对象付出“强一致（同一事务）”的成本。  \nDDD 建议：**尽量小聚合**，否则并发、性能、锁竞争都会变差。\n\n举个电商例子：\n\n- `Order`（订单）作为聚合根\n- `OrderItem`（订单项）属于 `Order` 聚合内部\n\n那么外部修改订单项通常要通过聚合根方法：\n\n```java\nclass Order {\n  private OrderId id;\n  private List<OrderItem> items;\n  private OrderStatus status;\n\n  public void changeItemQuantity(SkuId skuId, int qty) {\n    if (status != OrderStatus.DRAFT) throw new IllegalStateException(\"不可修改\");\n    // 在聚合内维护不变量：数量>0、库存校验策略等\n  }\n}\n```\n\n**不要**让别的模块直接拿到 `OrderItemRepository` 去改某一行记录，因为这会绕过聚合不变量与一致性规则。\n\n---\n\n## DDD 与“模块化单体 / 微服务”的关系\n\nDDD 不是“必须微服务”，反而常见正确路径是：\n\n- 先用 DDD 把单体做成**模块化单体**：  \n  - 每个限界上下文 = 一个清晰模块  \n  - 模块之间只通过接口/事件交互  \n- 当组织和交付节奏需要时，再把某些上下文拆成**独立服务**  \n  这时你会发现：边界、数据归属、契约早已更清晰，拆分成本更低。\n\n---\n\n## 一个简化的 DDD 分层视图（帮助落地）\n\nDDD 常与“整洁架构/六边形架构”结合，形成清晰依赖方向：\n\n```mermaid\nflowchart TD\n  UI[\"接口层(HTTP/消息/CLI)\"] --> APP[\"应用层(Application)\"]\n  APP --> DOM[\"领域层(Domain)\"]\n  APP --> INF[\"基础设施层(Infrastructure)\"]\n  INF --> DB[\"数据库/缓存/外部服务\"]\n```\n\n- **应用层**：编排用例（事务、调用领域对象、发布事件），不写复杂规则  \n- **领域层**：业务规则与不变量核心  \n- **基础设施层**：技术细节（ORM、MQ 客户端、第三方 SDK）\n\n---\n\n## 你可以继续深入的子主题（建议钻研顺序）\n\n- 限界上下文识别方法：事件风暴（Event Storming）、业务能力地图\n- 聚合设计原则：不变量、并发、最终一致性与 Saga\n- 领域事件与 EDA 的结合：Outbox、幂等、事件版本兼容\n- 防腐层（ACL）实践：如何隔离外部支付/ERP 的模型污染\n- Repository 的边界：以“聚合”为单位 vs 以“查询”为单位（与 CQRS 配合）\n\n如果你告诉我你的业务场景（例如订单/支付/库存/内容），我可以用 DDD 的方式帮你画出可能的限界上下文与聚合边界，并指出哪些地方适合用事件解耦、哪些地方必须强一致。","markdown":"## DDD 是什么：把“业务复杂度”放回软件设计中心\n\n**DDD（Domain-Driven Design，领域驱动设计）**不是某种框架或微服务模板，而是一套在**复杂业务**下更容易保持“可理解、可演进”的建模与架构方法。它的核心思想是：  \n> 软件的结构应当围绕“领域（业务）”来组织，而不是围绕技术层（Controller/Service/DAO）或数据库表来组织。\n\n在你提供的文章语境里，DDD 被放在“可维护性”“清晰边界与稳定契约”“为未来拆分铺路”这些目标之下，因此它更像一种**划分模块边界、控制复杂度、降低协作摩擦**的手段。\n\n---\n\n## DDD 解决的典型痛点\n\n在大型系统里，最难的是“长期变化”。DDD 常用来对抗这些问题：\n\n- **业务语言不统一**：产品说“订单关闭”，研发说“状态=9”，测试说“取消”，最后代码里出现三套概念。\n- **模型失真**：代码结构跟业务不一致，新增功能只能“到处 if/else”。\n- **边界模糊**：一个需求要改 10 个模块，且彼此互相直接引用数据库或内部类。\n- **一致性失控**：为了一个功能跨表跨服务强事务，导致性能和可用性风险。\n\n---\n\n## 两大支柱：战略设计 vs 战术设计\n\n### 1) 战略设计（Strategic Design）：先把边界划清楚\n战略设计关心“系统怎么拆、团队怎么协作、模型在哪些边界内成立”。\n\n- **限界上下文（Bounded Context）**  \n  同一个词在不同上下文含义可能不同，DDD 允许它们并存，但要求**边界内自洽**、边界间通过契约连接。  \n  例：  \n  - 在“交易上下文”里，`Order` 关注支付、履约状态  \n  - 在“客服上下文”里，`Order` 关注投诉、补偿、工单关联  \n  两边都叫 Order，但字段、规则、生命周期可能完全不同。\n\n- **上下文映射（Context Mapping）**：上下文之间怎么集成  \n  常见方式包括：API 调用、事件订阅、共享内核（谨慎）、防腐层（ACL）等。  \n  其中 **防腐层（Anti-Corruption Layer）** 很关键：用一层适配把外部系统的“脏模型”隔离开，避免污染自己的领域模型。\n\n### 2) 战术设计（Tactical Design）：在边界内把模型做好\n战术设计关心“代码怎么写更贴近业务模型”。\n\n- **实体（Entity）**：有身份（id），生命周期中属性会变  \n- **值对象（Value Object）**：无身份、不可变，靠值相等（例如 Money、Address）  \n- **聚合（Aggregate）与聚合根（Aggregate Root）**：一致性边界  \n  聚合根是唯一对外入口，外部不能随意改聚合内部对象。\n- **领域服务（Domain Service）**：不适合放在某个实体里的业务规则  \n- **领域事件（Domain Event）**：领域里发生了“重要事实”，用于解耦和异步扩展  \n- **仓储（Repository）**：以“聚合”为单位的持久化抽象（不是表级 CRUD）\n\n---\n\n## 聚合：文章里提到的“事务一致性边界”如何理解？\n\n**聚合的本质**：你愿意为哪些对象付出“强一致（同一事务）”的成本。  \nDDD 建议：**尽量小聚合**，否则并发、性能、锁竞争都会变差。\n\n举个电商例子：\n\n- `Order`（订单）作为聚合根\n- `OrderItem`（订单项）属于 `Order` 聚合内部\n\n那么外部修改订单项通常要通过聚合根方法：\n\n```java\nclass Order {\n  private OrderId id;\n  private List<OrderItem> items;\n  private OrderStatus status;\n\n  public void changeItemQuantity(SkuId skuId, int qty) {\n    if (status != OrderStatus.DRAFT) throw new IllegalStateException(\"不可修改\");\n    // 在聚合内维护不变量：数量>0、库存校验策略等\n  }\n}\n```\n\n**不要**让别的模块直接拿到 `OrderItemRepository` 去改某一行记录，因为这会绕过聚合不变量与一致性规则。\n\n---\n\n## DDD 与“模块化单体 / 微服务”的关系\n\nDDD 不是“必须微服务”，反而常见正确路径是：\n\n- 先用 DDD 把单体做成**模块化单体**：  \n  - 每个限界上下文 = 一个清晰模块  \n  - 模块之间只通过接口/事件交互  \n- 当组织和交付节奏需要时，再把某些上下文拆成**独立服务**  \n  这时你会发现：边界、数据归属、契约早已更清晰，拆分成本更低。\n\n---\n\n## 一个简化的 DDD 分层视图（帮助落地）\n\nDDD 常与“整洁架构/六边形架构”结合，形成清晰依赖方向：\n\n```mermaid\nflowchart TD\n  UI[\"接口层(HTTP/消息/CLI)\"] --> APP[\"应用层(Application)\"]\n  APP --> DOM[\"领域层(Domain)\"]\n  APP --> INF[\"基础设施层(Infrastructure)\"]\n  INF --> DB[\"数据库/缓存/外部服务\"]\n```\n\n- **应用层**：编排用例（事务、调用领域对象、发布事件），不写复杂规则  \n- **领域层**：业务规则与不变量核心  \n- **基础设施层**：技术细节（ORM、MQ 客户端、第三方 SDK）\n\n---\n\n## 你可以继续深入的子主题（建议钻研顺序）\n\n- 限界上下文识别方法：事件风暴（Event Storming）、业务能力地图\n- 聚合设计原则：不变量、并发、最终一致性与 Saga\n- 领域事件与 EDA 的结合：Outbox、幂等、事件版本兼容\n- 防腐层（ACL）实践：如何隔离外部支付/ERP 的模型污染\n- Repository 的边界：以“聚合”为单位 vs 以“查询”为单位（与 CQRS 配合）\n\n如果你告诉我你的业务场景（例如订单/支付/库存/内容），我可以用 DDD 的方式帮你画出可能的限界上下文与聚合边界，并指出哪些地方适合用事件解耦、哪些地方必须强一致。","structured":null,"children":[]},"breadcrumbs":[{"id":"5bc695b9-372f-48da-b53f-1d163fe78a70","slug":"常见大型软件架构设计快速入门101-5bc695b9","title":"常见大型软件架构设计快速入门101","type":"page","url":"https://drillso.com/en/share/sessions/tZyOEtBDn_om/%E5%B8%B8%E8%A7%81%E5%A4%A7%E5%9E%8B%E8%BD%AF%E4%BB%B6%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8101-5bc695b9","agentUrl":"https://drillso.com/en/share/sessions/tZyOEtBDn_om/agent.json?node=%E5%B8%B8%E8%A7%81%E5%A4%A7%E5%9E%8B%E8%BD%AF%E4%BB%B6%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8101-5bc695b9"}],"parent":{"id":"5bc695b9-372f-48da-b53f-1d163fe78a70","slug":"常见大型软件架构设计快速入门101-5bc695b9","title":"常见大型软件架构设计快速入门101","type":"page","url":"https://drillso.com/en/share/sessions/tZyOEtBDn_om/%E5%B8%B8%E8%A7%81%E5%A4%A7%E5%9E%8B%E8%BD%AF%E4%BB%B6%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8101-5bc695b9","agentUrl":"https://drillso.com/en/share/sessions/tZyOEtBDn_om/agent.json?node=%E5%B8%B8%E8%A7%81%E5%A4%A7%E5%9E%8B%E8%BD%AF%E4%BB%B6%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8101-5bc695b9"},"children":[],"fullTree":null,"warnings":[],"truncated":false}