写在前面2026 年AI 编码助手已经从尝鲜变成了日常——无论是 Cursor、GitHub Copilot 还是 JetBrains 系的 AI 插件几乎每个开发者每天都在和 AI 结对编程。但大多数人的体感是AI 写代码能用但离好用还有距离。它能帮你补全一段函数、写一个 CRUD但产出的代码经常需要大量人工修改——命名不规范、异常处理粗糙、分层混乱、缺少日志、事务管理遗漏。问题出在哪不是 AI 不行而是你没有告诉它什么是好代码。这篇文章从实战角度出发系统讲解如何通过提示词优化、规则体系建设、上下文管理三板斧让 AI 产出的代码质量从能跑提升到可上线。所有方法来自我们团队半年多的实践经过日均数百次 AI 编码验证。一、核心认知AI 代码质量 f(提示词, 规则, 上下文)先建立一个认知模型AI 产出代码质量 f(提示词质量, 规则约束, 上下文充分度) 其中 - 提示词质量你说清楚了没有——需求描述是否精确、无歧义 - 规则约束你立规矩了没有——AI 是否知道你的编码规范 - 上下文充分度你给够背景了没有——AI 是否理解项目的技术栈和设计三者的影响权重大致是规则约束 (40%) 上下文充分度 (35%) 提示词质量 (25%)为什么规则约束排第一因为一个好的规则体系可以系统性地消灭低级问题——命名、分层、异常处理、日志格式这些问题不应该每次在提示词里重复说而是写成规则让 AI 持续遵守。二、提示词优化从写个函数到精确表达意图2.1 差提示词 vs 好提示词先看反面教材❌ 差提示词 写一个用户注册接口 AI 产出能跑但没有参数校验、没有重复检测、没有事务、没有日志、 返回值格式不统一、异常直接抛出不包装...好的提示词应该包含五要素✓ 好提示词的五要素 1. 做什么What实现用户注册功能 2. 输入输出IO入参 RegisterRequest返回 ResultUserVO 3. 约束条件Constraints手机号唯一性校验、密码加密存储 4. 异常场景Edge Cases手机号已注册、验证码过期、并发注册 5. 技术上下文ContextSpring Boot MyBatis-Plus分层Controller → Service → Mapper示例实现用户注册 Service 方法。 入参RegisterRequestphone, password, verifyCode 返回ResultUserVO 业务逻辑 1. 校验验证码是否有效调用 VerifyCodeService.validate 2. 检查手机号是否已注册查 user 表 3. 密码 BCrypt 加密 4. 插入用户记录 5. 发送注册成功事件Spring Event 约束 - 步骤 2-4 需要在同一事务内 - 手机号已注册抛出 BizException(USER_PHONE_DUPLICATE) - 验证码校验失败抛出 BizException(VERIFY_CODE_INVALID) - 方法入口和异常处记录 INFO/ERROR 日志2.2 提示词四层模型把提示词按抽象层级分成四层越底层越稳定、越顶层越具体┌─────────────────────────────────────────────┐ │ Layer 4: 任务指令每次不同 │ │ 实现 UserService.register 方法 │ ├─────────────────────────────────────────────┤ │ Layer 3: 业务上下文按需提供 │ │ 用户注册需要验证码、手机号唯一... │ ├─────────────────────────────────────────────┤ │ Layer 2: 技术上下文项目级别 │ │ Spring Boot 3 MyBatis-Plus RocketMQ │ ├─────────────────────────────────────────────┤ │ Layer 1: 编码规则全局级别写一次永久生效 │ │ 命名规范、异常处理、日志格式... │ └─────────────────────────────────────────────┘Layer 1-2 不应该每次手写——应该配置成 AI 编辑器的全局规则/项目规则Layer 3-4 是每次需要人工输入的——但越精确AI 产出越好2.3 提示词模板化高频场景可以建立提示词模板降低每次的思考成本## 新增接口模板 实现 [Controller/Service/Mapper] 的 [方法名] 方法。 ### 接口签名 - 入参[参数类型及含义] - 返回[返回类型] - HTTP 方法/路径[POST /api/v1/xxx] ### 业务逻辑按步骤 1. [步骤1] 2. [步骤2] 3. ... ### 边界情况 - [异常场景1] → 抛出 BizException([错误码]) - [异常场景2] → 返回 [特定响应] ### 依赖 - 调用 [XxxService.yyy 方法] - 查询 [表名.字段]## Bug 修复模板 修复 [类名.方法名] 的 [Bug 现象描述]。 ### 当前行为 [描述现在的错误表现] ### 期望行为 [描述修复后应该怎样] ### 根因分析 [如果已知根因写上如果不知道让 AI 先分析] ### 约束 - 不要改变方法签名 - 不要影响 [其他功能] - 修复后补充对应的单元测试2.4 提示词的反模式反模式问题改进“帮我优化一下这个类”太模糊AI 不知道优化什么“把这个类的 N1 查询改为批量查询”一次让 AI 写 500 行上下文越长 AI 越容易偏拆分成 3-5 个小任务分步完成不给示例AI 不知道你的代码风格给一个标杆文件让它参考描述实现而非目标“用 for 循环遍历…”“过滤出满足条件的元素”让 AI 选择最佳实现忽略异常场景AI 默认走 happy path显式列出需要处理的异常三、规则引导建立 AI 必须遵守的编码规范3.1 为什么规则比提示词更重要提示词是临时的——每次对话都要写。规则是持久的——写一次AI 持续遵守。把重复出现的质量要求沉淀成规则而不是每次在提示词里重复。现代 AI 编辑器都支持规则文件的机制Cursor.cursorrules文件Qoder / JetBrains AI项目级 Rules 配置GitHub Copilot.github/copilot-instructions.mdWindsurf.windsurfrules文件3.2 规则体系的三层设计┌────────────────────────────────────────────────┐ │ 全局规则所有项目通用 │ │ - 编程语言级规范 │ │ - 通用设计原则 │ │ - AI 交互偏好 │ ├────────────────────────────────────────────────┤ │ 项目规则当前项目特有 │ │ - 技术栈声明 │ │ - 分层架构规范 │ │ - 业务术语词典 │ ├────────────────────────────────────────────────┤ │ 模块规则特定模块/领域 │ │ - 该模块的设计决策 │ │ - 性能约束 │ │ - 安全要求 │ └────────────────────────────────────────────────┘3.3 五类硬性规则必须配置根据我们团队的实践以下五类规则能消灭80% 的 AI 代码质量问题规则一命名规范## 命名规范 ### 类命名 - Controller 类{业务}Controller如 FlowController - Service 接口{业务}Service如 FlowService - Service 实现{业务}ServiceImpl如 FlowServiceImpl - Mapper 接口{业务}Mapper如 FlowMapper - 实体类{业务}Entity 或 {业务}DO如 FlowEntity - VO/DTO{业务}VO / {业务}DTO / {业务}Request / {业务}Response ### 方法命名 - 查询单条get{Entity}ById / find{Entity}By{Condition} - 查询列表list{Entity}s / page{Entity}s - 新增create{Entity} / add{Entity} - 修改update{Entity} - 删除delete{Entity} / remove{Entity} - 判断is{Condition} / has{Property} / can{Action} - 转换convert{Source}To{Target} / build{Target} ### 变量命名 - 布尔变量is/has/can 开头如 isEnabled, hasPermission - 集合变量复数名词如 users, orderItems - Map 变量{key}To{Value}Map如 userIdToNameMap - 常量全大写下划线分隔如 MAX_RETRY_COUNT ### 禁止 - ❌ 单字母变量循环变量 i/j/k 除外 - ❌ 拼音命名 - ❌ 无意义缩写如 usr, mgr, proc - ❌ 匈牙利命名法如 strName, intCount规则二分层架构## 分层规范 ### 调用关系严格单向 Controller → Service → Mapper/Repository → 外部 Client → MQ Producer ### 各层职责 - Controller参数校验Valid、调用 Service、包装 Result - Service业务逻辑、事务管理、事件发布 - Mapper/Repository数据访问不含业务逻辑 - Client外部系统调用封装 ### 禁止 - ❌ Controller 直接调用 Mapper - ❌ Service 之间循环依赖 - ❌ Mapper 中写业务判断逻辑 - ❌ 在 Controller 中写超过 10 行的业务逻辑 - ❌ Entity/DO 对象暴露到 Controller 层必须转 VO规则三异常处理## 异常处理规范 ### 业务异常 - 统一使用 BizException(ErrorCode code, String message) - ErrorCode 为枚举格式{模块}_{异常描述} - 示例FLOW_INSTANCE_NOT_FOUND, USER_PHONE_DUPLICATE ### 异常分类 - 参数校验异常Controller 层 Valid 抛出全局拦截器统一处理 - 业务异常Service 层主动抛出 BizException返回 400 - 系统异常未预期的 RuntimeException返回 500记录 ERROR 日志 ### 规则 - ✓ 异常消息必须包含关键业务标识如 flowId, userId - ✓ 捕获异常必须记日志或重新抛出禁止空 catch - ✓ 外部调用HTTP/RPC必须 catch 并包装为业务异常 - ❌ 禁止用异常控制业务流程如用 try-catch 代替 if-else - ❌ 禁止 catch(Exception e) 后吞掉不处理 - ❌ 禁止在循环内 try-catch应该在循环外规则四日志规范## 日志规范 ### 必须记录日志的场景 - 方法入口INFO核心 Service 方法入口记录入参关键字段 - 外部调用前后INFOHTTP/RPC/MQ 调用的请求和响应 - 异常ERROR包含异常堆栈和业务上下文 - 状态变更INFO关键业务状态机变更 ### 日志格式 - 使用 Slf4j 占位符log.info(处理流程实例, flowId{}, status{}, flowId, status) - 禁止字符串拼接❌ log.info(处理 flowId 状态 status) ### 级别使用 - ERROR系统异常、外部调用失败、数据不一致 - WARN业务异常可预期的错误、性能退化 - INFO核心业务流程、状态变更、外部调用 - DEBUG调试信息、详细数据内容生产不开启 ### 禁止 - ❌ 日志中打印密码、Token、身份证号等敏感信息 - ❌ 在循环内打印日志大批量场景改为汇总后打印 - ❌ 使用 System.out.println - ❌ 使用 e.printStackTrace()规则五事务管理## 事务管理规范 ### 基本规则 - 事务注解只加在 Service 层方法上 - 默认传播行为REQUIRED - 默认隔离级别READ_COMMITTED - 只读查询加 Transactional(readOnly true) ### 事务边界 - ✓ 事务内只做数据库操作和必要的内存计算 - ❌ 事务内禁止调用外部 HTTP/RPC网络超时导致长事务 - ❌ 事务内禁止发 MQ 消息事务回滚消息不回滚 - ✓ 需要在事务提交后发消息使用 TransactionalEventListener(phase AFTER_COMMIT) ### 大事务拆分 - 单个事务内操作行数不应超过 1000 行 - 批量操作分批提交每批 200-500 条 - 长流程用编程式事务 TransactionTemplate 代替 Transactional ### 分布式事务 - 优先用最终一致性方案MQ 本地事务表 - 避免使用 2PC/XA性能差、可用性低3.4 反模式清单除了该怎么做还需要告诉 AI “不该怎么做”。反模式清单的效果往往比正面规则更好——因为 AI 有时候会创造性地犯错。## 反模式清单AI 禁止产出以下代码 ### 性能反模式 - ❌ N1 查询循环内查数据库 - ❌ 全表扫描无 WHERE 条件的 SELECT * - ❌ 大对象序列化后存 Redis应该只存 ID/关键字段 - ❌ 同步调用外部接口无超时设置 ### 安全反模式 - ❌ SQL 拼接必须用参数化查询 - ❌ 日志打印完整 Token / 密码 / 身份证号 - ❌ 硬编码数据库密码 / AK/SK - ❌ 用户输入未校验直接使用 ### 设计反模式 - ❌ God Class单个类超过 500 行 - ❌ 万能 Map 传参应该定义 DTO - ❌ 魔法数字应该定义常量或枚举 - ❌ 在 Controller 中写超过 3 行的数据转换逻辑 ### 并发反模式 - ❌ 非线程安全的 SimpleDateFormat用 DateTimeFormatter - ❌ 双重检查锁不加 volatile - ❌ 直接 new Thread()应该用线程池 - ❌ HashMap 在并发场景使用用 ConcurrentHashMap3.5 标杆文件机制光有规则还不够——给 AI 一个好代码长什么样的参考比规则更直观。## 标杆文件对照表 当 AI 需要编写以下类型的代码时先阅读对应的标杆文件作为参考 | 任务类型 | 标杆文件 | 参考要点 | |---------|---------|---------| | 新增 Controller | FlowController.java | 参数校验、Result 包装、接口注释 | | 新增 Service | FlowServiceImpl.java | 事务管理、异常处理、日志记录 | | 新增 Mapper | FlowMapper.java FlowMapper.xml | SQL 写法、动态条件 | | 新增连接器 | DingTalkConnector.java | 模板方法、鉴权流程、错误处理 | | 新增定时任务 | FlowInstanceCleanScheduler.java | 分页处理、幂等、监控埋点 | | 新增 MQ 消费者 | FlowResumeMessageListener.java | 幂等校验、重试策略、死信处理 | | 新增单元测试 | FlowServiceTest.java | Given-When-Then、Mock 用法 |配置方式在规则文件中引用标杆文件路径AI 编辑器会自动在相关任务时加载参考。四、上下文管理让 AI 理解你的项目4.1 为什么上下文这么重要一个没有项目上下文的 AI写出来的代码是通用的——它不知道你的项目用了什么框架、分了什么层、有什么公共工具类。结果就是自己造了一个工具方法实际项目里已经有了用了项目里不存在的依赖返回值格式和项目其他接口不一致不知道项目的 Result 包装类、分页对象叫什么4.2 四种上下文喂养策略策略一技术栈声明在规则文件开头声明项目技术栈## 项目技术栈 - 语言Java 17 - 框架Spring Boot 3.2 Spring Cloud 2023 - ORMMyBatis-Plus 3.5 - 数据库MySQL 8.0 - 缓存Redis 7 (Lettuce) - 消息队列RocketMQ 5.x - 注册中心Nacos 2.x - 构建工具Maven 3.9 - 日志框架Logback Slf4j - 接口文档Knife4j (OpenAPI 3) - 单元测试JUnit 5 Mockito策略二业务术语词典GlossaryAI 不知道你的业务术语。给一份词典避免命名混乱## 业务术语词典 | 术语 | 英文 | 含义 | 对应实体 | |------|------|------|---------| | 流程实例 | FlowInstance | 一次流程的完整执行记录 | flow_instance 表 | | 连接器 | Connector | 对接第三方系统的适配器 | connector_config 表 | | 节点 | Node | 流程中的单个执行步骤 | flow_node 表 | | 执行快照 | Snapshot | 流程中断时保存的状态 | flow_snapshot 表 | | 租户 | Tenant | 使用平台的企业客户 | tenant 表 | | 空间 | Workspace | 租户下的逻辑隔离单元 | workspace 表 |策略三公共类清单告诉 AI 项目里已有哪些工具类/基类避免重复造轮子## 项目公共类直接使用禁止重复实现 | 类名 | 作用 | 使用示例 | |------|------|---------| | ResultT | 统一返回值包装 | return Result.success(data) | | PageResultT | 分页返回值 | return PageResult.of(page) | | BizException | 业务异常 | throw new BizException(ErrorCode.XXX) | | ErrorCode | 错误码枚举 | ErrorCode.USER_NOT_FOUND | | BaseEntity | 实体基类含 id/createTime/updateTime | extends BaseEntity | | ConvertUtils | Bean 转换工具 | ConvertUtils.convert(source, TargetVO.class) | | AssertUtils | 业务断言 | AssertUtils.notNull(user, ErrorCode.USER_NOT_FOUND) | | RedisUtils | Redis 操作封装 | RedisUtils.set(key, value, 30, TimeUnit.MINUTES) |策略四架构决策记录ADR对于关键的设计决策写成 ADR 让 AI 理解为什么这样设计## ADR-001: 流程引擎使用自研执行器而非开源引擎 ### 决策 自研流程执行器ExecutionRunner不使用 Camunda/Activiti。 ### 原因 1. 开源引擎的 BPMN 模型对 iPaaS 场景过重 2. 我们需要深度控制执行快照和恢复机制 3. 连接器调用的异步编排是核心竞争力 ### 影响 - 流程定义使用自研 JSON Schema不是 BPMN XML - 执行状态机需要自己维护 - 需要自己实现中断恢复机制Snapshot MQ 驱动 ### AI 编码时注意 - 不要引入 Camunda/Activiti 的任何依赖 - 流程相关代码参考 ExecutionRunner.java 的设计模式4.3 上下文窗口管理AI 的上下文窗口有限。不是给越多越好——信息过载会导致 AI 选择性忽视关键信息。原则给精准的上下文而不是给所有的上下文。好的做法 - 告诉 AI 参考 FlowServiceImpl.java 的第 50-80 行 - 只贴与当前任务相关的接口定义 - 在提示词中明确指出关注 XX 方法的异常处理方式 坏的做法 - 一次性把整个 Service 包的所有文件都丢给 AI - 贴了 200 行代码但没说重点在哪 - 给了 10 个相关类但不说关联关系五、工作流实践AI 编码的正确打开方式5.1 任务拆分原则核心原则一次让 AI 做一件事做完验证再做下一件。❌ 错误工作流 帮我实现用户模块的全部功能注册、登录、修改密码、注销 → AI 一次性写 800 行质量失控 ✓ 正确工作流 1. 先实现 UserService.register 方法 → 验证 → ✓ 2. 实现 UserService.login 方法 → 验证 → ✓ 3. 实现 UserService.changePassword 方法 → 验证 → ✓ 4. 实现 UserService.deactivate 方法 → 验证 → ✓5.2 渐进式编码流程Step 1: 接口定义让 AI 先定义签名不写实现 定义 UserService 接口包含 register/login/changePassword 三个方法签名 → 人工审核方法命名、参数设计、返回值 Step 2: 核心逻辑一次只实现一个方法 实现 UserServiceImpl.register参考标杆文件 FlowServiceImpl.java → 人工审核业务逻辑正确性 Step 3: 异常处理增强 给 register 方法补充完整的异常处理和边界情况 → 人工审核异常覆盖度 Step 4: 单元测试 为 register 方法编写单元测试覆盖正常流程 手机号重复 验证码过期三个场景 → 运行测试验证5.3 Review-Fix 循环AI 写完代码后不要直接用。用以下 checklist 做 review## AI 代码 Review Checklist ### 正确性 □ 业务逻辑是否和需求一致 □ 边界情况是否处理空值、空集合、并发 □ SQL 是否有注入风险 □ 数据权限是否考虑租户隔离、操作者权限 ### 规范性 □ 命名是否符合项目规范 □ 分层是否正确没有跨层调用 □ 异常是否用 BizException 包装 □ 日志是否在关键位置记录 □ 事务注解是否正确使用 ### 性能 □ 是否有 N1 查询 □ 循环内是否有 IO 操作 □ 大集合是否分页/流式处理 □ 是否需要加缓存 ### 可维护性 □ 方法长度是否超过 50 行超过需拆分 □ 参数是否超过 5 个超过需封装为对象 □ 是否有魔法数字 □ 注释是否充分复杂逻辑必须有注释发现问题后精确地告诉 AI 哪里有问题✓ 好的反馈register 方法的第 3 步缺少并发控制—— 两个请求同时用同一个手机号注册会出现重复数据。 请加分布式锁或者数据库唯一索引 catch DuplicateKeyException。 ❌ 差的反馈这个代码有 bug改一下六、进阶技巧6.1 用测试驱动 AI先让 AI 写测试再让它写实现。Step 1: 根据以下需求为 UserService.register 编写单元测试。 测试场景正常注册成功 / 手机号已注册 / 验证码过期 / 密码为空 Step 2: 现在实现 UserService.register使上述测试全部通过。这样做的好处测试先行逻辑边界提前定义清楚AI 写实现时有明确的验收标准减少后期补测试的工作6.2 对话式调优不要期望 AI 一次就写对。把它当成一个初级开发者通过对话引导它改进你实现 FlowService.batchExport 方法支持导出流程实例。 AI[生成初版代码] 你两个问题——1. 大批量导出需要分页查询不能一次性加载到内存 2. 导出过程中如果某条失败应该跳过继续而不是整体失败。请修改。 AI[改进版] 你分页 OK 了。但你在循环内每条数据都打了一次 INFO 日志 10万条数据会产生 10万行日志。改为每处理完一页打一次汇总日志。 AI[再次改进]6.3 善用解释能力当 AI 产出的代码你看不懂或不确定是否正确时让它解释设计意图你解释一下你为什么在这里用了 CompletableFuture 而不是同步调用 如果其中一个 Future 异常了其他的会怎样 AI[解释设计决策和异常传播机制] 你明白了但在我们的场景中不需要并行——这三个步骤有顺序依赖。请改回同步。6.4 代码重构请求AI 很擅长做机械性的重构。用精确的重构指令## 好的重构指令 - 把这个 400 行的方法按职责拆成 3-4 个私有方法每个方法做一件事 - 把 if-else 链路改成策略模式 Map 注册 - 把这段重复出现 3 次的逻辑抽成公共方法放到 XxxUtils - 把 MySQL 分页查询改成游标查询避免深分页性能问题 - 把硬编码的配置值提取到 application.yml用 Value 注入七、团队级落地清单如果你要在团队中推行AI 写高质量代码按以下步骤落地第一周基础建设□ 为项目创建规则文件.cursorrules / copilot-instructions.md □ 编写命名规范、分层规范、异常处理规范本文第三章的五类规则 □ 整理反模式清单至少 15-20 条 □ 选定 5-8 个标杆文件 □ 编写项目术语词典Glossary □ 配置技术栈声明第二周模板与流程□ 制作 3-5 个提示词模板新增接口/Bug修复/重构/测试 □ 定义 AI 代码 Review Checklist □ 明确团队的 AI 编码工作流拆分 → 生成 → Review → Fix □ 跑通一个完整案例从需求到代码到测试全流程用 AI 完成第三周持续优化□ 收集团队成员使用中的问题迭代规则文件 □ 把新发现的反模式补充到清单 □ 优秀的 AI 交互案例沉淀为团队 wiki □ 定期 review 规则文件每月一次删除过时规则、补充新规则八、常见问题FAQQ规则文件写多长合适A建议控制在200-500 行。太短覆盖不全太长 AI 会选择性遗忘。核心规则精简明确用表格和列表代替大段文字。QAI 不遵守规则怎么办A常见原因① 规则太模糊“写好代码” vs “方法不超过50行”② 规则和提示词冲突③ 上下文窗口被撑满规则被挤出去了。解法规则写得更具体、更短重要规则放在前面。Q不同 AI 工具的规则格式通用吗A核心内容通用命名规范、分层规范这些放哪个工具都适用但加载方式不同。建议维护一份核心规则文档各工具各自做格式适配。Q一个人开发需要搞这么复杂吗A规则体系的核心价值是一次投入、持续收益。即使一个人开发配好规则后 AI 产出的代码质量也会显著提升——尤其体现在命名一致性和异常处理完整性上。投入 2-3 小时配规则后续每天节省 30 分钟的 review 修改时间。QAI 写的代码还需要 Code Review 吗A绝对需要。AI 代码的 Review 重点和人写的不一样——人写的代码重点看设计是否合理AI 写的代码重点看是否符合项目规范和边界情况是否遗漏。建议建立 AI 代码专属的 Review Checklist。Q如何度量 AI 编码的质量提升效果A三个可量化指标① 代码首次提交通过 Review 的比例无修改意见直接合并的占比② Bug 密度每千行代码的 Bug 数③ 返工率生成的代码需要人工修改的行数占比。配好规则后这三个指标通常改善 30-50%。九、写在最后用 AI 写出高质量代码本质上是把你脑子里的编码常识外化成机器可读的规则。很多经验丰富的开发者觉得 AI 产出的代码不靠谱——但仔细想想你之所以能写出高质量代码是因为你经过多年积累形成了一套内化的规范。AI 没有这个积累它需要你显式地告诉它。三个核心要点规则先行——把命名/分层/异常/日志/事务五类规范写成规则文件一次配置持续生效上下文充分——技术栈声明 术语词典 公共类清单 标杆文件让 AI 理解你的项目任务拆小——一次只做一件事做完验证再做下一件避免 AI 在大任务中失控做到这三点AI 产出的代码质量会从能跑但需要大改提升到Review 几行就能合并。这不是夸张——我们团队在配好规则体系后AI 代码的首次 Review 通过率从 30% 提升到了 70%。标签#AI编码 #提示词工程 #代码质量 #编码规范 #CursorRules #GitHubCopilot #AI编程 #代码审查 #软件工程 #开发效率 #规则引导 #上下文管理 #Java #最佳实践
如何用 AI 写出高质量代码:提示词优化与规则引导的实战指南
发布时间:2026/5/27 10:52:26
写在前面2026 年AI 编码助手已经从尝鲜变成了日常——无论是 Cursor、GitHub Copilot 还是 JetBrains 系的 AI 插件几乎每个开发者每天都在和 AI 结对编程。但大多数人的体感是AI 写代码能用但离好用还有距离。它能帮你补全一段函数、写一个 CRUD但产出的代码经常需要大量人工修改——命名不规范、异常处理粗糙、分层混乱、缺少日志、事务管理遗漏。问题出在哪不是 AI 不行而是你没有告诉它什么是好代码。这篇文章从实战角度出发系统讲解如何通过提示词优化、规则体系建设、上下文管理三板斧让 AI 产出的代码质量从能跑提升到可上线。所有方法来自我们团队半年多的实践经过日均数百次 AI 编码验证。一、核心认知AI 代码质量 f(提示词, 规则, 上下文)先建立一个认知模型AI 产出代码质量 f(提示词质量, 规则约束, 上下文充分度) 其中 - 提示词质量你说清楚了没有——需求描述是否精确、无歧义 - 规则约束你立规矩了没有——AI 是否知道你的编码规范 - 上下文充分度你给够背景了没有——AI 是否理解项目的技术栈和设计三者的影响权重大致是规则约束 (40%) 上下文充分度 (35%) 提示词质量 (25%)为什么规则约束排第一因为一个好的规则体系可以系统性地消灭低级问题——命名、分层、异常处理、日志格式这些问题不应该每次在提示词里重复说而是写成规则让 AI 持续遵守。二、提示词优化从写个函数到精确表达意图2.1 差提示词 vs 好提示词先看反面教材❌ 差提示词 写一个用户注册接口 AI 产出能跑但没有参数校验、没有重复检测、没有事务、没有日志、 返回值格式不统一、异常直接抛出不包装...好的提示词应该包含五要素✓ 好提示词的五要素 1. 做什么What实现用户注册功能 2. 输入输出IO入参 RegisterRequest返回 ResultUserVO 3. 约束条件Constraints手机号唯一性校验、密码加密存储 4. 异常场景Edge Cases手机号已注册、验证码过期、并发注册 5. 技术上下文ContextSpring Boot MyBatis-Plus分层Controller → Service → Mapper示例实现用户注册 Service 方法。 入参RegisterRequestphone, password, verifyCode 返回ResultUserVO 业务逻辑 1. 校验验证码是否有效调用 VerifyCodeService.validate 2. 检查手机号是否已注册查 user 表 3. 密码 BCrypt 加密 4. 插入用户记录 5. 发送注册成功事件Spring Event 约束 - 步骤 2-4 需要在同一事务内 - 手机号已注册抛出 BizException(USER_PHONE_DUPLICATE) - 验证码校验失败抛出 BizException(VERIFY_CODE_INVALID) - 方法入口和异常处记录 INFO/ERROR 日志2.2 提示词四层模型把提示词按抽象层级分成四层越底层越稳定、越顶层越具体┌─────────────────────────────────────────────┐ │ Layer 4: 任务指令每次不同 │ │ 实现 UserService.register 方法 │ ├─────────────────────────────────────────────┤ │ Layer 3: 业务上下文按需提供 │ │ 用户注册需要验证码、手机号唯一... │ ├─────────────────────────────────────────────┤ │ Layer 2: 技术上下文项目级别 │ │ Spring Boot 3 MyBatis-Plus RocketMQ │ ├─────────────────────────────────────────────┤ │ Layer 1: 编码规则全局级别写一次永久生效 │ │ 命名规范、异常处理、日志格式... │ └─────────────────────────────────────────────┘Layer 1-2 不应该每次手写——应该配置成 AI 编辑器的全局规则/项目规则Layer 3-4 是每次需要人工输入的——但越精确AI 产出越好2.3 提示词模板化高频场景可以建立提示词模板降低每次的思考成本## 新增接口模板 实现 [Controller/Service/Mapper] 的 [方法名] 方法。 ### 接口签名 - 入参[参数类型及含义] - 返回[返回类型] - HTTP 方法/路径[POST /api/v1/xxx] ### 业务逻辑按步骤 1. [步骤1] 2. [步骤2] 3. ... ### 边界情况 - [异常场景1] → 抛出 BizException([错误码]) - [异常场景2] → 返回 [特定响应] ### 依赖 - 调用 [XxxService.yyy 方法] - 查询 [表名.字段]## Bug 修复模板 修复 [类名.方法名] 的 [Bug 现象描述]。 ### 当前行为 [描述现在的错误表现] ### 期望行为 [描述修复后应该怎样] ### 根因分析 [如果已知根因写上如果不知道让 AI 先分析] ### 约束 - 不要改变方法签名 - 不要影响 [其他功能] - 修复后补充对应的单元测试2.4 提示词的反模式反模式问题改进“帮我优化一下这个类”太模糊AI 不知道优化什么“把这个类的 N1 查询改为批量查询”一次让 AI 写 500 行上下文越长 AI 越容易偏拆分成 3-5 个小任务分步完成不给示例AI 不知道你的代码风格给一个标杆文件让它参考描述实现而非目标“用 for 循环遍历…”“过滤出满足条件的元素”让 AI 选择最佳实现忽略异常场景AI 默认走 happy path显式列出需要处理的异常三、规则引导建立 AI 必须遵守的编码规范3.1 为什么规则比提示词更重要提示词是临时的——每次对话都要写。规则是持久的——写一次AI 持续遵守。把重复出现的质量要求沉淀成规则而不是每次在提示词里重复。现代 AI 编辑器都支持规则文件的机制Cursor.cursorrules文件Qoder / JetBrains AI项目级 Rules 配置GitHub Copilot.github/copilot-instructions.mdWindsurf.windsurfrules文件3.2 规则体系的三层设计┌────────────────────────────────────────────────┐ │ 全局规则所有项目通用 │ │ - 编程语言级规范 │ │ - 通用设计原则 │ │ - AI 交互偏好 │ ├────────────────────────────────────────────────┤ │ 项目规则当前项目特有 │ │ - 技术栈声明 │ │ - 分层架构规范 │ │ - 业务术语词典 │ ├────────────────────────────────────────────────┤ │ 模块规则特定模块/领域 │ │ - 该模块的设计决策 │ │ - 性能约束 │ │ - 安全要求 │ └────────────────────────────────────────────────┘3.3 五类硬性规则必须配置根据我们团队的实践以下五类规则能消灭80% 的 AI 代码质量问题规则一命名规范## 命名规范 ### 类命名 - Controller 类{业务}Controller如 FlowController - Service 接口{业务}Service如 FlowService - Service 实现{业务}ServiceImpl如 FlowServiceImpl - Mapper 接口{业务}Mapper如 FlowMapper - 实体类{业务}Entity 或 {业务}DO如 FlowEntity - VO/DTO{业务}VO / {业务}DTO / {业务}Request / {业务}Response ### 方法命名 - 查询单条get{Entity}ById / find{Entity}By{Condition} - 查询列表list{Entity}s / page{Entity}s - 新增create{Entity} / add{Entity} - 修改update{Entity} - 删除delete{Entity} / remove{Entity} - 判断is{Condition} / has{Property} / can{Action} - 转换convert{Source}To{Target} / build{Target} ### 变量命名 - 布尔变量is/has/can 开头如 isEnabled, hasPermission - 集合变量复数名词如 users, orderItems - Map 变量{key}To{Value}Map如 userIdToNameMap - 常量全大写下划线分隔如 MAX_RETRY_COUNT ### 禁止 - ❌ 单字母变量循环变量 i/j/k 除外 - ❌ 拼音命名 - ❌ 无意义缩写如 usr, mgr, proc - ❌ 匈牙利命名法如 strName, intCount规则二分层架构## 分层规范 ### 调用关系严格单向 Controller → Service → Mapper/Repository → 外部 Client → MQ Producer ### 各层职责 - Controller参数校验Valid、调用 Service、包装 Result - Service业务逻辑、事务管理、事件发布 - Mapper/Repository数据访问不含业务逻辑 - Client外部系统调用封装 ### 禁止 - ❌ Controller 直接调用 Mapper - ❌ Service 之间循环依赖 - ❌ Mapper 中写业务判断逻辑 - ❌ 在 Controller 中写超过 10 行的业务逻辑 - ❌ Entity/DO 对象暴露到 Controller 层必须转 VO规则三异常处理## 异常处理规范 ### 业务异常 - 统一使用 BizException(ErrorCode code, String message) - ErrorCode 为枚举格式{模块}_{异常描述} - 示例FLOW_INSTANCE_NOT_FOUND, USER_PHONE_DUPLICATE ### 异常分类 - 参数校验异常Controller 层 Valid 抛出全局拦截器统一处理 - 业务异常Service 层主动抛出 BizException返回 400 - 系统异常未预期的 RuntimeException返回 500记录 ERROR 日志 ### 规则 - ✓ 异常消息必须包含关键业务标识如 flowId, userId - ✓ 捕获异常必须记日志或重新抛出禁止空 catch - ✓ 外部调用HTTP/RPC必须 catch 并包装为业务异常 - ❌ 禁止用异常控制业务流程如用 try-catch 代替 if-else - ❌ 禁止 catch(Exception e) 后吞掉不处理 - ❌ 禁止在循环内 try-catch应该在循环外规则四日志规范## 日志规范 ### 必须记录日志的场景 - 方法入口INFO核心 Service 方法入口记录入参关键字段 - 外部调用前后INFOHTTP/RPC/MQ 调用的请求和响应 - 异常ERROR包含异常堆栈和业务上下文 - 状态变更INFO关键业务状态机变更 ### 日志格式 - 使用 Slf4j 占位符log.info(处理流程实例, flowId{}, status{}, flowId, status) - 禁止字符串拼接❌ log.info(处理 flowId 状态 status) ### 级别使用 - ERROR系统异常、外部调用失败、数据不一致 - WARN业务异常可预期的错误、性能退化 - INFO核心业务流程、状态变更、外部调用 - DEBUG调试信息、详细数据内容生产不开启 ### 禁止 - ❌ 日志中打印密码、Token、身份证号等敏感信息 - ❌ 在循环内打印日志大批量场景改为汇总后打印 - ❌ 使用 System.out.println - ❌ 使用 e.printStackTrace()规则五事务管理## 事务管理规范 ### 基本规则 - 事务注解只加在 Service 层方法上 - 默认传播行为REQUIRED - 默认隔离级别READ_COMMITTED - 只读查询加 Transactional(readOnly true) ### 事务边界 - ✓ 事务内只做数据库操作和必要的内存计算 - ❌ 事务内禁止调用外部 HTTP/RPC网络超时导致长事务 - ❌ 事务内禁止发 MQ 消息事务回滚消息不回滚 - ✓ 需要在事务提交后发消息使用 TransactionalEventListener(phase AFTER_COMMIT) ### 大事务拆分 - 单个事务内操作行数不应超过 1000 行 - 批量操作分批提交每批 200-500 条 - 长流程用编程式事务 TransactionTemplate 代替 Transactional ### 分布式事务 - 优先用最终一致性方案MQ 本地事务表 - 避免使用 2PC/XA性能差、可用性低3.4 反模式清单除了该怎么做还需要告诉 AI “不该怎么做”。反模式清单的效果往往比正面规则更好——因为 AI 有时候会创造性地犯错。## 反模式清单AI 禁止产出以下代码 ### 性能反模式 - ❌ N1 查询循环内查数据库 - ❌ 全表扫描无 WHERE 条件的 SELECT * - ❌ 大对象序列化后存 Redis应该只存 ID/关键字段 - ❌ 同步调用外部接口无超时设置 ### 安全反模式 - ❌ SQL 拼接必须用参数化查询 - ❌ 日志打印完整 Token / 密码 / 身份证号 - ❌ 硬编码数据库密码 / AK/SK - ❌ 用户输入未校验直接使用 ### 设计反模式 - ❌ God Class单个类超过 500 行 - ❌ 万能 Map 传参应该定义 DTO - ❌ 魔法数字应该定义常量或枚举 - ❌ 在 Controller 中写超过 3 行的数据转换逻辑 ### 并发反模式 - ❌ 非线程安全的 SimpleDateFormat用 DateTimeFormatter - ❌ 双重检查锁不加 volatile - ❌ 直接 new Thread()应该用线程池 - ❌ HashMap 在并发场景使用用 ConcurrentHashMap3.5 标杆文件机制光有规则还不够——给 AI 一个好代码长什么样的参考比规则更直观。## 标杆文件对照表 当 AI 需要编写以下类型的代码时先阅读对应的标杆文件作为参考 | 任务类型 | 标杆文件 | 参考要点 | |---------|---------|---------| | 新增 Controller | FlowController.java | 参数校验、Result 包装、接口注释 | | 新增 Service | FlowServiceImpl.java | 事务管理、异常处理、日志记录 | | 新增 Mapper | FlowMapper.java FlowMapper.xml | SQL 写法、动态条件 | | 新增连接器 | DingTalkConnector.java | 模板方法、鉴权流程、错误处理 | | 新增定时任务 | FlowInstanceCleanScheduler.java | 分页处理、幂等、监控埋点 | | 新增 MQ 消费者 | FlowResumeMessageListener.java | 幂等校验、重试策略、死信处理 | | 新增单元测试 | FlowServiceTest.java | Given-When-Then、Mock 用法 |配置方式在规则文件中引用标杆文件路径AI 编辑器会自动在相关任务时加载参考。四、上下文管理让 AI 理解你的项目4.1 为什么上下文这么重要一个没有项目上下文的 AI写出来的代码是通用的——它不知道你的项目用了什么框架、分了什么层、有什么公共工具类。结果就是自己造了一个工具方法实际项目里已经有了用了项目里不存在的依赖返回值格式和项目其他接口不一致不知道项目的 Result 包装类、分页对象叫什么4.2 四种上下文喂养策略策略一技术栈声明在规则文件开头声明项目技术栈## 项目技术栈 - 语言Java 17 - 框架Spring Boot 3.2 Spring Cloud 2023 - ORMMyBatis-Plus 3.5 - 数据库MySQL 8.0 - 缓存Redis 7 (Lettuce) - 消息队列RocketMQ 5.x - 注册中心Nacos 2.x - 构建工具Maven 3.9 - 日志框架Logback Slf4j - 接口文档Knife4j (OpenAPI 3) - 单元测试JUnit 5 Mockito策略二业务术语词典GlossaryAI 不知道你的业务术语。给一份词典避免命名混乱## 业务术语词典 | 术语 | 英文 | 含义 | 对应实体 | |------|------|------|---------| | 流程实例 | FlowInstance | 一次流程的完整执行记录 | flow_instance 表 | | 连接器 | Connector | 对接第三方系统的适配器 | connector_config 表 | | 节点 | Node | 流程中的单个执行步骤 | flow_node 表 | | 执行快照 | Snapshot | 流程中断时保存的状态 | flow_snapshot 表 | | 租户 | Tenant | 使用平台的企业客户 | tenant 表 | | 空间 | Workspace | 租户下的逻辑隔离单元 | workspace 表 |策略三公共类清单告诉 AI 项目里已有哪些工具类/基类避免重复造轮子## 项目公共类直接使用禁止重复实现 | 类名 | 作用 | 使用示例 | |------|------|---------| | ResultT | 统一返回值包装 | return Result.success(data) | | PageResultT | 分页返回值 | return PageResult.of(page) | | BizException | 业务异常 | throw new BizException(ErrorCode.XXX) | | ErrorCode | 错误码枚举 | ErrorCode.USER_NOT_FOUND | | BaseEntity | 实体基类含 id/createTime/updateTime | extends BaseEntity | | ConvertUtils | Bean 转换工具 | ConvertUtils.convert(source, TargetVO.class) | | AssertUtils | 业务断言 | AssertUtils.notNull(user, ErrorCode.USER_NOT_FOUND) | | RedisUtils | Redis 操作封装 | RedisUtils.set(key, value, 30, TimeUnit.MINUTES) |策略四架构决策记录ADR对于关键的设计决策写成 ADR 让 AI 理解为什么这样设计## ADR-001: 流程引擎使用自研执行器而非开源引擎 ### 决策 自研流程执行器ExecutionRunner不使用 Camunda/Activiti。 ### 原因 1. 开源引擎的 BPMN 模型对 iPaaS 场景过重 2. 我们需要深度控制执行快照和恢复机制 3. 连接器调用的异步编排是核心竞争力 ### 影响 - 流程定义使用自研 JSON Schema不是 BPMN XML - 执行状态机需要自己维护 - 需要自己实现中断恢复机制Snapshot MQ 驱动 ### AI 编码时注意 - 不要引入 Camunda/Activiti 的任何依赖 - 流程相关代码参考 ExecutionRunner.java 的设计模式4.3 上下文窗口管理AI 的上下文窗口有限。不是给越多越好——信息过载会导致 AI 选择性忽视关键信息。原则给精准的上下文而不是给所有的上下文。好的做法 - 告诉 AI 参考 FlowServiceImpl.java 的第 50-80 行 - 只贴与当前任务相关的接口定义 - 在提示词中明确指出关注 XX 方法的异常处理方式 坏的做法 - 一次性把整个 Service 包的所有文件都丢给 AI - 贴了 200 行代码但没说重点在哪 - 给了 10 个相关类但不说关联关系五、工作流实践AI 编码的正确打开方式5.1 任务拆分原则核心原则一次让 AI 做一件事做完验证再做下一件。❌ 错误工作流 帮我实现用户模块的全部功能注册、登录、修改密码、注销 → AI 一次性写 800 行质量失控 ✓ 正确工作流 1. 先实现 UserService.register 方法 → 验证 → ✓ 2. 实现 UserService.login 方法 → 验证 → ✓ 3. 实现 UserService.changePassword 方法 → 验证 → ✓ 4. 实现 UserService.deactivate 方法 → 验证 → ✓5.2 渐进式编码流程Step 1: 接口定义让 AI 先定义签名不写实现 定义 UserService 接口包含 register/login/changePassword 三个方法签名 → 人工审核方法命名、参数设计、返回值 Step 2: 核心逻辑一次只实现一个方法 实现 UserServiceImpl.register参考标杆文件 FlowServiceImpl.java → 人工审核业务逻辑正确性 Step 3: 异常处理增强 给 register 方法补充完整的异常处理和边界情况 → 人工审核异常覆盖度 Step 4: 单元测试 为 register 方法编写单元测试覆盖正常流程 手机号重复 验证码过期三个场景 → 运行测试验证5.3 Review-Fix 循环AI 写完代码后不要直接用。用以下 checklist 做 review## AI 代码 Review Checklist ### 正确性 □ 业务逻辑是否和需求一致 □ 边界情况是否处理空值、空集合、并发 □ SQL 是否有注入风险 □ 数据权限是否考虑租户隔离、操作者权限 ### 规范性 □ 命名是否符合项目规范 □ 分层是否正确没有跨层调用 □ 异常是否用 BizException 包装 □ 日志是否在关键位置记录 □ 事务注解是否正确使用 ### 性能 □ 是否有 N1 查询 □ 循环内是否有 IO 操作 □ 大集合是否分页/流式处理 □ 是否需要加缓存 ### 可维护性 □ 方法长度是否超过 50 行超过需拆分 □ 参数是否超过 5 个超过需封装为对象 □ 是否有魔法数字 □ 注释是否充分复杂逻辑必须有注释发现问题后精确地告诉 AI 哪里有问题✓ 好的反馈register 方法的第 3 步缺少并发控制—— 两个请求同时用同一个手机号注册会出现重复数据。 请加分布式锁或者数据库唯一索引 catch DuplicateKeyException。 ❌ 差的反馈这个代码有 bug改一下六、进阶技巧6.1 用测试驱动 AI先让 AI 写测试再让它写实现。Step 1: 根据以下需求为 UserService.register 编写单元测试。 测试场景正常注册成功 / 手机号已注册 / 验证码过期 / 密码为空 Step 2: 现在实现 UserService.register使上述测试全部通过。这样做的好处测试先行逻辑边界提前定义清楚AI 写实现时有明确的验收标准减少后期补测试的工作6.2 对话式调优不要期望 AI 一次就写对。把它当成一个初级开发者通过对话引导它改进你实现 FlowService.batchExport 方法支持导出流程实例。 AI[生成初版代码] 你两个问题——1. 大批量导出需要分页查询不能一次性加载到内存 2. 导出过程中如果某条失败应该跳过继续而不是整体失败。请修改。 AI[改进版] 你分页 OK 了。但你在循环内每条数据都打了一次 INFO 日志 10万条数据会产生 10万行日志。改为每处理完一页打一次汇总日志。 AI[再次改进]6.3 善用解释能力当 AI 产出的代码你看不懂或不确定是否正确时让它解释设计意图你解释一下你为什么在这里用了 CompletableFuture 而不是同步调用 如果其中一个 Future 异常了其他的会怎样 AI[解释设计决策和异常传播机制] 你明白了但在我们的场景中不需要并行——这三个步骤有顺序依赖。请改回同步。6.4 代码重构请求AI 很擅长做机械性的重构。用精确的重构指令## 好的重构指令 - 把这个 400 行的方法按职责拆成 3-4 个私有方法每个方法做一件事 - 把 if-else 链路改成策略模式 Map 注册 - 把这段重复出现 3 次的逻辑抽成公共方法放到 XxxUtils - 把 MySQL 分页查询改成游标查询避免深分页性能问题 - 把硬编码的配置值提取到 application.yml用 Value 注入七、团队级落地清单如果你要在团队中推行AI 写高质量代码按以下步骤落地第一周基础建设□ 为项目创建规则文件.cursorrules / copilot-instructions.md □ 编写命名规范、分层规范、异常处理规范本文第三章的五类规则 □ 整理反模式清单至少 15-20 条 □ 选定 5-8 个标杆文件 □ 编写项目术语词典Glossary □ 配置技术栈声明第二周模板与流程□ 制作 3-5 个提示词模板新增接口/Bug修复/重构/测试 □ 定义 AI 代码 Review Checklist □ 明确团队的 AI 编码工作流拆分 → 生成 → Review → Fix □ 跑通一个完整案例从需求到代码到测试全流程用 AI 完成第三周持续优化□ 收集团队成员使用中的问题迭代规则文件 □ 把新发现的反模式补充到清单 □ 优秀的 AI 交互案例沉淀为团队 wiki □ 定期 review 规则文件每月一次删除过时规则、补充新规则八、常见问题FAQQ规则文件写多长合适A建议控制在200-500 行。太短覆盖不全太长 AI 会选择性遗忘。核心规则精简明确用表格和列表代替大段文字。QAI 不遵守规则怎么办A常见原因① 规则太模糊“写好代码” vs “方法不超过50行”② 规则和提示词冲突③ 上下文窗口被撑满规则被挤出去了。解法规则写得更具体、更短重要规则放在前面。Q不同 AI 工具的规则格式通用吗A核心内容通用命名规范、分层规范这些放哪个工具都适用但加载方式不同。建议维护一份核心规则文档各工具各自做格式适配。Q一个人开发需要搞这么复杂吗A规则体系的核心价值是一次投入、持续收益。即使一个人开发配好规则后 AI 产出的代码质量也会显著提升——尤其体现在命名一致性和异常处理完整性上。投入 2-3 小时配规则后续每天节省 30 分钟的 review 修改时间。QAI 写的代码还需要 Code Review 吗A绝对需要。AI 代码的 Review 重点和人写的不一样——人写的代码重点看设计是否合理AI 写的代码重点看是否符合项目规范和边界情况是否遗漏。建议建立 AI 代码专属的 Review Checklist。Q如何度量 AI 编码的质量提升效果A三个可量化指标① 代码首次提交通过 Review 的比例无修改意见直接合并的占比② Bug 密度每千行代码的 Bug 数③ 返工率生成的代码需要人工修改的行数占比。配好规则后这三个指标通常改善 30-50%。九、写在最后用 AI 写出高质量代码本质上是把你脑子里的编码常识外化成机器可读的规则。很多经验丰富的开发者觉得 AI 产出的代码不靠谱——但仔细想想你之所以能写出高质量代码是因为你经过多年积累形成了一套内化的规范。AI 没有这个积累它需要你显式地告诉它。三个核心要点规则先行——把命名/分层/异常/日志/事务五类规范写成规则文件一次配置持续生效上下文充分——技术栈声明 术语词典 公共类清单 标杆文件让 AI 理解你的项目任务拆小——一次只做一件事做完验证再做下一件避免 AI 在大任务中失控做到这三点AI 产出的代码质量会从能跑但需要大改提升到Review 几行就能合并。这不是夸张——我们团队在配好规则体系后AI 代码的首次 Review 通过率从 30% 提升到了 70%。标签#AI编码 #提示词工程 #代码质量 #编码规范 #CursorRules #GitHubCopilot #AI编程 #代码审查 #软件工程 #开发效率 #规则引导 #上下文管理 #Java #最佳实践