
1. 从“AI写代码”到“AI写架构”我们正在面对什么最近几个月我身边不少同事和社区里的开发者朋友都开始频繁地使用各种LLM大语言模型来辅助写代码。从最初的“帮我写个排序函数”到现在的“基于Spring Boot设计一个用户权限管理模块”AI生成的内容正从单行代码、单个函数迅速蔓延到整个类、模块甚至初步的系统架构设计。这听起来效率惊人但作为一个在软件工程一线摸爬滚打了十几年的老兵我嗅到了一丝熟悉又陌生的“味道”——不是代码的芬芳而是一种潜在的、由AI大规模生成代码和架构所带来的“技术债”前兆。这种“味道”我称之为“AI-Generated Smells”。它不同于我们熟知的“代码坏味道”Code Smells后者通常指代人类程序员写出的一些可读性差、结构混乱但逻辑尚可运行的代码。而“AI-Generated Smells”则更加隐蔽和系统化它源于AI模型对海量开源代码和文档的“统计性学习”与“模式缝合”可能生成出看似合理、语法正确但在架构一致性、领域逻辑深度、长期可维护性上存在根本缺陷的代码块和设计。当这种生成行为从代码片段升级到架构层面特别是在LLM驱动的智能体Agent开发范式中问题会被指数级放大。简单来说我们正从一个“人编写AI辅助”的时代快速滑向一个“AI生成人审核甚至不审核”的时代。在这个过程中代码和架构的质量控制防线正在发生微妙而危险的转移。这篇文章我想结合最近的观察和一些实际案例深入聊聊“AI-Generated Smells”在代码和架构层面的具体表现、其背后的成因以及我们作为开发者该如何建立新的“嗅觉”和防御机制。2. 代码层面的“AI味道”语法正确性与逻辑合理性的割裂当AI生成单块代码时问题往往最直观。我见过不少新手开发者欣喜地将一段AI生成的、能通过编译甚至通过简单测试的代码直接并入项目却为后续的维护埋下了深坑。2.1 “过度拟合”的样板代码LLM在训练时“见过”海量的GitHub代码这导致它极其擅长生成某种特定框架或库的“样板代码”。比如你让AI“用Python Flask写一个用户登录的API端点”它很可能会给你生成一套包含/login路由、使用flask_jwt_extended、带有密码哈希验证的“标准答案”。问题在于这段代码本身可能没有语法错误但它是否适合你的项目你的项目可能用的是FastAPI或者你根本不需要JWT而是用Session或者你的用户模型字段完全不同。AI生成的是一段“在统计意义上最可能出现的Flask登录代码”而不是“为你的业务场景定制的登录代码”。开发者如果不加修改地使用就会引入不必要的依赖flask_jwt_extended、不符合项目约定的代码风格以及可能完全用不到的冗余逻辑。注意这里的关键不是AI生成了“错误”的代码而是生成了“不匹配”的代码。这种不匹配性就是第一种“AI味道”——上下文失配Context Mismatch。它看起来运行正常但与项目现有的技术栈、架构模式和业务上下文格格不入像一块颜色不同的补丁。2.2 “幻觉”产生的脆弱逻辑LLM的“幻觉”在代码生成中表现为编造不存在的API、误解参数含义或组合出理论上可行但实践中脆弱的逻辑。例如我曾看到一个AI生成的Python函数目的是安全地解析JSON并处理异常import json def parse_json_safely(json_string): try: data json.loads(json_string) return data except json.JSONDecodeError as e: # AI可能会生成这样的“通用”错误处理 print(fAn error occurred: {e}) return {error: str(e), status: failed}这段代码的问题在于其错误处理的“通用性”掩盖了业务特异性。在Web API中你可能需要抛出特定的HTTP异常如HTTP 400 Bad Request在后台任务中你可能需要将错误记录到日志系统并重试而这里简单打印日志并返回一个字典很可能破坏上游调用者的错误处理逻辑。AI倾向于生成“平均化”的、看似普适的方案却忽略了错误处理是高度依赖调用链上下文和业务规则的。2.3 缺乏“设计意图”的代码组合人类程序员在写一个复杂函数时心中是有“设计意图”和“不变式”的。比如一个函数要保证“无论发生什么数据库连接必须在函数退出前关闭”。AI生成的代码可能会正确地使用try...finally块但它不理解这个模式背后的“资源管理”意图。当需求稍作变化比如需要在函数中间提前返回AI生成的后续代码就可能破坏这个“不变式”因为它只是模仿了模式而非理解其目的。这种“知其然不知其所以然”的生成方式导致代码在初次集成时可能工作但在后续迭代中极易被破坏形成脆弱抽象Brittle Abstraction的味道。修改AI生成的代码有时比从头重写更危险因为你很难确定哪些部分承载了关键的设计约束。3. 架构层面的“AI味道”系统级设计的“拼贴画”风险当任务从“写一个函数”升级到“设计一个微服务”或“规划一个模块的架构”时AI-Generated Smells的危害性会急剧上升。架构决策的影响是全局性和长期性的。3.1 架构风格的“大杂烩”你让AI“为一个电商系统设计后端架构”。它可能会给你一个包含用户服务、商品服务、订单服务、支付服务的微服务列表每个服务都配有REST API、独立的数据库并建议使用Kafka进行服务间通信。这听起来很“标准”但这就是问题所在。AI基于它学到的“最佳实践”合集给出了一个“流行架构”的拼盘。它不会问你你的团队规模是否支撑得起微服务的运维复杂度你的业务流量是否真的需要服务拆分带来的独立部署能力你的领域边界是否清晰到足以划分出这些服务商品和库存的变更是否必须强一致使用Kafka是出于确切的异步解耦需求还是仅仅因为“大家都在用”结果可能就是一个初创团队被引入了一套为大型互联网公司设计的、过度复杂的微服务架构反而拖慢了开发速度增加了调试难度。这是一种过度工程Over-Engineering的AI味道源于AI对“现代化架构”模式的机械推荐缺乏对项目阶段、团队能力和业务上下文的最小可行架构MVA的考量。3.2 数据流与边界上下文的模糊在领域驱动设计DDD中“限界上下文”是核心。AI在生成架构描述时可能会画出清晰的方框图但方框之间的数据流和职责边界往往是模糊或矛盾的。例如在一个“文章发布系统”中“文章”在“创作上下文”中是一个富文本草稿在“发布上下文”中是一个待审核的实体在“展示上下文”中是一个只读的渲染结果。AI生成的架构可能只会定义一个ArticleService和一个Article表将所有属性内容、状态、审核意见、阅读数混在一起。这导致了贫血模型Anemic Domain Model和上下文污染Context Pollution不同业务逻辑相互纠缠变更风险扩散。AI很难理解这种隐式的、高度依赖业务知识的“边界”它倾向于生成结构上扁平、数据上集中的“单块”设计因为这在其训练数据中出现的概率最高。3.3 非功能性需求的缺失或错配架构设计必须考虑性能、安全性、可观测性、可扩展性等非功能性需求。AI在生成架构方案时对这些要素的处理往往是模板化的、分离的。安全性AI可能会在API网关的配置里加上“使用JWT”但不会深入考虑令牌的刷新机制、密钥轮换、不同端点的细粒度权限控制RBAC/ABAC。可观测性AI会建议“使用Prometheus和Grafana”但不会定义关键的业务指标如“订单创建失败率”、不会设计有意义的链路追踪Trace上下文传递。数据一致性在涉及多个服务的业务流程中AI可能会简单地建议“使用分布式事务Saga”但不会深入分析该业务流程是否适合Saga模式也不会给出具体的状态机设计和补偿事务逻辑。这种对非功能性需求的浅层覆盖Superficial Coverage使得生成的架构图看起来很美但一旦进入实现就会发现大量关键细节是空白或错误的需要人工重新填补而这时往往已经基于有缺陷的架构做出了大量开发投入。4. Agent-Driven Development当AI开始自主决策与迭代如果说单次的AI代码/架构生成是“静态风险”那么LLM驱动的智能体Agent开发范式则将“AI-Generated Smells”动态化、系统化了。在这种模式下AI Agent被赋予目标如“实现一个用户注册功能”它可以自主规划任务、编写代码、运行测试、调试错误并循环迭代。4.1 “局部最优”的迭代陷阱Agent在迭代中其优化目标往往是“让当前测试通过”或“解决刚刚抛出的编译错误”。这是一个典型的局部优化。为了通过一个测试Agent可能会采取一些破坏整体设计或引入技术债的“捷径”。一个真实场景的模拟Agent的任务是“修复一个因数据库连接超时而导致的失败测试”。它的“思考”过程可能是发现错误日志指向get_db_connection()超时。最简单的“修复”是去修改这个函数将超时时间从5秒增加到60秒。测试通过了。然而真正的问题可能是数据库连接池泄漏或者某个慢查询拖垮了数据库。增加超时时间掩盖了问题使得系统在负载下行为更不可预测性能隐患更大。人类开发者可能会去查看监控、分析连接池状态、定位慢查询。但Agent的“目标函数”是“通过测试”而不是“找到根本原因并实施可持续的修复”。这会导致症状缓解而非根因治疗Symptom Alleviation的味道问题被一次次地掩盖和转移最终积累成一场灾难。4.2 架构腐蚀的加速在Agent-Driven Development中多个Agent可能协作或依次修改同一个代码库。如果没有一个强约束的、机器可读的“架构守护规则”Agent的修改很容易侵蚀原有的架构约定。例如最初的架构规定“所有外部服务调用必须通过ServiceClient层以便统一熔断和监控”。一个负责实现新功能的Agent为了快速完成任务可能直接在一个业务逻辑类里用HttpClient发起了请求。代码能工作测试也能过但架构原则被破坏了。随着这类修改越来越多清晰的架构层次会逐渐模糊退化成“大泥球”Big Ball of Mud。这种架构漂移Architecture Drift在人工开发中也会发生但Agent的快速、自动化特性会使其发生速度提高一个数量级。4.3 知识库的“幻觉”污染许多Agent系统会配备向量知识库存储项目文档、API手册等。Agent在决策时可以检索这些知识。但如果知识库本身包含了过时的、错误的或由之前AI生成的“有味道”的代码示例呢这就形成了一个负反馈循环AI用有问题的知识生成代码这些代码又被作为“成功案例”存入知识库进而影响后续的生成。知识库被幻觉污染Hallucination Pollution其作为可信参考的价值会迅速衰减。5. 建立防御开发者如何应对“AI-Generated Smells”面对这些新的挑战我们不能因噎废食拒绝AI辅助开发。相反我们需要升级我们的工程实践和审查流程建立针对“AI-Generated Smells”的防御体系。5.1 从“代码审查”升级到“AI生成物审查”传统的Code Review关注逻辑错误、风格一致性。现在我们需要增加新的审查维度上下文匹配度审查这段生成的代码/设计是否与我们的技术栈、现有架构模式、团队约定完全匹配是否需要适配设计意图审查AI实现的这个模式如工厂模式、观察者模式其背后的设计意图在当前场景下是否成立有没有更简单直接的写法非功能性需求审查生成的代码是否考虑了错误处理、日志、监控、安全架构设计是否明确了性能、扩展性、数据一致性的方案“为什么”审查要求开发者或Agent在提交时不仅提供代码还要提供简短的设计理由或备选方案考虑。这能暴露AI的机械选择过程。5.2 强化机器可检查的架构约束对抗架构腐蚀必须将架构原则从文档转化为机器可执行的规则。使用架构守护工具例如对于Java项目可以使用 ArchUnit 编写测试规定“Controller层的类不能直接依赖Repository”、“Service命名结尾的类必须在service包内”。将这些测试集成到CI/CD流水线任何Agent或人工提交的代码如果违反都会导致构建失败。定义清晰的API契约和数据结构使用OpenAPI/Swagger严格定义接口使用Protobuf或JSON Schema定义核心数据结构。让Agent在生成的代码中必须遵循这些强契约减少“自由发挥”带来的不一致性。模板化与代码生成对于高度重复且规范的代码如CRUD接口、DTO与其让AI自由生成不如维护一套项目特定的代码生成模板如使用JHipster、Spring Initializr的自定义模板。让AI在模板的约束下填充内容而非从头创造。5.3 为AI设定更精准、更富上下文的任务给AI的指令质量直接决定生成物的质量。模糊的指令得到模糊的、有味道的代码。坏指令“写一个用户服务。”好指令“在我们现有的Spring Boot项目中遵循com.example.user包下的现有模式参考UserController和UserServiceImpl实现一个UserProfileService接口及其实现类。该服务需要提供根据用户ID查询完整资料包含从account表和profile表联查的信息的方法。注意使用已有的Cacheable注解进行缓存缓存键为userProfile: userId。异常处理需统一抛出BusinessException。”后者的指令包含了技术栈、项目上下文、参考模式、具体业务逻辑、非功能性需求缓存和异常规范。这能极大限制AI的生成空间使其输出更贴合项目实际。5.4 建立“AI生成物”的质量门禁和溯源在CI/CD流水线中引入针对AI生成代码的静态分析检查。定制化Lint规则除了常规的代码风格检查可以添加规则来检测某些典型的“AI味道”模式例如“是否存在打印语句而非日志框架”、“异常捕获是否过于通用且未重新抛出”等。标记与溯源要求所有AI辅助生成的代码块无论是完整文件还是片段都必须有明确的注释标记例如// generated-by: claude-code, prompt: xxxx。这有助于在后期维护时理解代码的由来和原始意图也便于进行专项的质量审计。AI生成的代码和架构正在成为我们软件系统中越来越重要的一部分。它们带来了巨大的效率提升也引入了新型的、系统性的质量风险。“AI-Generated Smells”不会取代传统的“Code Smells”而是会与它们共存甚至相互叠加。作为开发者我们的核心价值正在从“编写语法正确的代码”向“定义问题、设定约束、进行高阶抽象和深度审查”迁移。培养对“AI味道”的敏锐嗅觉建立与之配套的工程纪律是我们在这个新时代保持软件系统健康、可控的必备技能。这不再是一个可选项而是决定项目能否在AI辅助的洪流中稳健前行的关键。