尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
用Agent Skills为AI生成代码做设计审查:基于《软件设计的哲学》的工程实践
1. 从“能跑就行”到“改不动了”一个被忽视的工程拐点代码生成工具现在确实好用。你描述一个需求几秒钟之后一个能跑的函数、一个完整的组件、甚至一整个模块就出现在屏幕上。我身边不少朋友已经习惯了这种节奏遇到问题先让工具生成一版跑通了就提交跑不通就继续追问直到测试通过为止。这个过程非常爽爽到让人产生一种错觉——写代码这件事的门槛好像消失了。但真正在维护项目的人会告诉你另一个故事。三个月后你回头看那段生成的代码变量名是data1、data2、tempResult函数体两百行起步嵌套的if像俄罗斯套娃一个文件里塞了七八个职责完全不同的类。你想改一个字段的校验逻辑结果发现这个校验散落在四个地方改完三处漏了一处线上直接报错。这时候你才意识到代码生成解决的是“写出来”的问题但完全没有解决“写得好”的问题。这就是我想聊的核心矛盾。生成工具擅长的是从零到一它能在没有上下文的情况下快速产出一个可运行的版本。但软件设计真正难的部分从来不是从零到一而是从一到十、从十到一百的过程中如何让代码保持可理解、可修改、可扩展。复杂度不会因为生成速度快就自动消失它只是被推迟了然后在某个你最不想面对的时刻集中爆发。我最近做了一件事把《软件设计的哲学》这本书里的核心思想拆解成一套可执行的 Agent Skills让代码生成工具在写完代码之后自动进入一个“设计审查”的环节。这套东西不是简单的提示词模板而是一组有明确触发条件、有具体检查项、有输出格式约束的技能模块。下面我会把这套方案的完整设计思路、实现细节、踩过的坑和实际效果全部拆开来讲。2. 为什么是《软件设计的哲学》而不是别的设计模式书2.1 复杂度是唯一真正的敌人市面上讲软件设计的书很多设计模式那本经典偏重具体场景的解决方案重构那本偏重代码级别的改善手法整洁代码那本偏重编码规范。这些书都很好但它们有一个共同的问题它们告诉你“应该怎么做”但没有告诉你“什么时候该停下来检查”。《软件设计的哲学》不一样。这本书的核心论点非常集中软件开发中唯一真正重要的问题就是复杂度管理。作者把复杂度定义为“任何让系统难以理解和修改的东西”然后从三个维度拆解它依赖关系、模糊性、以及变化带来的连锁反应。这个定义的好处在于它不依赖于具体的编程语言、框架或架构风格而是一个跨技术栈的通用判断标准。我选择这本书作为 Agent Skills 的理论基础原因有三个。第一它的核心概念足够少少到可以转化成可执行的检查项。第二它的判断标准足够具体比如“一个模块的接口是否比实现简单”这种问题是可以被自动化检查的。第三它不教条它承认有时候为了性能或交付压力需要做妥协但要求你清楚地知道自己在妥协什么。2.2 从“设计原则”到“可执行检查项”的转化书里的概念要变成 Agent Skills中间需要一个转化过程。我拿几个核心概念举例说明这个转化是怎么做的。概念一信息隐藏。书里说模块应该隐藏设计决策只暴露必要的接口。转化成检查项就是这个模块导出的函数和类型中有多少是外部真正需要的如果导出的数量超过实际使用数量的两倍就标记为“接口过宽”。这个检查可以通过静态分析工具自动完成不需要人工判断。概念二依赖方向。书里说依赖应该指向稳定的方向。转化成检查项就是这个文件导入的模块中有多少是它不应该知道的比如一个工具函数文件导入了业务逻辑模块这就是依赖方向错误。这个检查可以通过分析导入语句的路径深度和模块类型来判断。概念三变化放大。书里说一个小的变化不应该导致多个文件的大幅修改。转化成检查项就是如果修改一个数据结构的字段需要同时修改超过三个文件就标记为“变化放大风险”。这个检查需要结合版本控制的历史数据来分析。注意这些检查项都不是绝对的对错判断而是风险提示。Agent Skills 的输出应该是“这里可能有问题建议你看看”而不是“这里错了必须改”。这个区别很重要因为自动化工具没有足够的上下文来做最终判断。3. Agent Skills 的整体架构设计3.1 为什么不用单一的提示词模板最开始我试过最简单的方法写一个很长的提示词把书里的原则都塞进去让工具在生成代码后自己检查。效果很差。原因是提示词太长会导致注意力分散工具会随机挑几个原则来检查而且每次检查的深度不一致。更糟糕的是它经常把“检查”变成“重写”直接给你一版新的代码但你不知道它改了什么、为什么改。所以我决定用 Agent Skills 的架构。每个 Skill 是一个独立的、有明确输入输出定义的模块。主流程在代码生成完成后依次调用这些 Skill每个 Skill 只负责一个维度的检查输出结构化的结果。这样做的好处是每个 Skill 的提示词可以很短很聚焦检查深度可控而且输出格式统一方便后续汇总和展示。3.2 五个核心 Skill 的分工我最终定义了五个 Skill覆盖从微观到宏观的五个层次。这个分层方式参考了书里对复杂度的拆解但做了工程化的调整。Skill 名称检查层次核心问题触发时机命名与注释审查微观名字是否准确表达了意图每次生成后函数复杂度审查函数级函数是否做了太多事情每次生成后模块接口审查模块级接口是否比实现简单每次生成后依赖关系审查文件级依赖方向是否合理每次生成后变化影响审查系统级修改是否会放大提交前这五个 Skill 不是并行执行的而是有先后顺序。命名和函数复杂度是最基础的如果这两个层面问题很大后面的模块和依赖审查就没有意义。所以主流程会先跑前两个如果发现严重问题会先提示修复然后再继续后面的检查。3.3 输出格式的统一约定每个 Skill 的输出必须遵循同一个 JSON 结构这样主流程才能统一处理。结构定义如下{ skill_name: 函数复杂度审查, status: pass | warn | fail, issues: [ { severity: high | medium | low, location: 文件路径:行号, description: 具体问题描述, suggestion: 建议的修改方向 } ], summary: 一句话总结 }这个结构的关键在于suggestion字段。它不是直接给出修改后的代码而是给出修改的方向。比如“考虑将校验逻辑抽取为独立函数”而不是直接贴一段重构后的代码。这样做是为了让开发者保持对代码的掌控感而不是被工具牵着走。4. 核心 Skill 的实现细节与实操要点4.1 命名与注释审查 Skill这个 Skill 看起来简单但实际实现时有很多细节要注意。命名审查的核心判断标准是一个名字是否能让读者在不看实现的情况下理解它的用途。我用的检查规则包括变量名是否包含无意义的数字后缀如data1、temp2函数名是否使用了过于泛化的动词如handle、process、do布尔变量是否以is、has、can开头常量是否全部大写。这些规则听起来很基础但实际项目中违反的情况非常普遍。注释审查的规则更微妙一些。书里有一个观点我特别认同好的注释解释“为什么”坏的注释重复“是什么”。所以我的检查规则是如果注释的内容可以直接从代码本身读出来比如// 将 a 和 b 相加对应a b就标记为“冗余注释”。如果注释解释了某个决策的原因比如// 使用二分查找因为数据已排序就标记为“有效注释”。实操心得这个 Skill 最容易产生误报。比如有些项目故意用data1、data2来对应外部系统的字段名这时候改名反而会增加理解成本。所以我在输出中会把这类问题标记为low严重度并加上“如果与外部约定一致可忽略”的说明。4.2 函数复杂度审查 Skill函数复杂度是代码可读性最直接的指标。我用的核心指标是圈复杂度但做了调整。标准的圈复杂度计算每个if、for、while、case都加一但实际经验告诉我嵌套的if比平铺的if危害大得多。所以我在计算时给嵌套结构加了权重每增加一层嵌套该分支的权重乘以 1.5。具体实现时我用了一个简单的解析器来遍历代码的抽象语法树。对于每个函数计算加权圈复杂度然后根据阈值判断。阈值设定如下加权复杂度 ≤ 5通过6 ≤ 加权复杂度 ≤ 10警告加权复杂度 10失败除了复杂度这个 Skill 还会检查函数的参数数量。超过四个参数的函数会被标记因为参数越多调用者需要记住的东西就越多。书里有一个很形象的比喻一个函数的参数列表就像它的使用说明书如果说明书太长说明这个函数做的事情太多。4.3 模块接口审查 Skill这个 Skill 的检查逻辑是对比模块导出的内容和实际被外部使用的内容。如果一个模块导出了 20 个函数但外部只用了 3 个那另外 17 个就是不必要的暴露。这个检查需要结合项目内的引用分析来做不能只看单个文件。实现时我用了两步第一步扫描整个项目建立每个模块的导出符号表和引用关系图。第二步对于每个模块计算“导出符号中被外部引用的比例”。比例低于 30% 的模块会被标记为“接口过宽”。这个 Skill 还有一个补充检查模块的导出中是否包含内部实现细节。比如一个数据访问模块导出了一个ConnectionPool类但外部只需要query和execute两个函数。这种情况下ConnectionPool的导出就是不必要的应该改为内部类。注意有些模块的导出是为了测试目的这种情况下接口过宽是合理的。所以我在输出中会区分“生产代码引用”和“测试代码引用”只有生产代码引用比例低才会标记为问题。4.4 依赖关系审查 Skill依赖关系审查的核心是判断依赖方向是否合理。书里有一个原则依赖应该指向更稳定的方向。什么叫更稳定就是更少变化的模块。工具函数比业务逻辑稳定业务逻辑比 UI 稳定UI 比配置稳定。实现时我给不同类型的模块定义了稳定性等级工具函数5、数据模型4、业务逻辑3、UI 组件2、配置文件1。然后检查每条依赖边的方向如果从低稳定性模块指向高稳定性模块就是合理的反之则标记为“依赖倒置”。这个 Skill 还会检查循环依赖。循环依赖是复杂度的重要来源因为它意味着两个模块必须一起理解、一起修改。检测循环依赖用的是标准的图算法这里不展开。但我要强调的是循环依赖不一定要立刻消除但必须被记录和监控。所以这个 Skill 的输出中循环依赖会被标记为medium严重度并附上“建议在下次重构时处理”的说明。4.5 变化影响审查 Skill这个 Skill 是最难实现的因为它需要结合版本控制的历史数据。我的做法是分析最近 20 次提交中每次提交修改的文件集合。如果某个文件在超过 60% 的提交中都被修改就标记为“高频变更文件”。如果两个文件在超过 40% 的提交中同时被修改就标记为“耦合变更对”。这个分析的价值在于它揭示了代码的实际变化模式而不是理论上的依赖关系。有时候两个模块在代码层面没有直接依赖但在实际开发中总是被一起修改这说明它们之间存在隐性的耦合。这种耦合在代码审查时很难发现但通过提交历史可以清晰地暴露出来。实操心得这个 Skill 需要至少 20 次提交的历史数据才能给出有意义的分析结果。对于新项目我会跳过这个 Skill或者只做简单的文件变更频率统计。5. 完整实操流程从代码生成到设计审查5.1 环境准备与工具链配置这套方案不依赖特定的代码生成工具任何能输出代码文件的工具都可以接入。我用的工具链包括一个代码生成工具负责生成代码、一个静态分析工具负责解析代码结构、一个版本控制工具负责提供历史数据。这三个工具通过一个主控脚本串联起来。主控脚本用 Python 编写核心逻辑是监听代码生成完成事件然后依次调用五个 Skill最后汇总输出。每个 Skill 的实现方式可以不同命名审查可以用正则表达式函数复杂度审查需要解析抽象语法树依赖关系审查需要构建引用图。我选择用 Python 是因为它的解析库和图形库比较成熟而且脚本本身容易维护。配置方面最重要的是阈值设定。我在前面给出了默认阈值但实际使用时需要根据项目规模和团队习惯调整。比如一个大型遗留项目函数复杂度的阈值可以适当放宽否则会收到大量警告反而让人麻木。我的建议是新项目用严格阈值遗留项目用宽松阈值然后逐步收紧。5.2 一次完整的审查过程记录我拿一个实际生成的模块来演示整个流程。这个模块是一个用户数据处理的工具类生成工具根据“读取用户数据、校验格式、转换字段、输出结果”这个需求生成了大约 150 行代码。第一步命名与注释审查。输出结果显示有三个变量名包含数字后缀user1、user2、result1两个函数名过于泛化processData、handleResult五条注释是冗余的重复了代码本身的内容。严重度都是low因为功能上没有问题只是可读性差。第二步函数复杂度审查。输出结果显示processData函数的加权圈复杂度是 14超过失败阈值。具体问题是函数内部有 6 个if分支其中 3 个是嵌套的最深层嵌套达到 4 层。参数数量是 5 个超过警告阈值。严重度是high因为复杂度高的函数很难测试和维护。第三步模块接口审查。这个模块导出了 8 个函数但外部只引用了 2 个。导出比例是 25%低于 30% 的阈值。标记为medium严重度建议将不需要导出的函数改为内部函数。第四步依赖关系审查。这个模块导入了三个其他模块一个工具函数模块稳定性 5、一个数据模型模块稳定性 4、一个业务逻辑模块稳定性 3。从工具类稳定性 5导入业务逻辑稳定性 3是依赖倒置标记为medium严重度。第五步变化影响审查。由于这是一个新模块没有历史数据跳过。汇总输出后我根据这些提示做了修改重命名了变量和函数将processData拆分成三个小函数将不需要导出的函数改为内部函数将业务逻辑的调用改为通过接口注入。修改后的代码行数从 150 行增加到 180 行但可读性和可测试性明显提升。5.3 参数计算与阈值调整的实际案例阈值设定不是拍脑袋决定的需要根据实际数据来调整。我拿一个中型项目约 5 万行代码做了统计发现函数加权圈复杂度的分布如下中位数是 375 分位是 690 分位是 1195 分位是 16。这意味着如果阈值设为 10会有 10% 的函数被标记如果设为 16只有 5% 被标记。我最终选择 10 作为警告阈值、16 作为失败阈值。理由是10 以下的函数基本不需要拆分10 到 16 之间的函数需要关注但不一定有问题16 以上的函数几乎肯定需要拆分。这个阈值在实际使用中产生的警告数量适中既不会让人忽略也不会让人崩溃。参数数量的阈值也是类似的方法。统计显示参数数量的中位数是 275 分位是 390 分位是 4。所以我把警告阈值设为 4失败阈值设为 6。超过 6 个参数的函数在实际项目中非常少见一旦出现通常意味着设计有问题。6. 常见问题与排查技巧实录6.1 误报太多怎么办这是最常见的问题。刚开始用的时候一个 200 行的文件可能产生 30 条警告其中大部分是误报。原因通常是阈值太严格或者检查规则没有考虑项目的特殊情况。我的解决方法是三步走。第一步先只启用high严重度的检查忽略medium和low。这样警告数量会减少到 5 条以内都是真正需要关注的问题。第二步根据项目特点调整规则。比如如果项目约定用data1、data2来对应外部字段就在命名审查中加白名单。第三步逐步启用更多检查但每次只增加一个维度观察一周后再决定是否保留。避坑技巧不要一次性启用所有 Skill。先启用函数复杂度审查因为这个维度的误报最少、价值最高。运行一周后再加入命名审查再一周后加入接口审查。这样团队有时间适应也能逐步调整阈值。6.2 工具生成的代码风格不一致不同的生成工具、甚至同一个工具的不同版本生成的代码风格可能不同。这会导致审查结果不稳定。比如一个工具生成的代码用驼峰命名另一个用下划线命名命名审查的规则就需要同时支持两种风格。我的处理方式是在审查之前先做一次风格归一化。具体来说用格式化工具统一缩进和换行用命名转换工具统一命名风格。归一化之后再做审查结果就稳定多了。这个步骤看起来多余但实际上节省了大量处理误报的时间。6.3 如何处理“合理但违反规则”的情况有些代码虽然违反了规则但在特定场景下是合理的。比如一个性能敏感的循环展开写虽然增加了复杂度但减少了函数调用开销。这种情况下工具应该允许开发者标记“已知例外”。我在输出格式中加了一个exceptions字段开发者可以在代码中用特殊注释标记例外审查时会跳过这些位置。比如// design-check: ignore complexity表示这个函数的复杂度问题已知且接受。这个机制的关键是例外必须显式标记不能默默忽略。这样既尊重了开发者的判断又保持了审查的严肃性。6.4 审查结果如何与团队流程结合审查结果不应该只是一个报告而应该嵌入到开发流程中。我的做法是在代码提交前自动运行审查如果出现high严重度的问题提交会被阻止直到问题修复或标记为例外。medium和low的问题只记录不阻止提交但会在周会上汇总展示。这个流程的关键是阻止提交的阈值要足够高否则开发者会想办法绕过。我只阻止high严重度的问题而且high的定义非常严格只有函数复杂度超过 16、或者出现循环依赖、或者接口导出比例低于 10% 才算high。这样一周下来阻止提交的次数通常不超过三次开发者不会觉得被干扰。6.5 常见问题速查表问题现象可能原因排查方法解决方向警告数量过多阈值太严格统计警告的严重度分布先只启用 high 级别审查结果不稳定代码风格不一致对比两次审查的差异先做风格归一化开发者忽略警告警告价值低抽查警告的准确性调整规则或加白名单审查耗时过长分析范围太大计时每个 Skill 的耗时只审查变更的文件例外标记滥用阻止阈值太低统计例外标记的数量提高阻止阈值7. 实际效果与持续改进这套方案在一个约 8 万行的项目上运行了三个月。最直观的变化是代码审查会议的时间从平均 45 分钟缩短到 20 分钟因为很多基础问题在提交前就被工具标记并修复了。另一个变化是新加入的开发者上手时间从两周缩短到一周因为代码的可读性明显提升命名和注释的质量稳定了很多。但我也要诚实地说这套方案不是银弹。它解决的是“明显可以改进”的问题比如函数太长、命名太差、依赖太乱。它解决不了“设计方向错误”的问题比如选错了架构模式、用错了技术栈。这些需要人来判断工具只能提供信息。我目前在做的一个改进是把审查结果和历史数据结合起来生成一个“复杂度趋势图”。如果某个模块的复杂度在持续上升就提前预警而不是等到问题爆发才处理。这个功能还在试验阶段效果好的话再分享。最后分享一个我在使用中总结的小技巧把审查结果当作代码审查的输入而不是替代品。工具标记的问题在人工审查时重点看工具没标记的地方人工审查时快速过。这样人和工具各司其职效率最高。完全依赖工具或者完全不用工具都不是好的选择。
RELATED

