我花 7 天用 AI 重构了我的开发方式:一个 Java 程序员的 AI 工作流实践

发布时间:2026/7/25 16:09:31

我花 7 天用 AI 重构了我的开发方式:一个 Java 程序员的 AI 工作流实践 摘要这不是一篇“AI 一键写完项目”的爽文而是一份可以照着执行的 Java 开发工作流复盘。我用 7 天把需求澄清、读代码、写接口、排查故障、补测试、优化 SQL 和沉淀文档重新串了一遍。结果不是每天少上四小时班而是把大量无效搜索、机械搬运和重复解释压缩掉让有限的四小时高质量时间真正落在设计、验证和决策上。文中给出任务日志、提示模板、Java/JUnit/SQL 示例、踩坑记录和一套可复用的 AI 协作清单。先说结论AI 没替我写代码它先替我消灭了“来回切换”过去我对“AI 提升开发效率”这句话一直有点警惕。网上常见的演示是输入一句需求模型吐出几百行代码页面一刷新项目就跑起来了。这个过程看着很爽但只要把场景换成一个维护多年的 Java 项目事情立刻变了表名不是按常规命名的字段里还有历史兼容逻辑一个“新增状态”可能同时影响枚举、数据库、缓存、消息队列和前端字典单元测试能通过不代表集成环境里的事务和权限没问题真正耗时间的往往不是敲代码而是确认“改哪里、为什么改、改完会不会伤到别处”。所以这次我没有给自己定“7 天学会 20 个 AI 工具”的目标也没有统计模型生成了多少行代码。我只记录一件事完成同一类开发任务从收到需求到交付可验证结果中间哪些时间可以被压缩哪些责任必须留在人手里。一周之后变化最明显的不是打字速度而是工作节奏。以前遇到陌生模块我会在 IDE、数据库客户端、浏览器、群聊记录和旧文档之间反复切换。现在我会先把任务边界、相关文件、失败现象和验收条件整理成一个上下文包再让 AI 做第一轮归纳。它负责快速展开可能性我负责删掉不符合项目事实的部分它负责生成候选修改我负责看 diff、跑测试、查数据和做最后判断。这套协作可以概括成一句话把 AI 放进反馈闭环而不是放在交付终点。一、改造前一天 8 小时是怎么被切碎的我先连续记录了几天普通开发日没有刻意挑“适合 AI”的任务。下面是一个典型工作日的时间去向。它不是严谨的生产力实验只是帮助我定位浪费发生在哪里。工作环节原来的常见耗时真正困难的部分是否适合交给 AI理解需求、补问题清单50 分钟找到模糊条件和隐含边界适合做第一轮审查阅读陌生模块90 分钟找入口、调用链、数据流适合归纳人来核对编写接口与 DTO80 分钟项目约定、校验、异常语义可生成草稿排查报错110 分钟从噪声日志中找关键证据很适合压缩日志和提出假设补测试60 分钟边界用例是否完整适合生成测试矩阵写文档、提交说明50 分钟把改动讲清楚适合结构化整理沟通和上下文切换40 分钟反复解释同一背景可用任务记录减少重复这里最值得优化的不是“编写接口”那 80 分钟而是上下文切换和重复理解。比如一个空指针异常我可能先复制完整日志到搜索引擎再打开报错行再向上追调用者再查数据库里是否有脏数据。中途同事问一句进度我又要把思路口头复述一遍。回来以后刚才建立的心智模型已经散了一半。AI 的价值恰好在这里它可以充当一个临时的“外部工作记忆”帮我保存问题、证据、假设和下一步。但前提是我不能只扔给它一句“这是什么问题”。二、我重新设计的闭环先给证据再让 AI 动手我最后稳定下来的流程如下不准确准确否是任务与验收条件收集最小上下文让 AI 复述问题与列出假设人工核对事实生成最小修改方案审查 Diff 与安全边界运行测试/查询/构建结果通过?把失败证据反馈给 AI人工验收与提交沉淀决策和复盘这张图里有三个我刻意保留的人工关卡事实核对。模型可以推理但它不知道我们项目里的status4为什么代表“人工关闭”。变更审查。AI 很容易顺手“优化”用户没有要求改的地方范围必须由人控制。最终验收。编译通过只是最低门槛业务数据、权限、并发、回滚都需要真实验证。为了让每次对话不从零开始我给任务准备了一个很朴素的上下文模板【目标】 新增订单取消原因查询接口只读不改现有取消流程。 【验收条件】 1. 仅订单创建人和管理员可查询 2. 找不到订单返回业务错误 ORDER_NOT_FOUND 3. 老订单 cancellation_reason 为空时返回“未记录”不能报错 4. 必须补 Controller 与 Service 测试。 【已知事实】 - Spring Boot 3.xJDK 17 - 统一响应体为 CommonResultT - 当前分支已有未提交的前端字典修改不要触碰 - 权限判断复用 OrderPermissionService。 【相关文件】 - OrderController.java - OrderQueryService.java - OrderPermissionService.java - OrderMapper.xml 【希望你先做什么】 先复述调用链、列出风险和需要我确认的问题不要修改代码。最后一句很重要。遇到陌生模块时我不会一上来就让 AI 改代码而是先让它证明自己理解了问题。它的复述如果错了后面的代码写得越快返工越大。三、第 1 天不写代码先给自己的工作做“接口盘点”第一天我只做了一件事把最近两周的开发任务分成四类。类型典型任务我给 AI 的权限信息压缩总结日志、整理调用链、比较配置只读可大胆使用草稿生成DTO、测试矩阵、SQL 候选、文档可生成必须人工审查有限执行修改指定文件、运行指定测试明确范围后执行高风险操作数据修复、生产配置、权限、删除AI 只给方案不直接执行这个分类看起来简单却解决了我最初的一个问题同一个工具不应该在所有任务上拥有同样权限。读一段日志和执行一条生产 SQL风险完全不是一个量级。把“能不能用 AI”问成一个二选一问题没有意义真正要问的是它能读哪些上下文它能改哪些文件它能运行哪些命令哪些动作必须再次确认失败以后能否回滚我还建了一个任务日志每次只记六项## 任务订单取消原因查询 - 开始时间09:20 - 目标增加只读查询接口 - AI 参与调用链归纳、测试矩阵、代码草稿 - 人工决策权限复用方式、空值兼容策略 - 验证模块测试 42/42通过手工检查 3 类账号 - 复盘一开始漏掉历史空值测试矩阵帮助发现如果不记录人很容易只记住 AI “一把过”的高光时刻却忘了它制造的返工。任务日志让我能够区分真正节省的时间和只是看起来很快的输出。四、第 2 天让 AI 帮我读代码但禁止它先入为主维护老项目最累的环节之一是在陌生模块里找真正的入口。以前我的做法是全文搜索一个接口名沿着 Controller、Service、Mapper 一层层点开。现在我仍然这样做只是先把搜索结果和关键文件交给 AI让它输出一张“待核对地图”。我会要求它按固定格式回答请只根据我提供的代码回答不要猜测未出现的实现。 输出 1. 请求从 Controller 到数据库的调用链 2. 每一层的输入、输出和副作用 3. 与权限、事务、缓存相关的代码位置 4. 你无法确认的地方统一标记为【待核对】 5. 最后给出最小阅读顺序最多 8 个文件。这比“帮我分析一下项目”有效得多。后者通常会得到一段正确但空泛的架构介绍前者会逼着模型区分证据和推断。以一个订单状态查询为例AI 第一次给出的调用链是OrderController - OrderService - OrderMapper - t_order看起来没有问题但项目里实际还有一个切面根据租户重写查询条件Mapper XML 里又关联了归档表。如果直接按它的第一版理解修改很可能在测试环境正常、到历史数据查询时失败。我补充了切面和 XML 后再让它更新地图。这时 AI 的作用不是“发现一切”而是把我已经找到的证据组织成可复用的结构。第二天结束时我最大的感受是AI 读代码的上限取决于它能看到什么AI 读代码的可信度取决于它是否被要求标注不知道什么。五、第 3 天写接口——从“生成代码”改成“生成最小 Diff”第三天开始真正改代码。我刻意选择了一个小接口而不是让 AI 新建一整套模块。需求是根据订单号查询取消信息。为了让示例聚焦下面省略项目里的统一异常和权限实现publicrecordCancellationView(StringorderNo,Stringreason,LocalDateTimecancelledAt){publicstaticCancellationViewfrom(Orderorder){StringsafeReasonOptional.ofNullable(order.getCancellationReason()).filter(reason-!reason.isBlank()).orElse(未记录);returnnewCancellationView(order.getOrderNo(),safeReason,order.getCancelledAt());}}Controller 没有直接访问 Mapper而是复用现有查询服务RestControllerRequestMapping(/api/orders)RequiredArgsConstructorclassOrderQueryController{privatefinalOrderQueryServiceorderQueryService;privatefinalOrderPermissionServicepermissionService;GetMapping(/{orderNo}/cancellation)CommonResultCancellationViewgetCancellation(PathVariableStringorderNo,AuthenticationPrincipalLoginUserloginUser){OrderorderorderQueryService.getRequired(orderNo);permissionService.checkCanRead(loginUser,order);returnCommonResult.success(CancellationView.from(order));}}AI 最初给我的代码更“完整”它新建了一个 Repository、一个异常类型还改了统一响应体。单看每一段都说得通但它把一个小需求扩成了架构改造。我把提示改成只修改我列出的 3 个文件优先复用现有 Service、异常和响应体 不要新增依赖不要重命名公共类型不要顺手格式化无关代码 先给出变更计划和预计 diff再生成实现。第二版明显收敛。这里有一个很实用的判断标准让 AI 写“文件”还是写“变更”对全新练习项目生成完整文件没什么问题对已有项目我更关心它相对当前代码改了什么。因此审查时我只看 diff修改是否超出需求是否复制了已有能力是否改变异常语义是否把敏感信息写入日志是否引入不必要依赖是否保留了历史兼容。当我开始用“最小 diff”约束 AI 后代码量反而少了但一次通过率更高。六、第 4 天Debug——别把 3000 行日志直接倒给模型第四天遇到的是一个更真实的问题测试环境偶发返回 500本地无法稳定复现。最初我犯了一个典型错误把完整日志直接贴进对话。结果 AI 抓住了最显眼的一条连接池警告给出了一套数据库连接优化建议。但那条警告在正常请求里也存在真正的异常藏在后面。我重新整理证据只保留第一个业务异常根因Caused by前后各 20 行请求 ID 对应的 SQL发生时间、接口参数和环境差异一次成功请求的对照信息。然后让 AI 输出“假设表”而不是直接给结论假设支持证据反对证据下一步验证历史订单字段为空失败订单创建时间较早本地新数据无法复现查询该订单原始字段权限服务返回空组织日志在权限判断后失败同组织其他订单成功打印组织 ID不打印用户敏感信息缓存旧对象缺字段清缓存后短暂恢复未确认缓存版本对比缓存与数据库对象这个格式会迫使我们把“可能”与“已经证明”分开。最终根因是缓存中的旧序列化对象没有新字段反序列化后为null而下游代码直接调用了trim()。修复不复杂privateStringnormalizeReason(Stringreason){if(reasonnull||reason.isBlank()){return未记录;}returnreason.trim();}真正有价值的是复盘AI 第一次判断错不是因为它完全不懂 Java而是我给了噪声过多的上下文“请分析根因”太容易得到一个自信结论“列出互斥假设、证据和验证动作”更适合故障排查没有真实查询和复现任何根因都只是候选答案。此后我固定使用下面这段 Debug 提示你是排障搭档不是结论生成器。 请按“现象—证据—假设—验证动作”回答。 至少给出 3 个可能原因并说明每个原因如何被证伪。 如果证据不足明确写“当前不能下结论”。 不要建议大规模重构优先给最小验证步骤。七、第 5 天补测试——AI 最适合先生成“测试矩阵”让 AI 直接写单元测试常见结果是代码很长Mock 很全但只验证了最顺利的路径。所以第五天我先让它生成测试矩阵场景输入依赖状态预期正常取消订单合法订单号有取消原因返回原原因历史订单合法订单号原因为null返回“未记录”空白原因合法订单号原因为空格返回“未记录”订单不存在未知订单号查询为空抛ORDER_NOT_FOUND非订单所有人合法订单号权限拒绝返回无权限管理员查询合法订单号管理员权限正常返回确认矩阵后再让 AI 按项目现有测试风格生成代码。比如对取消原因的参数化测试classCancellationViewTest{ParameterizedTestNullAndEmptySourceValueSource(strings{ , })voidshouldFallbackWhenReasonIsMissing(Stringreason){OrderordernewOrder();order.setOrderNo(SO20260725001);order.setCancellationReason(reason);order.setCancelledAt(LocalDateTime.of(2026,7,25,10,30));CancellationViewviewCancellationView.from(order);assertEquals(未记录,view.reason());assertEquals(SO20260725001,view.orderNo());}}针对权限逻辑我会检查 AI 是否只验证“方法被调用”还是验证真正的业务结果。下面这种测试就太弱verify(permissionService).checkCanRead(any(),any());它只能证明调用发生过不能证明传入的是正确用户和正确订单。更好的做法是捕获参数或者直接覆盖允许与拒绝两个结果。AI 生成测试时还经常出现三类问题Mock 了被测对象内部太多细节导致重构一下测试就全碎自己编了不存在的工厂方法和测试基类为了让测试通过反过来修改生产代码的可见性。我的约束是测试必须先编译失败时只把第一组关键错误反馈给 AI禁止为了测试方便扩大生产方法权限。模型能把测试骨架搭得很快但测试有没有保护真实风险仍然需要开发者判断。八、第 6 天SQL 与文档——让 AI 解释计划不让它“猜索引”第六天我把 AI 用在 SQL 优化和接口文档上。原 SQL 是按租户、状态和创建时间查询订单SELECTid,order_no,user_id,status,created_atFROMt_orderWHEREtenant_id?ANDstatus?ANDcreated_at?ORDERBYcreated_atDESCLIMIT50;如果只把 SQL 发给 AI它几乎一定会建议建立联合索引CREATEINDEXidx_order_tenant_status_createdONt_order(tenant_id,status,created_at);这个建议可能正确也可能只是“教科书正确”。真实项目还要看现有索引是否已经覆盖status的区分度查询频率与写入成本实际执行计划是否走索引是否存在按user_id的另一类高频查询数据库类型和版本。所以我提供了脱敏后的表结构、索引列表和EXPLAIN结果让 AI 逐列解释再由我在测试库验证。优化前后记录的是扫描行数、回表情况和耗时分布而不是只看一次查询“快了几毫秒”。文档部分则更适合 AI。提交前我会让它根据 diff 生成一版说明请根据变更内容生成提交说明包含 1. 为什么改 2. 改了什么 3. 没改什么 4. 如何验证 5. 风险与回滚方式。 不要写“优化了系统性能”这类无法验证的空话。得到的草稿再由我补上真正的业务背景。这样写出来的文档比“新增取消原因接口详见代码”有用得多下一位维护者也能知道为什么保留了“未记录”这个兼容逻辑。九、第 7 天把零散技巧沉淀成个人 SOP第七天我没有继续试新工具而是整理一份每天都能用的清单。1. 开始任务前用一句话写清目标不把解决方案当需求列出验收条件和明确不做的范围标注相关模块、技术版本和项目约定区分只读任务、可修改任务和高风险操作检查上下文里是否有密钥、用户数据、内部地址。2. 让 AI 分析时先复述问题再给方案要求区分“代码事实”“合理推断”“待核对”限制读取和修改范围复杂任务先要计划不要直接要完整代码故障排查要求假设和证伪步骤。3. AI 给出修改后只看 diff不被大段完整代码淹没检查是否改了无关文件检查异常、日志、权限和空值运行最小相关测试再运行更大范围测试手工验证至少一个正常场景和一个边界场景。4. 提交之前清理模型生成的无意义注释确认没有虚构 API、依赖和配置项记录验证命令和结果写清风险与回滚把本次踩坑补进团队文档或任务记录。这份 SOP 的意义不是把开发变成流水线而是把“我脑子里知道要检查的事”外显出来。AI 的输出越快检查清单越重要。十、7 天后的时间对比省下来的不是全部工时而是低价值耗时下面是同类任务在一周前后的粗略对比。样本量很小任务难度也不可能完全相同所以不要把它当成普遍结论。环节改造前稳定后变化原因需求澄清50 分钟30 分钟AI 先生成边界问题清单阅读模块90 分钟50 分钟先形成调用链地图再定点阅读接口草稿80 分钟45 分钟复用模板限制最小 diffDebug110 分钟60 分钟压缩日志使用假设表测试设计与编码60 分钟40 分钟先矩阵后代码文档与提交说明50 分钟25 分钟根据 diff 生成结构化草稿返工与上下文恢复40 分钟20 分钟任务日志保留思路合计从约 8 小时降到约 4.5 小时但这并不代表以后每天只工作半天。省下的时间很快会被更深入的设计、评审、沟通和新任务填满。对我而言真正的收益有三点晚上不再因为机械补文档而拖延复杂问题的思路不容易在切换窗口时丢失我能把更多注意力放到业务边界而不是样板代码。“8 小时变 4 小时”只有在任务类型合适、上下文清楚、验证手段完整时才可能发生。遇到架构决策、生产事故和复杂历史兼容AI 甚至可能让前期探索变长。但只要过程留下证据这种变长也不一定是坏事。十一、我踩过的 6 个坑坑 1提示词写得很长却没有验收条件长提示不等于好提示。背景写了两千字却不说输出要满足什么模型仍然只能猜。最有效的不是堆角色设定而是明确目标、范围、约束和验证方式。坑 2把整个项目一次性塞进去上下文越多噪声也越多。相似的旧实现、过期文档和无关日志会把模型带偏。我的做法是先给入口和失败证据模型提出缺口后再补文件。坑 3看到代码“像能跑”就直接接受AI 很擅长生成风格正确的代码也很擅长虚构一个名字非常合理的方法。必须编译、测试、搜索定义并与项目现有用法对照。坑 4让 AI 顺手重构修 Bug 时顺手改命名、抽公共类、升级依赖会让 review 范围失控。小任务坚持最小 diff真正需要重构时单独立项、单独验证。坑 5只计算生成速度不计算审查成本模型 30 秒生成 300 行代码不代表节省时间。如果我花 90 分钟确认它的隐含假设不如一开始让它生成 30 行最小改动。效率应该按“可交付结果”计算。坑 6把敏感数据当普通上下文日志可能包含手机号、Token、订单号和内部地址配置文件可能包含密钥。无论使用云端还是本地工具都应先做数据分级和脱敏。生产写操作、权限变更和数据删除不能因为“AI 建议”就跳过审批。十二、一套我现在每天使用的提示结构与其收藏一百条“神级提示词”不如掌握一个稳定骨架角色你是我的 Java 代码审查搭档。 目标修复订单取消原因在历史数据下触发的空指针。 上下文 - JDK 17 / Spring Boot - 已确认数据库允许 cancellation_reason 为 null - 相关代码和失败测试见下方 - 不允许修改数据库结构。 任务 1. 先说明根因是否已被证据支持 2. 给出最小修改方案 3. 列出需要补的测试 4. 标记所有不确定项。 约束 - 只修改 CancellationView 和对应测试 - 不新增依赖 - 不改变 API 字段 - 不输出完整项目只给 diff 说明和必要代码。 验收 - null、空串、空白串均返回“未记录” - 原有非空原因保持不变 - 相关测试全部通过。这个结构的核心不是“角色”而是最后三部分任务、约束、验收。它把模型从自由写作拉回工程协作。十三、AI 时代Java 程序员真正要加强什么一周实验之后我反而更确定传统工程能力不会失效。AI 可以很快生成 Controller却不知道某个接口是否应该公开可以建议索引却不知道业务高峰期的写入压力可以补一堆测试却不知道哪个失败会让公司真正损失钱。模型越能写我们越需要判断需求是否被正确理解系统边界是否清楚数据和权限是否安全代码是否可验证、可回滚一次修改是否符合长期维护成本。换句话说程序员的价值正在从“亲手输入每个字符”转向“定义问题、组织上下文、控制变更和验证结果”。这不是少写代码而是让代码重新回到解决问题的位置。总结我用 7 天完成的不是一次工具迁移而是一次工作方式重排把需求写成可验收的任务把陌生代码整理成可核对的地图把代码生成限制为最小变更把 Debug 变成证据和假设的循环把测试从“补数量”变成“覆盖风险”把每次交付沉淀成下一次可复用的上下文。如果你也想尝试不必同时安装十个工具。明天上班时挑一个低风险、可验证的小任务整理一段日志、为一个纯函数补边界测试或者根据 diff 写提交说明。记录改造前后耗时也记录返工。当你能够持续回答“AI 做了什么、我验证了什么、结果为什么可信”它才真正进入了你的开发工作流。

相关新闻