mcpField
E
evolutionary-modular-architecture

evolutionary-modular-architecture

github.com/tech-leads-club开发7.1k69 次安装3 天前更新
代码仓库

关于 evolutionary-modular-architecture

用于设计可随产品和团队需求演进的模块化单体架构技能,帮助架构师和开发者划分领域边界、组织模块、规划通信与弹性,并制定拆分部署的演进路径。

主要功能

  1. 01DDD 限界上下文与上下文映射
  2. 02按聚合组织扁平模块
  3. 03端口、适配器与事务发件箱
  4. 04外部调用的弹性策略
  5. 05用于边界校验的 Node 脚本
  6. 06自包含的 HTML 架构文档

适用场景

  1. 01设计新平台或后端
  2. 02梳理领域上下文和数据所有权
  3. 03通过适配器集成外部供应商
  4. 04评估单体与微服务的边界

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/tech-leads-club/agent-skills --skill evolutionary-modular-architecture

安装后在 Claude Code 中输入/evolutionary-modular-architecture确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/
architecture-template.html
references/
acl-and-communication.md
architecture-doc.md
ddd.md
flat-by-aggregate.md
principles.md
resilience.md
stack-2026.md
scripts/
validate-boundaries.mjs
validate-structure.mjs

详细介绍

演进式模块化架构

将平台设计和构建为演进式模块化单体:从第一天起就设立明确的逻辑边界(DDD 限界上下文、按聚合扁平组织模块、围绕每个外部系统设置防腐层、事件驱动通信、默认具备韧性),同时将物理边界(独立部署、独立数据库)留作后续可选步骤。先从简单开始,只有在产品和团队确有需要时才调整粒度——绝不为了追赶潮流而反向设计微服务。

何时使用此技能

  • 从头设计新的平台、后端或服务。
  • 为某个领域定义限界上下文和上下文映射。
  • 决定如何组织模块的文件夹和文件。
  • 在单体、模块化单体和微服务之间做出选择。
  • 集成外部供应商(或与其解耦):ERP、工单系统、存储、支付、AI、身份系统、持久化工作流引擎。
  • 提高外部调用或模块间调用的韧性。
  • 添加实时的服务端到客户端更新。
  • 选择现代化(2026)的全栈 TypeScript 技术栈。

何时不使用

  • 只有少量端点的简单 CRUD——使用框架默认设置即可。
  • 深入探讨 NestJS 特定的实现细节——优先使用 nestjs-modular-monolith。
  • 审查或重构单个贫血领域模型——优先使用 tactical-ddd。

统领一切的一条规则

始终严格区分逻辑边界与物理边界;前者固定,后者演进。 从第一天起,模块、契约、状态所有权和防腐层都不可妥协。模块是否独立部署、是否使用独立数据库,是之后再做的运维决策,绝不是结构上的前提。这样,系统就能从一次部署起步,并不断发展,而无需重写。

可以这样想象:房子里的房间划分明确(模块)。每个房间里的物品都摆在明处,并按用途归类(按聚合扁平组织),而不是埋在层层嵌套的抽屉里(按技术层划分的文件夹)。最重要的是平面布局(边界)。


核心模型(深入时加载相应的参考资料)

主题涵盖内容参考资料
原则10 条模块化原则(P1–P10)+ 9 条结构原则(P11–P19)+ 冲突层级references/principles.md
DDD战略设计(子域、上下文映射、集成模式)+ 战术设计(富领域模型聚合、按子域调整建模强度)references/ddd.md
模块内部结构按聚合扁平组织、后缀、深度、扁平结构与子域判定、脚手架references/flat-by-aggregate.md
通信端口与适配器 / ACL、事件 + 事务性发件箱、SSE 实时通信references/acl-and-communication.md
韧性退避 + 全抖动、熔断器、重试预算、幂等性、隔舱、超时references/resilience.md
2026 技术栈前端、后端、数据、可观测性、持久化工作流、决策references/stack-2026.md
架构文档构建精美且自包含的 HTML 架构文档,配有 SVG 图表references/architecture-doc.md + assets/architecture-template.html
验证用于检查结构和模块边界的确定性检查scripts/validate-structure.mjs、scripts/validate-boundaries.mjs

不要一次性加载所有参考资料。仅在当前阶段需要时阅读相应资料(下方工作流会说明何时需要)。


工作流

无论你是在设计新系统还是审查现有系统,都使用此工作流。按顺序推进各阶段;每个阶段都有退出标准。明确说明假设;如果领域不清楚,请先询问,不要猜测。

阶段 0 — 界定范围

确认:这是一个新平台、现有平台中的新模块,还是一次评审?确认运行时/技术栈约束(默认目标是 2026 TypeScript 技术栈——请参阅 references/stack-2026.md)。除非存在硬性约束,否则默认采用一次部署(模块化单体)。

退出条件:记录范围和约束。

阶段 1 — 领域发现(DDD 战略设计)

