常见大型软件架构设计快速入门101
常见大型软件架构设计快速入门 101(面向入门到上手) 大型软件架构的目标不是“炫技”,而是在复杂需求、多人协作、长期演进下,依然能做到:可扩展、可维护、可用、可观测、可交付。本文用“101”方式,把常见架构形态、核心原则、关键组件与落地步骤串起来,帮助你快速建立整体框架。 --- 大型系统与小系统的关键差异 小系统通常关注“功能实现”;大型系统更关注“变化与风险”。 变化:需求、流量、团队、技术
DDD 是什么:把“业务复杂度”放回软件设计中心
DDD(Domain-Driven Design,领域驱动设计)不是某种框架或微服务模板,而是一套在复杂业务下更容易保持“可理解、可演进”的建模与架构方法。它的核心思想是:
软件的结构应当围绕“领域(业务)”来组织,而不是围绕技术层(Controller/Service/DAO)或数据库表来组织。
在你提供的文章语境里,DDD 被放在“可维护性”“清晰边界与稳定契约”“为未来拆分铺路”这些目标之下,因此它更像一种划分模块边界、控制复杂度、降低协作摩擦的手段。
DDD 解决的典型痛点
在大型系统里,最难的是“长期变化”。DDD 常用来对抗这些问题:
- 业务语言不统一:产品说“订单关闭”,研发说“状态=9”,测试说“取消”,最后代码里出现三套概念。
- 模型失真:代码结构跟业务不一致,新增功能只能“到处 if/else”。
- 边界模糊:一个需求要改 10 个模块,且彼此互相直接引用数据库或内部类。
- 一致性失控:为了一个功能跨表跨服务强事务,导致性能和可用性风险。
两大支柱:战略设计 vs 战术设计
1) 战略设计(Strategic Design):先把边界划清楚
战略设计关心“系统怎么拆、团队怎么协作、模型在哪些边界内成立”。
-
限界上下文(Bounded Context)
同一个词在不同上下文含义可能不同,DDD 允许它们并存,但要求边界内自洽、边界间通过契约连接。
例:- 在“交易上下文”里,
Order关注支付、履约状态 - 在“客服上下文”里,
Order关注投诉、补偿、工单关联
两边都叫 Order,但字段、规则、生命周期可能完全不同。
- 在“交易上下文”里,
-
上下文映射(Context Mapping):上下文之间怎么集成
常见方式包括:API 调用、事件订阅、共享内核(谨慎)、防腐层(ACL)等。
其中 防腐层(Anti-Corruption Layer) 很关键:用一层适配把外部系统的“脏模型”隔离开,避免污染自己的领域模型。
2) 战术设计(Tactical Design):在边界内把模型做好
战术设计关心“代码怎么写更贴近业务模型”。
- 实体(Entity):有身份(id),生命周期中属性会变
- 值对象(Value Object):无身份、不可变,靠值相等(例如 Money、Address)
- 聚合(Aggregate)与聚合根(Aggregate Root):一致性边界
聚合根是唯一对外入口,外部不能随意改聚合内部对象。 - 领域服务(Domain Service):不适合放在某个实体里的业务规则
- 领域事件(Domain Event):领域里发生了“重要事实”,用于解耦和异步扩展
- 仓储(Repository):以“聚合”为单位的持久化抽象(不是表级 CRUD)
聚合:文章里提到的“事务一致性边界”如何理解?
聚合的本质:你愿意为哪些对象付出“强一致(同一事务)”的成本。
DDD 建议:尽量小聚合,否则并发、性能、锁竞争都会变差。
举个电商例子:
Order(订单)作为聚合根OrderItem(订单项)属于Order聚合内部
那么外部修改订单项通常要通过聚合根方法:
不要让别的模块直接拿到 OrderItemRepository 去改某一行记录,因为这会绕过聚合不变量与一致性规则。
DDD 与“模块化单体 / 微服务”的关系
DDD 不是“必须微服务”,反而常见正确路径是:
- 先用 DDD 把单体做成模块化单体:
- 每个限界上下文 = 一个清晰模块
- 模块之间只通过接口/事件交互
- 当组织和交付节奏需要时,再把某些上下文拆成独立服务
这时你会发现:边界、数据归属、契约早已更清晰,拆分成本更低。
一个简化的 DDD 分层视图(帮助落地)
DDD 常与“整洁架构/六边形架构”结合,形成清晰依赖方向:
- 应用层:编排用例(事务、调用领域对象、发布事件),不写复杂规则
- 领域层:业务规则与不变量核心
- 基础设施层:技术细节(ORM、MQ 客户端、第三方 SDK)
你可以继续深入的子主题(建议钻研顺序)
- 限界上下文识别方法:事件风暴(Event Storming)、业务能力地图
- 聚合设计原则:不变量、并发、最终一致性与 Saga
- 领域事件与 EDA 的结合:Outbox、幂等、事件版本兼容
- 防腐层(ACL)实践:如何隔离外部支付/ERP 的模型污染
- Repository 的边界:以“聚合”为单位 vs 以“查询”为单位(与 CQRS 配合)
如果你告诉我你的业务场景(例如订单/支付/库存/内容),我可以用 DDD 的方式帮你画出可能的限界上下文与聚合边界,并指出哪些地方适合用事件解耦、哪些地方必须强一致。