相关推荐

生成式AI知识真实性验证:从断言抽取到多源交叉的实操指南

生成式AI知识真实性验证:从断言抽取到多源交叉的实操指南

简介:这份文档面向人工智能研究者、相关专业学生及需要评估大模型生成内容可靠性的从业者,系统解决生成式人工智能知识真实性验证的方法论与实操问题。资源为docx格式,共1个文件,压缩包约82KB,内容围绕AI基础知识、验证…

📅 2026/10/11 10:01:19
BERT微调命名实体识别:从业务语料翻车到F1提升的实战指南

BERT微调命名实体识别:从业务语料翻车到F1提升的实战指南

简介:这份资源面向自然语言处理初学者与算法工程师,围绕命名实体识别任务,讲解如何基于BERT中文预训练模型进行微调落地。内容从实体类型定义入手,覆盖地址、书籍、公司、游戏、政府、电影、姓名、组织、职位、场景共10类实体&…

📅 2026/10/11 10:01:19
Hadoop四节点集群实战:成绩分析系统与MapReduce避坑指南

Hadoop四节点集群实战:成绩分析系统与MapReduce避坑指南

简介:这份资源是面向高校计算机相关专业学生与大数据入门学习者的课程设计文档,围绕基于Hadoop的成绩分析系统展开,帮助读者理解如何用分布式计算解决学生成绩数据量大、管理效率低的问题。压缩包内共1个docx文件,约1.46MB&#x…