阅读 references/ddd.md。根据业务语言识别子域,将每个子域划分为核心、支撑或通用,并找出每个子域的通用语言。不要按技术层分组。如果存在多种有界上下文解释,请一并列出——不要默默替用户做决定。

退出条件:列出候选有界上下文,并为每个上下文标明分类、用一句话说明职责以及列出关键聚合。

阶段 2 — 边界与上下文映射

绘制上下文映射:有哪些上下文、它们如何关联(客户/供应商、遵从者、开放主机服务、发布语言、共享内核、防腐层),以及哪些是核心上下文。确定状态所有权:可以使用一个数据库,但每个模块只能写入自己的表——模块边界之间不得设置外键;通过 id 引用其他上下文。保持聚合内聚(不要过度拆分事务性核心)。

退出条件:上下文映射 + 表所有权映射(一个模块对应自己的表)。

阶段 3 — 模块内部结构(按聚合扁平组织)

阅读 references/flat-by-aggregate.md。在每个模块内部,按聚合而非技术层组织:1 个业务概念 = 1 个文件夹;技术层通过文件后缀表示(.entity.ts、.service.ts、.controller.ts)。层级深度保持 ≤ 2(扁平)或 ≤ 3(按子域组织)。整洁架构的依赖规则仍然适用(表示层 → 应用层 → 领域层 ← 基础设施层)——只是通过后缀和共置来体现,而非通过分层文件夹。使用 6 项标准测试来决定采用扁平结构还是按子域组织;默认采用扁平结构。

退出条件:每个模块的文件夹布局,以及扁平结构与按子域组织的决策和理由。

阶段 4 — 通信与防腐层

阅读 references/acl-and-communication.md。每个外部系统都必须通过端口 + 适配器(ACL)接入——包括由其他团队负责的内部服务。领域使用自身的语言定义端口;适配器负责转换外部模型的输入和输出。内部模块之间:仅在聚合内部同步通信(一个 ACID 事务);跨模块通过事务发件箱传递事件,并使用幂等消费者。当用户体验需要服务器向客户端推送实时更新时,添加 SSE。

退出条件:端口 + 适配器列表;领域事件列表,采用 module.aggregate.action 命名;同步与异步决策。

阶段 5 — 弹性

阅读 references/resilience.md。为每个外部/服务间调用添加保护:超时 → 熔断器 → 重试(有上限的指数退避 + 完全抖动)。仅重试幂等操作(写入操作必须要求幂等键)。将重试限制在预算内(约占流量的 10%),根据滑动窗口错误率触发熔断器,并为每个熔断器指定具名降级方案。只有当长时间运行的多步骤流程必须在重启后继续时,才添加持久化执行机制。

退出条件:为每个适配器制定弹性策略,并为写入操作设置幂等键。

阶段 6 — 技术栈与演进

阅读 references/stack-2026.md。选择具体技术栈并说明权衡(运行时、API 风格、缓存、实时传输)。然后说明演进路径:阶段 1(模块化单体 + 清晰边界,并已设置事件/发件箱)是当前状态;只有当某个模块自身的指标证明有必要时,才将其拆分为独立应用/数据库。

退出条件:技术栈表 + 演进说明。

阶段 7 — 编写架构文档(HTML)

制作一份精致、独立的 HTML 架构文档,并配上优雅的手绘风格 SVG 图表。阅读 references/architecture-doc.md,并从 assets/architecture-template.html 开始:复制模板,保持其 CSS 和视觉系统不变,替换占位内容。构建标准章节(概览、领域、原则、单体映射图、限界上下文、ACL、通信、从前端到后端、模块、弹性、实时性、演进、技术栈),并按顺序为图表编号(“图表 N — …”)。保持视觉风格:配色、Lato 和 JetBrains Mono 字体、圆角矩形、箭头标记、柔和渐变和斜体说明文字。输出为一个可直接在浏览器中打开的 HTML 文件,无需构建步骤。

验收标准:一个独立的 HTML 文件,图表风格一致,页内导航可正常使用。


决策规则(速查表)

  • 子域类别: 竞争优势 → 核心;业务特定但不具差异化 → 支撑;由你使用、已解决的问题 → 通用。
  • 战术建模强度: 核心领域使用完整建模(丰富的聚合、值对象、不变量、事件);支撑领域使用中等强度;通用领域尽量精简(在没有不变量的地方强行丰富建模属于过度设计)。详见 references/ddd.md。
  • 扁平结构还是按子域划分: 默认采用扁平结构(深度为 2)。仅当 6 项标准中有 4 项或以上符合时,才按子域划分(深度为 3):不同的角色、授权、执行模型、扩展能力、部署、故障隔离。详见 references/flat-by-aggregate.md。
  • 同步还是事件: 同一聚合内采用同步方式(原子性很重要);跨模块采用 outbox 传递事件(可容忍最终一致性)。
  • 持久化执行: 仅在流程长时间运行、包含多个步骤且必须支持恢复时添加——不要用于普通请求。

