AI 架构治理
核心问题
AI 是熵增过程。
每次 AI 生成代码,都是在现有代码库上做局部最优的叠加——当前上下文里最合理的方案,在一个月后的整体架构视角下,可能就是不合理的抽象、不必要的间接层、不该有的重复代码。
如果没有持续治理,AI 代码库的腐化速度远高于人手写的代码。原因前面说过:AI 没有痛感。 人写烂代码会难受,会去重构。AI 不会——它只是忠实地在屎山上再盖一层。
这一章讨论 AI 架构治理的六个实践,来自项目中的真实经验。
一、Skill 规范化
问题
传统架构治理靠的是"规范文档"——几十页的 Word、Wiki 上的约定、PPT 里的架构图。但 AI 不会主动读文档,人的执行力也参差不齐。规范文档最终变成了没人看的摆设。
解法:规范即 Skill
把架构规范做成可执行的 Skill,AI 在生成代码时自动遵守,人在审查代码时用 Skill 自动检查。
yaml
# audit-transaction.skill
检查规则:
1. 所有写操作必须包裹在 TransactionTemplate 中
2. 禁止使用 @Transactional 注解(除测试代码)
3. 写操作必须包含:锁 → 判断 → 更新 三步
# check-module-architecture.skill
检查规则:
1. {ModuleName}Module.cs 必须存在
2. Interfaces/ 目录下必须为 public
3. Implementations/ 目录下必须为 internal
# generate-service-test.skill
生成规则:
1. 根据 Service 类签名自动生成测试类
2. 参数扁平化,Mock 最小化
3. 断言标准化
效果
Skill 和人的区别:人不读规范,AI 遵守 Skill。 一条 Skill 定义下去,AI 每次生成代码都会自动遵守——不是靠自觉,是靠执行。而且 Skill 本身是代码,可以被版本管理、被审查、被迭代。
二、基础组件 Skill 参考
问题
架构治理不能每次都从零写 Skill。没有"标准库"的情况下,每次治理都像重新发明轮子——今天写一个事务检查,明天写一个模块检查,后天写一个日志检查。积累不够,治理永远只能覆盖几个点。
解法:建立基础 Skill 库
把常见的架构治理规则整理成一组基础 Skill,作为治理的起点:
yaml
# 治理链路示例:从创建模块到合入主干
generate-module-scaffold → 生成标准模块结构
→ generate-service-test → 自动生成测试类
→ run-service-tests → 执行测试验证
→ check-module-architecture → 检查模块合规
→ audit-transaction → 检查事务规范
→ audit-layer-dependency → 检查跨层调用
→ (合入主干)基础 Skill 清单
| 治理层面 | Skill | 检查/生成内容 | 对应原则 |
|---|---|---|---|
| 模块结构 | check-module-architecture | 目录结构、三标准类、访问修饰符 | 原则七 |
| 层次合规 | check-layer-dependency | 禁止 Controller 直调 Mapper | 原则一 |
| 对象体系 | audit-object-fragmentation | 发现 VO/BO/DTO/PO 等碎片对象 | 原则二 |
| 继承深度 | audit-inheritance-depth | 检查继承链是否超过 3 层 | 原则三 |
| 事务模板 | audit-transaction | 检查锁→判→更新模板 | 原则五 |
| 测试覆盖 | generate-service-test | 根据 Service 签名生成测试 | 原则六 |
| 测试执行 | run-service-tests | 执行指定 Service 的所有测试 | 原则六 |
| 接口设计 | audit-interface-design | 检查 public/internal 边界 | 原则七 |
| 日志格式 | audit-logging-format | 统一日志格式和级别 | 保留项 |
| 命名规范 | audit-naming-convention | 检查命名是否遵循项目约定 | 保留项 |
每个 Skill 都是可执行命令。架构治理不是"事后审计",而是事中合规——代码写完的那一刻,Skill 就已经检查过了。
三、文档先行
问题
传统做法是"先写代码,再补文档"。结果是:代码改了十遍,文档还是第一版。AI 时代,代码是 AI 写的,文档写得更少了——因为"人写完代码顺手写文档"这个环节消失了,AI 又不会主动写文档。
更致命的是 AI 的上下文碎片化:AI 每次生成代码时只看到当前文件或当前模块,看不到完整的架构图景。没有文档作为"边界条件",AI 很容易在一个局部做出和整体架构冲突的决策。
解法:文档先于代码
文档先行不是写长篇的 Word 文档,而是在关键边界上留下 AI 能读到的约束。
模块入口注释
每个 XxxModule.cs 的顶部写一段说明,告诉 AI 这个模块的职责边界:
csharp
/// <summary>
/// CLI 模块注册
/// 无状态设计:不依赖数据库,通过事件监听器实现执行记录和输出日志
/// 外部依赖:Runtimes.IModelService, Runtimes.IEnvironmentService
/// </summary>
public static class CLIModule { ... }AI 读代码前先读到注释,就能在正确的架构边界内生成代码。
架构决策记录
关键决策用轻量级文档记录——不是写给人看的详细分析,是写给 AI 看的"为什么":
markdown
# 决策:推流服务从 Java 迁移到 Go
时间:2025.06
原因:
- Java 版本同时开 2 个 Qoder 窗口就卡死
- Go 版本可以同时开 3 个窗口流畅开发测试验证
- 推流服务需要高频迭代快速验证,JVM 启动 30-60 秒不可接受
影响:后续类似服务(网关、中间件)优先考虑 GoAI 读到这个决策记录后,在生成类似服务代码时就不会自动选择 Java。
检查清单即文档
module-architecture-check.md 这种可执行的检查清单,比任何架构文档都精确——它不是给人看的,是给 AI 执行的。
原则
文档先行的核心是:文档不是写给人看的补充说明,是写给 AI 看的约束条件。 人在读代码之前先读文档,AI 也是。区别是:人读了可能忘,AI 不会——但前提是有文档让它读。
四、持续重构
问题
AI 代码有一个"渐进式腐烂"的特点:
- 第一天:代码质量不错,符合架构规范
- 第一周:加了三个功能,开始出现重复代码
- 第一个月:有了六处相似但不完全相同的实现,没人敢动
- 第三个月:重构成本已经高到没人愿意做
代码重复率是 AI 架构腐化最直观的指标。AI 不会主动做"提取公共逻辑"这件事——它每次生成都在做局部最优,重复代码在宏观上不断累积。
解法:定期重构 + Skill 辅助
重构不能靠"自觉",要靠机制。两种重构场景需要不同的处理方式:
被动重构(Skill 驱动)
当 Skill 检查发现问题时,自动触发重构建议:
yaml
# audit-code-duplication.skill
检查规则:
1. 扫描代码库中相似度 > 80% 的代码块
2. 标记可提取为公共方法的重复逻辑
3. 生成重构建议主动重构(定期执行)
每两周或每一个迭代执行一次架构健康检查:
bash
# 架构健康检查脚本
./scripts/architecture-health-check.ps1
→ 检查模块结构合规性
→ 统计代码重复率
→ 检查继承深度
→ 检查碎片化对象数量
→ 生成健康报告健康报告会暴露问题趋势:这周比上周多了几个碎片对象?重复率上升了多少?数据本身会推动治理。
为什么 AI 时代重构更重要
人手写代码时,重构的门槛是"人不想改"。AI 写代码时,重构的门槛变成了"AI 不知道要改"。
人有累积的代码直觉——"这块代码我三周前见过类似的"——会触发重构动作。AI 没有这种直觉,每次都是新的开始。所以需要用 Skill 来替代人的"代码嗅觉",用定期检查来替代人的"重构习惯"。
五、分层架构
问题
AI 生成代码时天然倾向于"跳过层次"——因为它看到的上下文是局部的,在当前文件里直接调 Mapper 比先调 Service 快得多。久而久之,层次边界就被突破了。
更隐蔽的问题是:AI 会在不自觉中创造新的层次。当它觉得一个类"太复杂"时,它会自动把逻辑抽到一个新的 Service 或 Helper 中——看起来是在重构,实际上是在无意义地增加间接层。
解法:用架构原则约束层次
第 08 章的原则一(层次精简)和原则七(模块标准化)就是用来控制分层结构的。
层次边界检查
yaml
# check-layer-dependency.skill
检查规则:
1. Controller 层只能调用 Service 层
2. Service 层可以调用 Mapper 和其他 Service
3. Mapper 层不能调用任何上层
4. 禁止跨层调用(Controller → Mapper 直调)层次健康指标
每一层的代码应该有一个合理的比例范围。如果一个模块的 Service 层只有 20 行代码,而 Controller 层有 800 行——这意味着 Controller 在做不该它做的事:
bash
# 检查每层代码行数分布
./scripts/layer-size-check.ps1
# 输出:模块 X 的 Controller 层 800 行,Service 层 20 行 → 告警和持续重构的关系
分层检查是持续重构的一部分。每次重构都应该验证:新的代码是否保持了正确的层次依赖?如果破坏了层次结构,重构还不如不做。
六、模块设计
问题
AI 生成代码时,倾向于在一个文件中堆逻辑——因为它看到的上下文是最小单元。久而久之,模块边界开始模糊:这个功能应该放在 A 模块还是 B 模块?AI 每次的选择可能不同,同一个功能在不同时间被放到了不同模块。
解法:标准化模块 + 模块入口
第 08 章的原则七(模块标准化)的核心是每个模块只有一个入口——XxxModule.Register()。外部不需要知道模块内部细节,新增模块 = 新增目录 + 新增 Register 调用。
模块边界由访问修饰符强制执行
csharp
// 标准模块结构
XxxModule.cs ← public static(唯一入口)
Interfaces/ ← public(对外暴露的契约)
Implementations/ ← internal(实现细节)
LogFormatHelper.cs ← internal(日志,模块级)编译器强制 internal 的类不能被外部模块引用。这不是约定,是规则。AI 即使想"偷懒"绕过模块边界,编译器也不会让它通过。
模块健康指标
- 模块内聚度:模块内部的类是否都在做相关的事?如果一个模块里有 3 个完全不相关的功能,考虑拆分。
- 模块耦合度:模块 A 引用了多少其他模块的
internal类?如果有,说明模块边界有问题。 - 模块大小:一个模块超过 50 个文件时,考虑是否拆分子模块。
和 Skill 规范化的关系
模块设计不是靠架构师画图来推动的,是靠 Skill 来执行的。check-module-architecture 每天跑一遍,合规就通过,不合规就告警——不需要人来决策。
治理的节奏
| 治理维度 | 频率 | 执行者 | 触发方式 |
|---|---|---|---|
| Skill 检查 | 每次代码生成/提交 | AI + CLI | 自动 |
| 架构健康检查 | 每两周 | CLI 脚本 | 定时 |
| 代码重复检测 | 每周 | CLI 脚本 | 定时 |
| 模块合规检查 | 每次新增模块 | Skill | 自动 |
| 层次违规检测 | 每次提交 | Skill | 自动 |
| 深度重构 | 每迭代 | 人手 + AI | 计划 |
关键原则:治理不是项目结束后的回顾,而是开发过程中的自动动作。 每次 AI 生成了代码,治理就发生一次——不是等人来审查,是 Skill 自动执行。
本章小结
| 治理实践 | 解决什么问题 | 关键手段 |
|---|---|---|
| Skill 规范化 | 规范无法执行 | 规范即 Skill,自动执行 |
| 基础 Skill 参考 | 治理成本高 | 建立基础 Skill 库,即插即用 |
| 文档先行 | AI 无架构全局观 | 在关键边界写 AI 能读的约束 |
| 持续重构 | AI 代码渐进式腐烂 | Skill 驱动 + 定期健康检查 |
| 分层架构 | AI 跨越层次边界 | 层次合规 Skill + 代码量监控 |
| 模块设计 | 模块边界模糊 | 标准化模块 + 编译器强制执行 |
关联:治理是手段不是目的。最后一章回到"人"的角色——AI 时代的架构师应该做什么。