📅 2026/10/11 10:01:19
MORE NEWS

更多资讯

📰

AI提示词工程实战:打造小红书爆款文案的完整指南

简介:面向新媒体运营从业者、自媒体达人与网络营销人士的AI指令合集,聚焦小红书爆款文案的批量生成。内容覆盖用户调研、主题选定、标题撰写、正文结构及SEO标签设置等全流程,内置角色设定、二极管标题法、爆款关键词库、emoji用法等实战技巧…

📰

Python电影数据可视化全流程:pandas清洗、Flask接口与ECharts图表实战

简介:这是一份基于Python的电影数据可视化分析系统完整项目,面向计算机专业毕业设计、课程大作业及数据可视化实战练习人群。项目以电影数据为对象,覆盖数据导入、数据库管理、Pandas统计分析、可视化出图与简单预测等环节,源码均…

📰

Python数据库学习心得:SQLite、MySQL、PostgreSQL优缺点

前言 先说一个方法论问题:「优缺点」这个说法脱离场景是没有意义的。SQLite 的「不支持高并发写」在桌面笔记应用里根本不是缺点,因为那里就不存在并发写;PostgreSQL 的「功能丰富」在一个只存几十行配置表的小工具里也换不来任何收益。所以本…

📰

深度学习糖尿病足溃疡风险评分系统:数据到部署全流程

简介:面向医学图像分析、人工智能及临床辅助决策方向的开发者,该资源围绕基于深度学习的糖尿病足溃疡(DFU)风险评分系统,提供了从数据处理、模型设计、训练验证到可视化分析的完整工程代码。压缩包共54个文件&#xff…

📰

TurboQuant存储格式详解:2/4个值如何挤进一个字节完成比特打包

【免费下载链接】turboquant TurboQuant: Near-optimal KV cache quantization for LLM inference (3-bit keys, 2-bit values) with Triton kernels vLLM integration 项目地址: https://gitcode.com/gh_mirrors/tu/turboquant 点击查看 免费下载 TurboQuant 是一…

📰

DeepSeek-R1推理模型提示语设计实战指南

简介:清华大学新闻与传播学院新媒体研究中心推出的这份DeepSeek入门到精通指南,聚焦国产大模型DeepSeek及开源推理模型DeepSeek-R1的研发与应用,适合有一定AI基础、希望深入实践推理模型的研究人员和技术爱好者。内容从“DeepSeek是什么”“能…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