1. 项目概述:当AI成为你的“初级工程师”

最近和团队一起,完整地跑通了一个用AI辅助开发新功能模块的项目。整个过程非常典型:我们利用AI编程工具,从零开始生成一个具备基础功能的代码版本,只花了大约1小时。这个速度,放在以前手动编码的时代,是不可想象的。但紧接着,我们投入了大约2-3天的时间,进行密集的代码审查(Code Review)、逻辑修正、边界测试和工程化适配。

这巨大的时间差,恰恰是当前AI协同开发从“玩具”走向“工程”的核心矛盾点,也是所有想将AI真正融入研发流程的团队必须直面的现实。AI不是魔法,它更像一个天赋极高但经验不足、有时会“想当然”的初级工程师。它能快速给你一个“能用”的草案,但距离“好用”、“可靠”、“可维护”的生产级代码,还有很长一段需要人类工程师引领和打磨的路要走。

这篇文章,我想结合这次具体的落地实践,拆解这“1小时生成”与“2-3天修正”背后的每一个环节。我们会深入探讨:AI生成的代码到底在哪些地方埋了“坑”?为什么Review变得如此重要且耗时?以及,我们如何建立一套高效的“人-AI”协作流程,让AI真正成为提效的杠杆,而不是引入混乱的源头。无论你是正在尝试AI编程的开发者,还是负责团队技术选型的负责人,这些踩过的坑和总结出的模式,或许能给你带来一些直接的参考。

2. 核心思路:将AI定位为“草案生成器”而非“最终交付者”

在项目启动前,我们团队内部首先达成了一个最重要的共识: 重新定义AI在开发流程中的角色 。过去,我们可能幻想AI能接收需求后,直接吐出完美代码。但现在我们更倾向于将其看作一个“超级强大的代码草案生成器”或“高级自动补全”。这个定位的转变,直接决定了后续所有协作策略和验收标准。

2.1 为什么是“草案生成器”?

因为当前主流的大模型(无论是GPT-4、Claude 3,还是专用的Cursor、GitHub Copilot),其本质是基于概率的文本生成器。它们在代码上的优势是:

  • 知识广度 :见过并学习过海量的开源代码和模式。
  • 生成速度 :能快速组合已知模式,形成一段连贯的代码。
  • 基础正确性 :对于常见、标准的业务逻辑和算法,正确率较高。

但其局限性也同样明显:

  • 缺乏深度上下文 :AI对你项目的独特架构、历史债务、团队约定的特殊规范、乃至某个复杂业务域的具体约束,缺乏深度的、持续的理解。它每次回答都基于有限的上下文窗口。
  • “幻觉”与捏造 :当遇到它知识盲区或模糊需求时,它倾向于生成“看起来合理”但实际错误或无效的代码,比如使用一个不存在的API,或误解某个库的用法。
  • 忽视非功能需求 :安全性、性能、可观测性(日志、监控)、错误处理完备性、可测试性等,AI通常处理得比较粗糙或直接忽略。
  • 设计连贯性差 :难以保证生成代码与项目整体架构风格一致,可能会引入不一致的设计模式或数据流。

因此,我们制定的核心协作原则是: 让AI做它擅长的事(快速生成草案),让人做AI不擅长的事(深度设计、审查、修正与集成) 。本次项目的目标,是开发一个内部运营用的数据报表导出服务,涉及多表关联查询、数据格式化、异步文件生成和提供下载链接。我们明确要求AI生成“功能实现草案”,而将架构设计、接口规范、错误码定义等前期工作由人工完成。

2.2 本次项目的协同流程设计

基于上述定位,我们设计了如下流程,这后来被证明是高效的关键:

  1. 人工阶段(需求澄清与设计) :产品需求文档(PRD)评审后,资深工程师先进行技术方案设计,定义核心接口、数据库访问层(DAO)方法、关键数据结构、以及与非功能需求相关的要点(如分页查询的最大限制、导出文件格式要求、任务超时时间等)。这部分形成了给AI的“详细设计说明书”。
  2. AI阶段(草案生成) :将设计说明书、相关的现有项目代码片段(如统一的响应封装类、日志工具类)作为上下文,提交给AI工具(我们主要使用Cursor),要求其生成具体的Service实现类、Controller层接口等。此时,1小时的“奇迹”发生了。
  3. 人工阶段(深度审查与修正) :生成的代码被放入Git仓库,发起Pull Request(PR)。团队进入为期2-3天的核心工作期:Code Review、逻辑测试、边界条件补充、性能与安全审计、代码风格统一等。

