尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

AI编程Java实战:Spec+Agent Harness+架构评审三件套

AI编程Java实战:Spec+Agent Harness+架构评审三件套 直接开门见山说个现象最近各大群里聊AI编程满屏都是“Cursor写了个接口贼快”“AI把我老代码重构了一跑直接OOM”。但问十个用AI写Java的人九个都遇到过同一个问题——小需求AI秒出活业务一复杂AI就给你编出根本不存在的类、凭空造方法、接口设计得让人血压飙升。原因很简单你把AI当成了“一个懂Java的高级外包”但它没人告诉你需求全貌也没规则约束更没人给它做架构评审。这不是AI不行是你的工程方法不对。这套东西我按标题里说的三件套拆完亲测跑了几周Spec规约解决“AI不知道干什么”Agent Harness规则解决“AI怎么干活不被带偏”架构评审标准解决“AI干完活怎么验收”。三件套叠起来AI写Java代码的可用性至少从“玩具水平”提到“能进代码评审”的程度而且不依赖具体哪款AI工具——你在IDE插件、命令行Agent、甚至本地模型上这套规则都通用。这篇文章我直接把这套完整方案端出来包括每条提示词怎么设计、为什么这么写、实际跑下来踩了什么坑还有我改过N版的Harness规则脚本和架构评审清单。适合正在把AI编程往真实项目里塞的Java开发者不管你是自己用还是想沉淀成团队规范都能直接抄。1. 核心思路拆解为什么是“Spec Harness 评审”三件套1.1 单靠一条提示词为什么必然翻车先说结论“帮我写一个用户订单模块”这种提示词AI能给出看起来完美、但工程上全是坑的代码。这不是概率问题是必然结果。原因有三层。第一层AI是生成模型它根据训练数据里的“平均规律”生成代码。你只说“订单模块”它会把见过的订单模块特征全部平均一遍字段叫orderId、status、createTime接口有createOrder、cancelOrder、queryOrder可能还给你加个没用上的设计模式。这些代码缝合得越“标准”离你的真实业务越远。第二层Java工程和其他语言不一样它的复杂度大头在类型系统、Spring容器、依赖管理、事务边界、异常体系上。AI单独看每个方法写得都对但方法之间的协作、事务切面会不会拦截某个内部调用、懒加载会不会在序列化时炸掉、泛型擦除会不会让某个重载失效——这些“跨方法、跨类、跨层”的东西单条提示词根本管不到AI也看不到全貌。第三层也是最隐蔽的AI没有“拒绝权”。你让它写代码它会假设你说的就是全部需求。你没提事务它就默认不需要你没提并发它就默认单线程你没提幂等它就默认调用方永远不会重试。而真实项目里这些“你没提的东西”恰恰是上线才炸的雷。所以你需要把“需求、约束、验收”三件事前置给AI。Spec规约干的就是这件事。1.2 Spec规约把“脑子里想的”翻译成“AI能执行的”我最初犯的错是写长篇大论的“需求文档”塞给AI什么背景、目标、用户故事都写上结果提示词又臭又长AI照样瞎写。后来总结出来Spec规约的精髓是去叙述化、去歧义化只需要事无巨细地写清楚下面几层东西输入/输出契约方法签名、参数类型、返回值、异常抛出。Java特有的DTO/VO/PO怎么区分用什么注解序列化规则是什么。状态与流转实体的状态字段有哪几个值什么条件下允许什么迁移。这个你不写死AI就会自己发明状态机而且大概率是错的。约束与边角哪些字段必填哪些字段必须唯一并发控制策略是什么事务边界在哪里操作是物理删除还是逻辑删除。成功/失败语义接口返回什么算成功什么情况抛什么异常错误码怎么编排。这决定AI会不会在业务失败时也返回200然后塞个errorCode还是直接500。说白了Spec规约就是把“验收标准”和“契约”先钉死。AI拿到这份规约它的自由度被约束在“怎么实现”上而不是“设计成什么样”上。工程里最贵的部分不是编码是设计决策Spec就是把关键的决策先替你定掉。1.3 Agent Harness控制AI在代码库里的“行为边界”有了SpecAI知道“做什么”了。但还有一个致命问题AI在真实工程里是“乱逛”的——它会顺手改掉你的pom.xml因为“觉得某个版本太老”会在写一个工具类的同时“顺手优化”你另一个私有方法会在不确定某个API用法的时候自己编一个出来然后假装它能编译通过。这就是Agent Harness要管的。Harness的本意是“套具、操控装置”在AI编程语境下它是一套约束Agent行为的规则集和工作流框架不直接生成业务代码而是生成“Agent接下来可以碰什么文件、不可以碰什么文件、每一步之前必须先做什么、完成到什么程度才可以交付”这些行为边界。标题里的“Agent Harness规则”核心就是两件事文件访问边界和步骤执行纪律。文件访问边界解决的是“AI别乱改代码库”。你要明确告诉它这个任务是新增代码只允许新增在哪个包下既有文件只读不改这个任务是重构只能改动哪些类测试类不允许动所有涉及数据库变更的必须先给你看SQL脚本等确认再执行。步骤执行纪律解决的是“AI别跳跃式干活”。我见过最让人崩溃的场景让AI写一个接口它5秒后返回结果打开一看Service、Controller、Mapper、XML、DTO全给你写完了但运行起来Mapper的XML里namespace配错了Controller没加RestControllerService里事务注解漏了——从头错到尾还错得特别均匀。后来我把步骤拆死先给实现方案再写接口定义再写实现类每一步都要进行编译验证通过了才能进入下一步。有了这个“纪律”AI的“自信”会被大大压制开始老老实实干活。1.4 架构评审标准不让AI既当运动员又当裁判AI写完代码绝大部分人不会认真审查看能编译、测试大概通过就收了。但AI生成代码的“表面正确”是极具迷惑性的。最典型的问题逻辑正确结构崩坏。AI为了让“当前这个方法”看起来正确会在一个类里堆上千行为了让逻辑“好理解”会复制粘贴大量重复代码为了方便“测试”会把依赖全怼到构造函数里Setter一堆暴露结果就是维护噩梦。架构评审标准就是给“验收”立规矩的。它和常规Code Review不一样评审对象不是“自然语言描述的需求”而是对比Spec规约逐条核对——不关心AI写得漂不漂亮只关心它有没有遵守契约、有没有突破边界、有没有引入架构上不允许的依赖关系。我在这套方案里设计的评审分四层契约层所有公开方法的签名、行为是否与Spec完全一致。工程层是否引入不符合项目结构的依赖包依赖方向是否逆向如Controller依赖了Repository是否存在循环依赖。质量层重复代码率、异常吞掉率、资源释放、并发安全性。领域层业务规则是否被绕开比如“订单超时未支付自动关闭”这种定时任务逻辑是不是被AI塞进查询接口里了。评审标准前置很重要——它在Spec阶段就定义好AI写代码前就知道“什么叫验收通过”。这比写完代码再拿标准去卡效率高得多因为大部分不合规点AI在写的过程中就直接避开了。2. 全套提示词与配置实录直接可复制的方案2.1 Spec规约提示词模板这块我打磨了很久目前用的版本长这样。不建议只发一次建议以系统提示词或项目级文档形式挂载让AI在做任何任务前都先读一遍。【角色设定】 你是一个Java技术专家擅长根据Spec规约编写高质量的生产级代码。 在写任何代码之前你都必须先阅读理解Spec规约并逐条确认无歧义。 【Spec规约定义】 以下是本次任务中必须遵守的规格说明。如果规约中有任何不清楚的地方 你必须先向我提问确认禁止自行假设后编码。 1. 业务目标{在这里写清楚这个模块/接口要解决什么问题最多五句话} 2. 输入契约 - 方法签名{例OrderResult createOrder(CreateOrderRequest request)} - 参数说明{例request.userId不能为空request.items不能为空且items.size1} - 预期异常{例参数非法抛IllegalArgumentException库存不足抛StockNotEnoughException} 3. 输出契约 - 正常返回: {例OrderResult包含orderId, orderStatus, totalAmount} - 错误返回: {例系统异常统一包装为ErrorResult错误码以A-开头} 4. 状态流转规则{说明实体状态有哪些什么操作把状态从什么变成什么哪些是非法流转} 5. 数据约束 - 唯一性约束{如订单号全局唯一} - 边界条件{如金额必须大于0小于等于999999.99} - 并发要求{如库存扣减必须使用悲观锁或乐观锁} 6. 事务与副作用规则 - 哪些操作必须在一个事务里 - 哪些操作不能在事务里调用远程服务 - 是否允许写日志日志级别要求 7. 建议实现方案{这一步可选。如果我有明确的实现倾向就写清楚如果没有留空让AI给方案}你可能会问为什么要搞这么固定格式直接对话说不也一样吗区别在于自然语言对话AI理解到的约束散落在上下文里后面写代码时很容易“遗忘前面说过的一句话”。而固定模板相当于“契约绑定”你在Spec里声明过的东西AI会当作约束处理而不是当背景知识处理。2.2 Agent Harness规则脚本实例Harness规则是我迭代最痛苦的环节。AI编程工具大多有自己的Agent模式比如Cursor的Agent、Codex的Agent模式但默认规则偏通用不管你的工程结构。我自己写的这套Java专用Harness规则核心是三大纪律。纪律一文件访问边界【文件访问边界规则】 1. 只读文件目录src/main/resources/、src/test/resources/、docs/、.github/ ——这些目录下任何文件未经确认禁止修改。 2. 可读可新建目录 - src/main/java/{当前业务包根} - src/test/java/{当前业务包根} ——只允许在本次任务指定的包根下新增或修改文件。 3. 禁止触碰目录 - pom.xml、build.gradle除非任务明确声明需要改依赖 - src/main/java/config/、src/main/java/common/ 下的公共配置和基类 - 任何Name以Test结尾的文件除非任务明确要求写测试 4. 任何需要修改上述禁区的操作必须先打印“潜在违规操作”并等待确认 未经确认直接修改视为违规。这条规则的背景特别真实我踩过AI改我pom.xml把Spring Boot版本从3.x悄悄降到2.7因为“AI训练数据里2.7的例子更多”也踩过AI把我一个公共的HttpClient工具类“优化”了一下优化完另一个没在本次改动范围内的服务直接编译失败。纪律二步骤执行顺序【步骤执行纪律】 每次任务按下列固定步骤执行每一步都必须在完成后输出结果才能进行下一步 1. 理解与确认Step 1 - 阅读Spec用自己的话复述业务目标与关键约束 - 列出你需要修改/新增的文件清单 - 明确是否有歧义点并提问 2. 方案设计Step 2 - 输出类结构设计包含类名、职责、关键方法签名 - 输出涉及到的数据库表变更SQL如果有 - 等待确认后才能进入下一步 3. 编码实现Step 3 - 按包顺序实现优先写接口定义再写实现类 - 每写完一个文件都检查该文件是否可以被正确编译 - 所有编译错误立即修复修复后列出修复记录 4. 自测Step 4 - 写出简单的自测代码main方法或JUnit均可 - 执行测试给出测试结果 - 若无法执行缺环境、缺依赖必须说明原因 5. 最终交付Step 5 - 汇总本次新增/修改的文件清单 - 输出变更说明包含影响范围与潜在风险为什么要这么“机械”因为AI在自由巡航时最常见的翻车是跳跃执行需求理解还没有确认就开始改代码方案设计是错的但代码已经写了一堆推倒重来成本极高。固定五步后AI每一步都“说人话、给人看”就算它中间有错你也早发现早纠偏而不是等它写完全部才看到灾难现场。纪律三输出风格与代码规范【代码风格规范】 1. JDK版本以项目实际配置为准默认JDK 17。 2. 禁止Lombok不要在实体上使用Data/Builder。 3. 命名规范类名名词方法名动词布尔方法以is/has/can开头。 4. 异常处理禁止catch后静默吞掉禁止catch后只打日志不抛不得catch Throwable/Error。 5. 空值安全所有外部参数与方法参数必须做null判断返回不允许null集合。 6. 格式化采用项目已有格式缩进为4空格。 7. 约束优先优先使用javax.validation注解做参数校验不手写if判断。 8. 依赖方向Controller不能直接依赖Repository/Mapper遵循分层架构。这里特别说下“禁止Lombok”这条很多人可能觉得我在抬杠。实际上我在团队里推AI编程时最先遇到的就是Lombok问题AI生成的Getter/Setter用的贼欢但它不知道项目里的Lombok插件在编译环境里没配好或者实体类需要自定义getter逻辑的它也只会一味加注解。这种“团队技术栈上没有的东西AI乱用”的情况非常普遍。所以我把这类“千行代码能用但不符合团队规范”的点全部列成硬约束让AI没法钻空子。2.3 架构评审标准的完整清单AI交付代码后评审人群的区分点在于新人评审只看“能不能跑”架构师评审看“改了会不会炸”。我的评审标准专门设计成五张清单。清单一契约一致性核对表这个表格是评审时最优先去看的直接拿Spec逐条对。核对项通过标准踩过最多次的坑方法签名与Spec定义完全一致AI“好心”把返回类型从OrderResult改成了OrderResultVO参数校验所有必填参数有校验逻辑AI认为只要Controller层校验就够Service层裸奔异常语义业务异常不包装成500AI把业务异常卷进Exception里抛了前端拿到500一脸懵返回结构正常/错误返回符合输出契约AI在成功路径里嵌了“错误码字段”感觉“反正前端也不看”状态机状态流转只走合法路径AI为了让代码“少几行”绕过状态检查直接改status字段清单二依赖与结构审查项检查点评判标准违规案例包依赖方向Controller → Service → Repository方向单向AI在Repository层里写了Controller逻辑循环依赖禁止任何类间循环依赖Service相互注入Spring启动都起不来无效依赖禁止引入未使用的依赖AI在pom.xml里加了某个工具包代码里根本没用重复代码同名或相似逻辑出现2次以上必须抽公共相同的“用户状态校验”逻辑在三个类重复隐式依赖禁止依赖静态方法、ThreadLocal等隐式数据流AI用ThreadLocal传了用户信息跨线程丢数据清单三质量与隐患扫描项检查点重点典型问题并发安全线程安全性、原子性HashMap并发写导致CPU100%改ConcurrentHashMap资源释放流、连接、锁是否关闭JDBC查询完不关连接连接池被掏空空指针所有可能为null的链式调用getA().getB().getC()AI压根没想过B可能是null性能隐患for循环里查库、N1问题用循环查详情接口一次查询100条就100次SQL事务边界事务是否被不必要地放大纯查询方法加了Transactional含只读日志审计关键操作是否留痕删了订单但没日志出问题没法排查清单四领域逻辑与业务规则审查项检查点说明业务规则完整性如“ coupon不能与满减叠加”是否实现了幂等性重复提交是否会重复创建时间处理时区处理是否正确是否用了LocalDateTime而非Date金额精度是否用BigDecimal有没有精度丢失清单五可测性与可维护性检查点通过标准测试覆盖核心业务逻辑有单元测试命名自解释方法名能看懂做了什么无需注释来“翻译”方法长度单个方法控制在50行以内类职责单类职责清晰避免上帝类3. 实操过程从零到一跑通一次完整AI编程交付3.1 准备环境选定工具与挂载配置先说我现在的常用组合Cursor的Agent模式命令行Codex辅助CLAUDE.md方式挂Harness规则或者如果是在纯命令行环境就把Harness规则写到项目根目录的AGENTS.md里让工具自动读取。目前主流AI编程工具都支持项目级规则文件所以这套方案对工具其实不挑。具体做三件事项目根目录创建一个SPEC.md把Spec规约模板按当前任务填好。项目根目录创建一个AGENTS.md或你所用工具对应规则文件把本文第二节的“文件访问边界”和“步骤执行纪律”贴进去。项目根目录创建一个ARCH_REVIEW.md把五张评审清单贴进去作为任务完成后的验收标准。这个做法的好处是这些文件本身纳入版本管理团队其他人clone下来也能直接复用同一个规矩。而且当Agent在上下文中看到这几个文件时它的“行为模式”会立刻切换——从一个“写代码的模型”变成一个“遵守项目纪律的工程师”。3.2 示例流程让AI实现一个“优惠券核销”接口用一个贴近业务的例子走一遍让大家看看三件套是这么互相配合的。第一步填Spec规约我在SPEC.md里写清楚以下内容要点业务目标核销一张优惠券扣减一次使用次数记一条核销流水。输入契约CouponUseResult useCoupon(CouponUseRequest request)参数包含couponId、orderId、userId三者均不能为空。输出契约正常返回核销信息优惠券不存在/已过期/已被使用/不属于该用户分别抛不同业务异常。状态流转规则优惠券状态有UNUSED、USED、EXPIRED、DISABLED只有UNUSED允许流转到USED其余流转非法。数据约束核销必须幂等——同一orderId对同一coupon只能核销一次金额精度用BigDecimal所有数据库操作在同一事务内。事务规则禁止核销事务内调用远程接口禁止catch后吞异常。第二步Agent按纪律执行按Harness规则Agent执行Step 1时先用自己的话复述需求然后提问“订单状态是已支付才能核销吗还是创建就能核销”——这个问题很关键因为Spec里确实漏了AI能识别出来并问而不是自己拍脑袋默认“必须支付成功”说明Spec搭配“有疑必问”的步骤纪律确实能提升AI追问意识和确认习惯。Step 2方案设计它输出后我扫了一眼发现它想把优惠券表、核销流水表都设计成一个字段超多的“大宽表”我直接在方案阶段拦下来了让它拆成用户侧查询和运营侧查询分开的字段结构。这个调整放在以前“直接生成代码”的模式下AI已经写好几百行再让你推翻了。Step 3编码实现时由于Harness里规定“每写完一个文件必须检查编译”我观察到AI在多文件场景下编译错误的自我修复率明显高了。以前一气呵成写10个文件最后由30个编译错误集中爆发拆步骤后基本每次只爆发一到两个错误而且是前一个文件修完了才写下一个文件错误不会滚动累积。第三步跑架构评审编码完成、自测通过后我拿着ARCH_REVIEW.md的五张清单逐条核对。实际发现的问题相当典型写出来给大家参考契约一致性发现AI把正常返回的CouponUseResult里多塞了一个couponName字段。这本身没什么但成功后AI有个隐蔽做法——它自作主张把错误响应里的错误码统一加了个“前缀”这和前端对错误码的解析规则不一致。如果没有契约核对表这个坑会直接流到联调阶段还是那种特别难定位的“对不上字段”的坑。依赖与结构发现AI在Service里直接注入了CouponMapper并直接做查询绕过了我设计的Repository层。这个如果不抓后续所有类似代码都会效仿分层结构直接烂掉。并发安全检查扣减次数的代码发现AI用的是“先select再update”的检查型写法没有加锁也没用乐观锁版本号。这在低并发下不会出错但压测一上就必炸。我要求改用UPDATE ... WHERE used_count ?的CAS写法并返回影响行数AI修改得很快因为Spec里的“并发要求”字面上满足实际上需要评审来发现实现不符合高并发场景。这个示例大致就是完整过程。你会发现最容易出质量问题的三个环节分别是方案设计时的数据模型粗心、编码时的越层依赖和高并发场景的安全意识。这三个都不是“编译错误”而是“架构错误”。架构评审清单存在的意义就是专门抓架构错误。3.3 与人协作的“提示词管理”技巧这套方案用顺之后我强烈建议你把“提示词本身”当成代码一样管理——版本化、评审、回滚。我在团队里推了一套简单流程每一条新的提示词模板先在小项目里试三次记录翻车点再迭代入模板库模板库用Git管理每次改动必须写commit message说明“为什么改”模板库里每条规则都必须注释“解决过什么问题”防止后人看不懂就删掉。比如我在Harness规则里那条“每写完一个文件必须检查编译”注释里就写着“解决AI一次性生成多文件时同名导入冲突和编译错误滚雪球问题”。有理由的规则维护者才愿意留。没理由的规则早晚被当垃圾删掉。4. 常见问题与排查技巧实录填平AI编程的那些坑4.1 问题速查表参考了社区里大量讨论以及我自己跑下来的高频问题整理成表。症状根源解法AI“幻觉”出不存在的API上下文没绑依赖版本或训练数据里API过时Spec里强制写清Spring/Boot版本Harness里规定“不确定的API先查文档再编码”AI改了没让动的文件文件访问边界规则无效或缺失检查AGENTS.md是否被Agent正确读取必要时在任务提示词里再强调一遍“只读文件列表”方案设计看着对实现出来都是错流程跳到Step 3方案没经过确认把Step 2设为“必须等待确认”模式不要让Agent连续执行多步单测全绿上线秒崩测试是AI写的AI用错误逻辑验证错误逻辑评审时抽查测试断言重点看“负面用例”是否存在等于可比不等于不可比代码越写越乱重复率飙升没有复用意识每次都是“新写一个”在架构评审质量层配上重复代码率阈值超过阈值打回重构大模型上下文一长规则就“失忆”上下文窗口挤压了早期规则把核心规则前置到系统提示词完成任务前要求Agent复述一次规则4.2 高频翻车点实录翻车一AI自己造了一个“不存在但看起来合理”的Spring注解。有一次让它实现一个定时任务它直接在方法上加了个Scheduled(cron ...)但项目里根本没有启用EnableScheduling。它没查配置也没问核心业务倒是实现了但定时任务从头到尾没跑过。后来Harness规则里加了“状态确认”这一步“写任何需要配置类支撑的注解前先确认项目里是否已有相关开关配置”。翻车二AI把“业务正确”与“代码正确”混为一谈。有次让它实现“优惠券已使用则不能再次核销”它写的代码在单线程下看起来没问题但并发请求同时进来两次请求都通过了“检查状态”这行代码然后双双更新了数据库。这完全可以用乐观锁解决但AI就是不会主动“预防未来”因为它没见过你的压测报告。架构评审里的并发安全这关就是为这个专门设置的。翻车三AI特别喜欢“过度设计”。模块只有一个接口三个实现类硬套一个策略模式还加了一个AbstractFactory。你问它为什么它的回答是“为了可扩展性将来可能有更多实现”。这句话听着耳熟吧跟刚入行的同事写代码一个毛病。架构评审里有一条“如果当前只有一个实现类禁止引入接口S实现工厂三件套等第二个实现出现再说”。这条能帮团队省下来大量无谓的抽象和阅读成本。4.3 我的改进心得这套方案迭代到当前版本最大的几个变化最早版Harness规则我写得像“宪法”几十条规则密密麻麻结果AI频繁违反因为上下文太长它记不住。现在改成三个纪律每条纪律下最多三到五条子规则简洁到AI能在每次任务开头把它完整读一遍。规则数量过载比没有规则更糟糕。Spec规约从“写一段话”变成了“填表格”。AI对结构化信息的遵从度远超对叙述性文字的遵从度。这可能和训练数据里“接口文档都是结构化格式”有关。架构评审从“凭感觉看”变成了“核对表勾选”。这个最重要因为AI输出的东西你盯着看会“顺眼”但用核对表去查的时候很多问题就自己浮出来了。最后说一个最拗但最有效的习惯每次让AI交付完成后追问一句“你这次自己对照Spec检查过哪些内容还有哪些没检查”别看它答案可能是“检查了契约一致性没检查并发安全”这句话的价值是让AI把自我评估的黑盒过程变成白盒过程你可以直接基于它的回答去做二次检查。这个做法是我这段时间用下来性价比最高的一个举动。如果你现在项目里也在用AI写Java真心建议你别再“裸奔”式提问了。把Spec、Harness和评审清单拉到项目里跑一个完整任务对比试试体感差异会非常明显。后续如果你们团队有什么好使的新规则也欢迎交流这套东西本来就是越迭代越有生命力。
返回列表