强制执行架构与开发者品味
强制架构与开发品味
Section titled “强制架构与开发品味”试想你聘请了一位速度极快、热情高涨的初级开发人员,他背诵了所有编程语言,却从未真正维护过一个超过一周的仓库。如果你任由他在代码库中自由发挥,他可能会准确实现你要求的功能,但最终的代码很可能像一团乱麻(Spaghetti Code)。在 AI 约束工程(AI Harness Engineering)中,我们正面临着同样的挑战。本章将探讨如何构建机械化的边界,以约束你的 AI Agent(智能体),并确保它们编写的代码符合你特定的架构愿景。
AI“面条代码”的威胁
Section titled “AI“面条代码”的威胁”AI Agent 是优化机器。当接到“添加用户登录功能”这样的任务时,它们会本能地寻找实现该目标的阻力最小路径。由于它们缺乏人类对长期可维护性的直觉理解,因此很容易违反架构原则。
如果没有严格的边界,自主 Agent 可能会对你的代码库犯下以下几项“罪行”:
- 层级跳跃(Layer Bypassing):直接在 React UI 组件内部编写原始 SQL 查询,而不是调用 API。
- 巨石函数(Monolithic Functions):生成庞大的 500 行函数,而不是将其分解为更小、可测试的辅助函数。
- 库泛滥(Library Sprawl):为了在不同文件中解决类似问题,引入了三种不同的 HTTP 客户端库。
- 命名不一致:混用 camelCase、snake_case 和 PascalCase,具体取决于 AI 在其训练数据中最后看到的代码片段。
你不能仅通过在初始系统提示词(System Prompt)中礼貌地要求 AI 来防止这些问题。随着上下文窗口的填满,系统提示词往往会被遗忘或忽略。相反,你必须通过机械手段强制执行架构规则。
定义你的“开发品味”
Section titled “定义你的“开发品味””在强制执行规则之前,你必须先定义你的“开发品味”。品味是将工程团队的主观偏好转化为客观标准的过程。它代表了设计模式、编码范式和结构选择,这些要素使你的代码库具有凝聚力。
为了构建有效的约束(Harness),你必须将这些主观品味转化为机器可以评估的非黑即白的规则。例如:
- 主观品味:“保持 UI 组件简洁且无状态。” -> 客观规则:
/components/ui文件夹中的 React 组件不允许从/services文件夹导入内容。 - 主观品味:“使用整洁的错误处理。” -> 客观规则:每个异步函数都必须使用标准的
Result<Success, Error>返回类型包装器。 - 主观品味:“保持文件短小精悍,易于阅读。” -> 客观规则:任何文件的代码行数不得超过 300 行。
代码化的边界:自定义 Linter 与结构测试
Section titled “代码化的边界:自定义 Linter 与结构测试”为了强制执行你的品味,你需要能够在 Agent 尝试保存或提交代码时自动运行的工具。标准的 Linter(如 JavaScript 的 ESLint 或 Python 的 Flake8)非常适合捕获语法错误,但你必须通过构建**结构测试(Structural Tests)**来更进一步。
结构测试利用抽象语法树(AST)或依赖关系图工具来映射代码不同部分之间的通信方式。如果 Agent 试图将数据库连接直接连接到 Web 路由,结构测试将会失败,从而阻止该变更。
| 测试类型 | 检查内容 | 示例场景 |
|---|---|---|
| 标准 Linter | 语法、风格和基础 Bug | 缺少分号、未使用的变量 |
| 依赖规则 | 模块间允许的导入路径 | 防止 UI 层直接导入数据库 ORM |
| AST 自定义规则 | 特定的代码结构和模式 | 确保每个 API 路由都包含日志记录语句 |
| 规模阈值 | 复杂度与长度限制 | 如果函数超过 50 行则构建失败 |
自动补救提示词的魔力
Section titled “自动补救提示词的魔力”阻止 Agent 提交糟糕的代码只是成功了一半。如果测试失败并抛出一个晦涩的错误(如 Error: Dependency violation in file auth.ts),Agent 可能不知道该如何修复。它可能会开始盲目猜测,导致代码变更陷入混乱的试错螺旋中。
AI 约束工程的秘密武器是将有用的补救指南直接注入到提示词上下文中。当 Agent 违反规则时,你的约束系统不应只是尖叫“错误!”,而应引导 Agent 回归你所偏好的架构路径。
一个有效的补救提示词应包含三要素:
- 精确的错误信息:具体是什么失败了。
- 架构规则:基于你的“品味”提醒该规则存在的原因。
- 正确的模式:提供一个简单的代码片段或说明,向 AI 展示如何正确操作。
实现补救循环
Section titled “实现补救循环”让我们看一个 TypeScript 的概念示例,了解约束系统如何拦截结构测试失败,并将其转化为对 Agent 而言极具教育意义的时刻。
// 约束补救循环示例
function evaluateAgentCode(agentCommitFiles) { const validationResult = runArchitectureLinters(agentCommitFiles);
if (!validationResult.passed) { // Agent 违反了架构规则 const errorDetails = validationResult.errors[0];
// 构建专门的补救提示词 const remediationPrompt = ` 你最近的代码更改未通过架构验证。
错误: ${errorDetails.message} 在文件 ${errorDetails.file} 中
规则提醒: 在本项目中,我们强制执行严格的关注点分离。 UI 组件严禁直接从数据库层导入内容。
如何修复: 请勿直接调用数据库,请从 'services/' 目录导入相应的函数。 如果服务函数不存在,请先在其中创建,然后从你的 UI 组件调用它。
请重写你的代码并重试。 `;
// 将此信息作为下一次指令直接反馈给 Agent sendPromptToAgent(remediationPrompt); }}通过将你的 AI Agent 包裹在这种严密且反馈丰富的约束系统中,你可以机械地强制执行架构边界。Agent 会在实践中实时学习你的“品味”,从一个混乱的代码生成器转变为一个尊重项目结构完整性的、纪律严明的软件工程师。