这个流程看似增加了前期的“人工设计”环节,但实际上它极大地约束了AI的生成范围,提高了草案的可用性,反而节省了后期修正的成本。如果没有清晰的设计,AI生成的代码会更加天马行空,Review成本会指数级上升。

3. AI生成代码的典型“坑点”与审查清单

那1小时生成的代码,具体需要Review什么?为什么需要这么久?下面是我们总结的、AI生成代码中高频出现的“坑点”,也是我们审查清单的核心组成部分。

3.1 逻辑正确性与业务一致性“幻觉”

这是最危险的一类问题。AI生成的代码可能语法完全正确,能运行,但业务逻辑是错的。

  • 案例 :在我们的报表导出中,有一个条件是“只导出状态为‘已审核’且创建时间在最近30天的数据”。AI生成的SQL可能是: WHERE status = ‘REVIEWED’ AND create_time >= DATE_SUB(NOW(), INTERVAL 30 DAY) 。看起来没问题。但Review时我们发现,业务上“已审核”的状态值在数据库里是数字 2 ,而非字符串 ‘REVIEWED’ 。这是AI根据常见命名“幻想”出来的。
  • 审查要点
    • 硬编码值 :检查所有字符串、数字常量是否与项目中的枚举、配置表一致。
    • 算法逻辑 :对于复杂的计算、公式、状态流转,必须逐行复核,最好能对照原始需求文档或设计稿。
    • 边界条件 :AI常常处理不好边界。例如,分页查询时, LIMIT OFFSET 的计算是否正确?处理空列表或null值时,是否会抛出异常?

实操心得 :对于关键业务逻辑,不要完全相信AI生成的代码。必须将其与产品需求文档或技术设计文档进行交叉验证。一个有效的方法是,让生成这段代码的AI,用自然语言解释一遍它的逻辑,看是否与你的理解一致。

3.2 工程化与健壮性缺失

AI倾向于生成“理想路径”下的代码,对异常处理、资源管理、性能等考虑不足。

  • 资源泄漏 :生成的文件流、数据库连接、HTTP客户端是否在 finally 块或 try-with-resources 中正确关闭?在异步任务中尤其容易被忽略。
  • 空洞的异常处理 :大量捕获 Exception e 然后只打印日志( e.printStackTrace() ),没有降级策略、没有给上游的明确错误响应、没有重试机制。
  • 性能隐患 :在循环内执行数据库查询(N+1问题)、使用低效的字符串拼接(如Java中用 + 在循环内拼接)、对大集合进行不必要的多次遍历。
  • 安全性疏忽 :生成的SQL是否使用参数化查询(PreparedStatement)防止注入?文件导出路径是否做了路径遍历检查?输出的数据是否包含敏感信息需要脱敏?

审查时,我们重点关注以下代码模式:

代码模式 AI可能产生的问题 审查与修正动作
数据库操作 循环内单条查询;缺少事务注解;连接未关闭。 改为批量查询;添加 @Transactional ;检查资源关闭。
文件/流操作 未使用 try-with-resources ;异常后文件未删除。 重构为 try-with-resources ;在 finally 或异常处理中清理临时文件。
HTTP调用 未设置超时时间;未处理网络异常。 配置连接、读取超时;添加重试逻辑或熔断降级。
异常处理 捕获过泛的 Exception ;生吞异常(空catch块)。 细化异常类型;记录日志并向上抛出或返回业务错误码。
数据验证 缺少对输入参数的有效性校验(null, 范围等)。 在方法入口添加断言或使用Validation框架注解。

3.3 项目上下文与风格契合度不足

AI不了解你的“家规”。它可能用 ArrayList 而你项目约定用 ImmutableList ,它可能用 log.info 而你项目有专用的日志工具类,它生成的Controller返回格式可能和项目全局封装的 Result 对象不匹配。

  • 案例 :我们项目统一使用 @Slf4j 注解和 log 变量,但AI可能生成 Logger logger = LoggerFactory.getLogger(...) 。虽然功能一样,但破坏了统一性。
  • 审查要点
    • 代码风格 :命名规范(驼峰、下划线)、导入顺序、注释格式是否符合项目要求?
    • 依赖使用 :是否使用了项目内禁用的或不推荐的类库、方法?
    • 架构模式 :生成的代码是否符合项目分层架构(如Controller-Service-DAO)?是否错误地在Controller中直接写业务逻辑?
    • 重复造轮子 :是否忽略了项目中已有的通用工具类、辅助方法,而是自己重新实现了一遍?