硬性规则(不可妥协)

  • 每个模块只能写入自己的表;跨上下文链接通过 id 建立,并在代码中验证(enforce-module-boundaries)。
  • 禁止直接跨模块导入——通过 facade/contract 或事件通信。
  • 每个外部系统都必须置于 port + ACL 之后——供应商模型不得泄漏到领域中。
  • 仅重试幂等操作;写入操作必须携带幂等键。
  • 模块化原则(P1–P10)优先于结构原则(P11–P19)。 如果将代码放在一起会导致跨模块实体导入,就使用 facade + DTO;如果拆分聚合会破坏事务,就将其保留在一起。

自动化检查

将原则落实为可执行检查,而不是依赖评审。请在 CI 中和合并前运行以下脚本(均为零依赖的 Node ESM 脚本;传入 libs/packages 根目录,或让脚本自动检测):

  • node scripts/validate-structure.mjs [root] — 强制检查按聚合扁平组织原则(P11–P17):不得有技术分层文件夹、不得有单文件文件夹(__test__/ 除外)、深度 ≤ 3、聚合内不得有 README。
  • node scripts/validate-boundaries.mjs [root] — 强制检查模块边界(P1、P3、P8):不得有深层跨模块导入(仅可通过 barrel/facade 导入)、不得有重复或未加前缀的实体名称、不得有跨上下文关系。

出现违规时,这两个脚本都会以非零状态码退出,并打印违规路径。结构检查失败应视为阻断项;团队采纳约定后,边界检查结果也应视为阻断项。


示例

示例 1:设计一个新平台

用户说:“设计一个面向客户 ERP 的应付账款平台架构。” 操作:

  1. 阶段 1 — 发现子域;进行分类(例如,应付账款和运营属于核心子域;文档、审计和游戏化属于支撑子域;身份和通知属于通用子域)。
  2. 阶段 2 — 绘制上下文映射图 + 采用单数据库,并明确每个模块对其表的所有权。
  3. 阶段 3 — 按模块采用按聚合划分的扁平布局。
  4. 阶段 4 — 将 ERP、工单系统和存储置于端口 + ACL 后;通过 outbox 传递事件;为操作员队列使用 SSE。
  5. 阶段 5 — 在 ERP 适配器上制定弹性策略(幂等键 = payment id)。
  6. 阶段 6 — 选择 2026 技术栈 + 制定演进说明(当前只部署一个应用)。 结果:上下文映射图、模块布局、端口/适配器列表、弹性策略以及技术栈 + 演进计划——每项都有相应参考资料作为依据。
示例 2:组织一个模块

用户说:“如何组织 billing 模块?” 操作:阅读 references/flat-by-aggregate.md;提出 billing/subscription/、billing/invoice/、billing/payment/ 目录,文件与 __test__/ 放在一起;执行 6 项标准测试(billing = 扁平布局)。结果:一个扁平的文件夹树及其设计依据,并通过后缀保留依赖规则。

示例 3:与供应商解耦

用户说:“我不想被 OMIE 绑定。” 操作:阅读 references/acl-and-communication.md;使用领域语言定义 ErpLedgerPort;实现 OmieAdapter;在边界处转换 OMIE 模型;说明更换 ERP 只需更换适配器。结果:一个端口接口 + 适配器方案;领域层绝不导入供应商类型。


反模式 / 危险信号

  • ❌ 从第一天起就采用微服务或多个数据库(“感觉规模很大”不是理由)。
  • ❌ 在模块中使用技术分层目录(core/service/、http/controller/、persistence/entity/)——这是按聚合划分的扁平布局所要取代的旧模式。
  • ❌ 一个模块读取或写入另一个模块的表。
  • ❌ 供应商 SDK 类型渗入领域层(没有 ACL)。
  • ❌ 重试非幂等写入;重试时不采用退避 + 抖动;重试不设预算。
  • ❌ 将内聚的事务型核心拆分成由事件耦合的片段。
  • ❌ 对没有不变量的通用子域强行采用丰富的战术 DDD。

参考指南

加载此文件适用场景
references/principles.md需要准确的原则文本,或需要解决结构与模块化之间的冲突。
references/ddd.md阶段 1–2:对子域分类、绘制上下文映射图、决定战术设计的应用深度。
references/flat-by-aggregate.md阶段 3:布局模块;选择扁平布局还是子域布局;脚手架;门面;测试。
references/acl-and-communication.md阶段 4:端口/适配器/ACL、事件 + outbox、SSE。
references/resilience.md阶段 5:退避/抖动、熔断器、幂等性、舱壁、持久化执行。
references/stack-2026.md阶段 0/6:具体的技术栈选择及权衡。
references/architecture-doc.md + assets/architecture-template.html阶段 7:生成 HTML 架构文档及其图表。
scripts/validate-structure.mjs、scripts/validate-boundaries.mjs验证:在 CI 中或合并前强制检查结构和模块边界。

评论

支持 Markdown