注意事项 :在给AI提供上下文时,多喂一些项目核心的、体现约定的代码片段(如统一的返回对象、异常处理基类、工具类),能显著改善生成代码的风格契合度。但完全依赖AI遵守“家规”是不现实的,人工Review是最后一道也是必不可少的防线。

4. 高效Review与修正的实战流程

明确了“坑点”,接下来就是如何系统性地进行Review和修正。这2-3天的工作,绝不是漫无目的地读代码,而是一个高度结构化的工程活动。

4.1 第一轮:逻辑与功能正确性审查

本轮目标是确保代码“做对了事”。我们通常结合静态代码分析和动态测试进行。

  1. 静态走查 :Review者逐行阅读生成的代码,对照技术设计文档。重点关注:
    • 核心算法与流程 :是否与设计一致?条件判断、循环边界是否正确?
    • 数据流转 :输入参数如何被处理?中间状态变化是否合理?最终输出是否符合预期?
    • 外部依赖调用 :调用的API、数据库查询语句、第三方服务接口是否正确?参数传递是否准确?
  2. 编写与执行单元测试 这是最有效的手段之一 。我们不会直接相信AI生成的代码,而是会针对核心方法,特别是条件分支,快速编写单元测试。
    • 好处 :单元测试能立刻暴露逻辑错误。同时,这些测试用例本身也成为了未来回归测试的资产。
    • 方法 :利用AI辅助生成测试用例骨架,但断言(Assert)部分必须由人工根据业务逻辑来精心设计,覆盖正常路径和各类异常边界。

一个典型的修正案例 :AI生成的金额计算方法是 amount = unitPrice * quantity 。Review时,我们意识到涉及货币计算必须使用 BigDecimal 避免精度丢失。于是修正为 amount = unitPrice.multiply(quantity).setScale(2, RoundingMode.HALF_UP) ,并补充了针对 BigDecimal 的单元测试。

4.2 第二轮:工程化与健壮性加固

本轮目标是让代码从“能跑”变得“可靠”、“可用”。

  1. 异常处理增强 :检查所有可能抛出异常的操作(IO、网络、数据库、第三方调用),确保被恰当捕获和处理。将泛泛的 catch (Exception e) 改为更具体的异常类型,并补充有意义的错误日志和用户友好的错误信息。
  2. 资源管理 :确保所有打开的资源(文件流、连接、锁)都有对应的关闭逻辑,且放在 finally 块或使用自动关闭语法。
  3. 性能优化 :检查循环内的复杂操作、潜在的多余数据库查询、大对象创建等。例如,将AI生成的多次单条插入改为批量插入。
  4. 安全加固 :验证所有用户输入是否经过清洗或转义,防止注入攻击。检查文件操作是否有路径遍历风险。确认敏感信息(如密码、密钥)没有硬编码在代码中。
  5. 日志与可观测性 :补充关键业务节点、错误场景的日志,确保日志级别合理(ERROR/WARN/INFO)、信息完整(包含请求ID、关键参数等),便于线上问题排查。

4.3 第三轮:代码风格与项目集成

本轮目标是让代码“像自己人写的”,能无缝融入现有项目。

  1. 代码风格统一 :使用项目的代码格式化工具(如Spotless、Prettier)统一格式化。检查并修正命名,使其符合项目规范。调整不规范的导入语句。
  2. 依赖与配置检查 :确认引入的依赖版本与项目 pom.xml build.gradle 中的版本管理一致。检查是否有不必要的或冲突的依赖被引入。确认代码中使用的配置项(如 @Value 注入的值)在配置文件中已定义。
  3. 集成测试 :将修正后的代码集成到本地开发环境,启动应用,执行相关的API调用或功能操作,进行端到端的集成测试,确保与其他模块协作正常。
  4. 文档更新 :如果AI生成或修改了公开的API(如Swagger接口),需要同步更新API文档。关键复杂的业务逻辑,补充必要的代码注释,解释“为什么这么做”,而不仅仅是“做了什么”。

这个过程是迭代的,并非严格线性。可能在进行第二轮“性能优化”时,又发现了第一轮遗漏的逻辑问题。但有了这个框架,整个Review和修正工作就能有条不紊地推进,而不是一团乱麻。

5. 工具链与最佳实践:让“人-AI”协作更顺畅

为了降低后期Review的成本,提升前期生成代码的质量,我们也在工具链和协作模式上做了一些优化。

5.1 给AI更优质的“输入”

  • 编写清晰的“提示词(Prompt)” :不要只说“生成一个导出服务”。要像给新人布置任务一样详细。
    • 差提示 :“用Spring Boot实现数据导出。”
    • 好提示 :“请基于以下技术栈和上下文,实现一个报表数据导出服务。需求:1. 接口路径 /api/report/export ,接受JSON参数 {‘filter’: {‘status’: int, ‘startDate’: string, ‘endDate’: string}, ‘exportType’: ‘EXCEL’} 。2. 查询 order 表,联查 user 表,条件为status=? and create_time between ? and ?。3. 使用Apache POI将查询结果生成Excel文件,文件需包含表头。4. 文件生成后上传至OSS,返回文件下载URL。5. 整个流程需异步处理,使用 @Async 。6. 异常需记录日志并返回标准错误格式 {‘code’: 500, ‘msg’: ‘导出失败’} 。以下是项目现有的统一响应类 Result 和日志工具类 LogUtil 的代码参考:[粘贴相关代码]。”
  • 提供丰富的上下文 :在对话或IDE插件中,将当前项目的关键文件(如定义数据模型的Entity类、统一封装的工具类、配置文件片段)作为参考内容提供给AI,它能更好地模仿你的项目风格。

5.2 利用自动化工具辅助Review

人工Review是核心,但工具能极大提升效率。

  • 静态代码分析(SAST) :在CI/CD流水线中集成SonarQube、Checkstyle、PMD等工具。AI生成的代码提交后,自动运行这些检查,可以快速发现代码异味、潜在bug、安全漏洞和风格问题,让Review者能聚焦于工具无法发现的逻辑和业务问题。
  • 单元测试覆盖率 :要求新代码(包括AI生成的)必须具备一定的单元测试覆盖率(如80%),并通过CI强制执行。这倒逼开发者在Review时必须补充测试,从而验证逻辑。
  • 依赖扫描 :使用OWASP Dependency-Check等工具,检查AI生成的代码是否引入了含有已知漏洞的第三方库版本。

5.3 建立团队协同规范

  • 明确AI使用准则 :在团队内约定,哪些场景鼓励使用AI(如生成样板代码、工具方法、单元测试骨架、文档注释),哪些场景慎用或禁用(如核心业务算法、安全相关代码、架构设计决策)。
  • Review重点清单 :将本文第三部分总结的“坑点”形成团队的Checklist,在Review AI生成代码时强制逐项核对。
  • 知识沉淀 :建立团队内部的Wiki或知识库,记录常见的AI生成代码问题案例及修正方案,以及经过验证的高效Prompt模板,帮助团队成员快速复用经验。

6. 总结与展望:AI协同开发的未来

这次“1小时生成,2-3天修正”的实践,让我们对AI编程有了更务实、更落地的认识。它绝不是替代,而是一次深刻的效率革命。那1小时节省的是从零到一的“打字”和“基础构思”时间,而那2-3天则是将粗糙的“原材料”加工成“合格产品”必不可少的、体现工程师核心价值的环节——设计、审查、优化与集成。

未来,随着AI能力的进化,特别是对长上下文、复杂工程上下文理解能力的提升,以及更多针对代码生成场景的优化(如更好的代码补全、更精准的漏洞提示),我们期待“修正”阶段的时间能被进一步压缩。但可以预见的是,人类工程师在 需求分析、系统设计、架构权衡、复杂问题拆解和最终质量把关 方面的作用,在很长一段时间内只会加强,不会减弱。

AI协同开发,正从一种炫技的新鲜玩意,走向成熟的工程实践。它的价值不在于制造惊喜,而在于提供稳定、可预期的效率提升。拥抱它,理解它的边界,用工程化的方法去管理它,我们才能在这场变革中真正受益。

更多推荐