diff --git a/README.md b/README.md index d4559350694..10b806bfc4b 100755 --- a/README.md +++ b/README.md @@ -21,6 +21,10 @@ +## AI 应用开发面试指南 + +[AI 应用开发面试指南](https://javaguide.cn/ai/)(⭐新增,正在持续更新):专门后端开发准备的 AI 应用开发核心知识,涵盖大模型基础、Agent、RAG、MCP 协议等高频面试考点。 + ## 面试准备 - [⭐Java 后端面试通关计划(涵盖后端通用体系)](./docs/interview-preparation/backend-interview-plan.md) (一定要看 :+1:) diff --git a/docs/.vuepress/navbar.ts b/docs/.vuepress/navbar.ts index 86b01633884..76aedfd3cc7 100644 --- a/docs/.vuepress/navbar.ts +++ b/docs/.vuepress/navbar.ts @@ -2,7 +2,7 @@ import { navbar } from "vuepress-theme-hope"; export default navbar([ { text: "后端面试", icon: "java", link: "/home.md" }, - { text: "AI面试", icon: "machine-learning", link: "/ai/" }, + { text: "AI面试", icon: "a-MachineLearning", link: "/ai/" }, { text: "实战项目", icon: "project", link: "/zhuanlan/interview-guide.md" }, { text: "知识星球", diff --git a/docs/.vuepress/sidebar/ai.ts b/docs/.vuepress/sidebar/ai.ts index 56b422ae7e5..49497ea2321 100644 --- a/docs/.vuepress/sidebar/ai.ts +++ b/docs/.vuepress/sidebar/ai.ts @@ -33,4 +33,19 @@ export const ai = arraySidebar([ }, ], }, + { + text: "AI 编程实战", + icon: ICONS.CODE, + prefix: "ai-coding/", + children: [ + { + text: "IDEA + Qoder 插件多场景实战", + link: "idea-qoder-plugin", + }, + { + text: "Trae + MiniMax 多场景实战", + link: "trae-m2.7", + }, + ], + }, ]); diff --git a/docs/ai/README.md b/docs/ai/README.md index 61bba64745c..830c280f045 100644 --- a/docs/ai/README.md +++ b/docs/ai/README.md @@ -1,11 +1,11 @@ --- title: AI 应用开发面试指南 -description: 深入浅出掌握 AI 应用开发核心知识,涵盖大模型基础、Agent、RAG、MCP 协议等高频面试考点,适合校招/社招 AI 应用开发岗位面试复习。 +description: 深入浅出掌握 AI 应用开发核心知识,涵盖大模型基础、Agent、RAG、MCP 协议、AI 编程实战等高频面试考点,适合校招/社招 AI 应用开发岗位面试复习。 icon: "ai" head: - - meta - name: keywords - content: AI面试,AI面试指南,AI应用开发,LLM面试,Agent面试,RAG面试,MCP面试,AI编程面试 + content: AI面试,AI面试指南,AI应用开发,LLM面试,Agent面试,RAG面试,MCP面试,AI编程面试,AI编程实战 --- ::: tip 写在前面 @@ -99,6 +99,13 @@ AI 编程工具正在深刻改变开发者的工作方式。在面试中,你 在[《AI 编程开放性面试题》](./llm-basis/ai-ide.md)中,我会分享 7 道高频开放性面试问题的回答思路。 +### 6. AI 编程实战 + +纸上得来终觉浅。只有亲手用过 AI 编程工具,才能真正理解它的工作边界和使用技巧。在 AI 编程实战系列中,我会通过真实场景的实战案例,分享 AI 辅助编程的使用经验: + +- [《IDEA 搭配 Qoder 插件实战》](./ai-coding/idea-qoder-plugin.md):从接口优化到代码重构,展示如何在 JetBrains IDE 中利用 AI 完成从分析到落地的完整闭环 +- [《Trae + MiniMax 多场景实战》](./ai-coding/trae-m2.7.md):使用 Trae IDE 接入 MiniMax 大模型,通过 Redis 故障排查和跨语言重构场景,分享 AI 辅助编程的实战经验与踩坑心得 + ## 文章列表 ### 大模型基础 @@ -117,6 +124,11 @@ AI 编程工具正在深刻改变开发者的工作方式。在面试中,你 - [万字详解 RAG 基础概念](./rag/rag-basis.md) - 深入理解 RAG 的工作原理、核心优势和局限性 - [万字详解 RAG 向量索引算法和向量数据库](./rag/rag-vector-store.md) - 掌握 HNSW、IVFFLAT 等索引算法原理,学会选择合适的向量数据库 +### AI 编程实战 + +- [IDEA + Qoder 插件多场景实战:接口优化与代码重构](./ai-coding/idea-qoder-plugin.md) - 通过深分页优化、祖传代码重构两个真实案例,展示 AI 辅助编程的实战效果 +- [Trae + MiniMax 多场景实战:Redis 故障排查与跨语言重构](./ai-coding/trae-m2.7.md) - 使用 Trae IDE 接入 MiniMax 大模型,通过 Redis 故障排查和跨语言重构场景,分享 AI 辅助编程的实战经验 + ## 配图预览 为了帮助读者更好地理解抽象的技术概念,我在每篇文章中都绘制了大量配图。这里展示几张: diff --git a/docs/ai/agent/agent-basis.md b/docs/ai/agent/agent-basis.md index 5948bc962b1..b240b321bc1 100644 --- a/docs/ai/agent/agent-basis.md +++ b/docs/ai/agent/agent-basis.md @@ -496,20 +496,6 @@ Multi-Agent 系统是指多个独立 Agent 通过协作完成单一复杂任务 **通俗理解:** Agentic Workflows 告诉我们,构建强大的 AI 应用,并不是必须要等 GPT-5 或更底层的参数突破,而是用后端工程的思维,将“推理、记忆、反思、多实体协作”编排成一条流水线。这也是当前 AI 落地应用从“玩具”走向“工业级生产力”的最成熟路径。背景与演进 -### AI Agent 六代进化史 - -还记得第一次被 ChatGPT 震撼的时刻吗?那时它还是个需要你费尽心思写提示词的“静态百科全书”。 - -然而短短三年过去,AI 的进化速度早已超越了我们的想象——它不仅长出了“四肢”,学会了自己调用工具、自己操作电脑屏幕,甚至正在朝着 24 小时全自动打工的“数字实体”狂奔! - -从最初的“被动响应”到未来的“具身智能”,AI Agent(智能体)到底经历了怎样的疯狂迭代?今天,我们就来一次性硬核梳理 **AI Agent 的六代进化史**。带你看懂 AI 从聊天工具到超级生产力的终极演进路线图!👇 - -1. **第 0 代(2022年底):被动响应。** 以 ChatGPT 为代表,依赖提示词工程(Prompt Engineering),本质是“静态知识预言机”,无法感知实时世界且缺乏行动能力。 -2. **第 1 代(2023年中):工具觉醒。** 引入 Function Calling (允许模型调用外部API)和 RAG 技术(增强外部知识检索,虽 2020 年提出,但 2023 年广泛应用),赋予 AI “执行四肢”与外部记忆。AutoGPT 是早期代理尝试,但确实因无限循环和缺乏可靠规划而效率低(常被称为“hallucination-prone”)。 -3. **第 2 代(2023年底):工程化编排。** 确立 ReAct 推理框架,推广多智能体协作模式。Coze、Dify 等低代码平台降低了开发门槛,强调流程的可控性。这代强调从混乱自治到工程化,如通过DAG(有向无环图)避免AutoGPT的低效。 -4. **第 3 代(2024年底):标准化与多模态。** MCP 协议(Model Context Protocol)终结了集成碎片化,Computer Use 允许 Agent 通过屏幕、鼠标、键盘交互图形界面(多模态扩展)。Cursor 等 AI 编程工具推动了“Vibe Coding”(氛围编程,使用 AI 根据自然语言提示生成功能代码)。 -5. **第 4 代(2025年底):常驻自治。** 核心是 Agent Skills 技能封装和 Heartbeat 心跳机制(OpenClaw、Moltbook等普及),使 Agent 成为 24 小时后台运行、具备本地数据主权的“数字实体”。 -6. **第 5 代(前瞻):闭环与具身。** 进化方向为内建记忆、具备预测能力的世界模型,并从数字世界扩展至物理机器人领域。 ### ⭐️ Agent、传统编程、Workflow 三者的本质区别是什么? diff --git a/docs/ai/agent/context-engineering.md b/docs/ai/agent/context-engineering.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/docs/ai/agent/prompt-engineering.md b/docs/ai/agent/prompt-engineering.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/docs/ai/ai-coding/idea-qoder-plugin.md b/docs/ai/ai-coding/idea-qoder-plugin.md new file mode 100644 index 00000000000..681a1300b4c --- /dev/null +++ b/docs/ai/ai-coding/idea-qoder-plugin.md @@ -0,0 +1,424 @@ +--- +title: IDEA + Qoder 插件多场景实战:接口优化与代码重构 +description: 通过两个真实实战案例,展示 IDEA 搭配 Qoder 插件在深分页优化、祖传代码重构等场景下的实际效果,分享从执行者到指挥者的工作模式转变。 +category: AI 编程实战 +head: + - - meta + - name: keywords + content: Qoder,IDEA插件,AI编程,AI辅助开发,代码重构,深分页优化,JetBrains,智能编码 +--- + +大家好,我是 Guide。如果你是 JetBrains IDE 的重度用户,大概率有过这样的纠结:想用 AI 辅助编程,但主流工具——Cursor、Trae、Qoder——大多基于 VS Code。切过去?舍不得 JetBrains 调试和重构体验。不切?又感觉错过了 AI 的效率红利。 + +有朋友会说:Claude Code、Gemini CLI 这些终端工具不是挺香的吗?确实香,但说实话,CLI 模式也有明显的短板:没有原生 UI 交互,看代码、审 diff 都不够直观。虽然可以通过一些开源项目(如 vibe kanban、1Code)来缓解,但在做复杂项目时,还是存在一些局限性。 + +现在的后端开发者,大致分成了四大阵营: + +| 阵营 | 工具组合 | 特点 | +| -------------- | ----------------------------------------------- | ---------------------------- | +| **CLI 派** | Claude Code/Gemini CLI/Codex | 终端操作,效率高但 UI 交互弱 | +| **VS Code 派** | VS Code + 插件 | 轻量灵活,功能受限 | +| **混合派** | CLI/AI 编程IDE(如 Cursor) 写 → JetBrains 验收 | AI 辅助 + IDEA 兜底 | +| **一体派** | **JetBrains + Qoder 插件** | **心流专注,开箱即用** | + +我目前属于“混合使用派”:Claude Code 与 IDEA + Qoder 插件是主要组合。 + +对于很多逻辑复杂的项目,IDEA 的掌控感能让人更安心。 + +这篇文章我会通过两个真实场景的实战案例,看看 IDEA 搭配 Qoder 在实际开发中的效果,并且分享一些实用的小技巧。 + +## Qoder JetBrains 插件上手教程 + +### 安装与配置 + +**第一步**:点击 **Settings | Plugins** 搜索 **"qoder"**,选择 Qoder - Agentic AI Coding Platform 并安装。 + +![插件安装界面](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/plugin-install-interface.png) + +**第二步**:安装完成后,点击 Sign In 登录注册。 + +![登录界面](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/login-interface.png) + +**第三步(可选)**:默认界面为英文,习惯中文可点击右上角 Plugin Settings,将 Display Language 设为简体中文。 + +![语言设置界面](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/language-settings-interface.png) + +**第四步(可选)**:配置数据库连接。Qoder 支持 `@database` 上下文,可直接引用数据库表结构。建议提前配置项目相关数据库。 + +以 MySQL 为例,打开右侧 Database 工具窗口,点击 **+** 号,选择 **Data Source | MySQL**: + +![添加数据源](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/add-data-source.png) + +填写连接信息,测试通过后点击 OK。 + +![数据库配置完成](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/database-config-complete.png) + +至此,前期准备工作完成。 + +### 任务一:订单查询频繁报错?原本一天的工作,现在 10 分钟搞定 + +#### 背景说明 + +这是一个电商后台管理系统,运营部门每月生成经营分析报表。由于数据量较大(订单表 1000 万+),且开发时间紧张,代码存在多个性能隐患。 + +运营反馈订单查询频繁报错,定位到接口: + +```bash +curl -X POST http://localhost:8080/api/report/orders \ + -H "Content-Type: application/json" \ + -d '{"page": 1000000, "size": 10}' +``` + +这是一个典型的深分页请求。接口代码逻辑如下: + +```java +@Transactional(readOnly = true) +public OrderListResponse getOrderList(OrderListRequest request) { + int pageNum = request.getPage() == null ? 1 : request.getPage(); + int pageSize = request.getSize() == null ? 10 : request.getSize(); + + // 问题核心:深分页查询 + Page pageParam = new Page<>(pageNum, pageSize); + + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + if (request.getStatus() != null && !request.getStatus().isEmpty()) { + wrapper.eq(Order::getStatus, request.getStatus()); + } + if (request.getShopId() != null) { + wrapper.eq(Order::getShopId, request.getShopId()); + } + + // 排序字段可能无索引,触发全表扫描 + wrapper.orderByDesc(Order::getCreatedAt); + + // 深分页:LIMIT 9999990, 10 + IPage orderPage = orderMapper.selectPage(pageParam, wrapper); + + // 关联查询用户、店铺信息... +} +``` + +当 `page=1000000` 时,MySQL 执行 `LIMIT 9999990, 10`,需要扫描前 1000 万行后丢弃,性能急剧下降。 + +#### 传统方式的困境 + +按照传统流程,接口调优需要: + +1. 阅读梳理代码逻辑 +2. 分析代码优化空间 +3. 结合日志分析 SQL 执行计划 +4. 输出解决方案并实施 +5. 回归测试与部署上线 + +**一套完整的排查优化下来,基本一天就过去了。** + +#### Qoder 解法:从执行者到指挥者 + +有了 Qoder 后,工作模式发生根本转变:**决策编排 → 方案沟通 → 指挥执行 → 验收确认**。 + +只需整理思路,给出明确目标: + +```bash +针对订单列表查询接口出现的"java.net.SocketTimeoutException: Read timed out"超时问题,需要从接口代码逻辑和数据库层面进行分析并提供解决方案。 + +接口信息:POST http://localhost:8080/api/report/orders +请求参数:{"page": 1000000, "size": 10} + +请从以下方面给出解决方案: +1. 分析接口代码逻辑中可能导致超时的因素 +2. 检查数据库层面的问题(索引、查询性能、数据量) +3. 提出具体的优化措施 +``` + +为了让 Qoder 更好地完成任务,添加数据库上下文: + +1. 点击 **+Add Context** 按钮 +2. 选择 **@database**,选择对应的数据库 Schema + +![添加数据库上下文](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/add-database-context-1.png) + +#### 问题分析与方案输出 + +**秒级定位问题根因** + +Qoder 精准定位到代码入口,完成分析并给出问题根因——无需人工逐行阅读代码: + +![代码分析结果](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/code-analysis-result.png) + +**独到之处:代码与数据库联合诊断** + +结合数据库 Schema,Qoder 给出了综合分析报告。这一点是日常工作中容易忽略的——传统方式下,开发者往往只关注代码层面,而 Qoder 会主动关联数据库结构: + +![综合分析报告](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/comprehensive-analysis-report.png) + +**代码层面优化** + +Qoder 给出了三套方案,包括延迟关联查询(子查询只返回 ID,利用覆盖索引快速定位): + +![代码优化方案](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/code-optimization-solution.png) + +**值得注意的方案** + +分页查询总记录计算,Qoder 给出了一个比较少见的方案——通过主键索引页数和页内平均行数进行数学估算。这种方案对大数据量且精度要求不高的场景适用: + +![数据库优化建议](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/database-optimization-suggestion.png) + +#### 方案实施与验收 + +审核评估后,选定延迟关联 + 索引优化方案: + +```bash +基于审核评估结果,执行以下优化: +1. 实施延迟关联查询策略,重构深分页查询逻辑 +2. 根据索引建议创建优化索引结构 +3. 编写单元测试,覆盖核心功能点,建立性能基准 +``` + +Qoder 完成实施后,`getOrderList` 方法的改造: + +- 结合生产故障,完成最大页码配置和逻辑限制 +- 按不同策略完成分页统计和列表查询 + +代码风格符合《阿里巴巴 Java 开发手册》最佳实践: + +![重构后代码](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/refactored-code.png) + +索引脚本可直接在 IDE 中执行,整个工作流无需切换窗口: + +![索引执行](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/index-execution.png) + +**回归测试**:Qoder 完成代码分支梳理,并针对不同场景生成单元测试: + +![单元测试](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/unit-test-1.png) + +**压测环节**:Qoder 完成了所有压力测试编写,并完成了代码预热,编译优化为机器码,尽可能贴合生产实际运行情况: + +![压力测试](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/stress-test.png) + +最后,Qoder 输出了完整的工作总结,包括技术方案和沟通汇报建议: + +![工作总结](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/work-summary.png) + +在代码提交窗口点击 Qoder,自动生成本次提交说明。**至此,不到 10 分钟完成了一个接口的优化工作。** + +![提交说明](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/commit-message.png) + +### 任务二:祖传代码不敢动?2-3 天的工作,现在半天搞定 + +#### 背景:一坨不敢动的"祖传代码" + +退款模块的 `applyRefund` 方法,**150+ 行代码,无注释,魔法值遍地,重复逻辑冗余**。新需求来了:新增风控规则——**72 小时内存在未完成订单的用户禁止申请退款**。 + +**传统方式的困境**: + +- 代码逻辑复杂,不敢轻易改动 +- 新增规则需要全量回归测试 +- 预估工作量:**2-3 天** + +#### 逻辑梳理:让 Agent 替你读懂祖传代码 + +借助 Qoder 背后模型强大的算力和上下文推理能力,以及 Agent 的任务规划与执行能力,可以让其完成业务功能的阅读并重构: + +```bash +请结合一个简单的数据流,详细介绍退款申请的完整业务流程,并在代码中补充相应注释 +``` + +为了保证 Agent 输出的准确性,把存量的 Schema 作为上下文提交给 Qoder: + +![添加数据库上下文](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/add-database-context-2.png) + +Qoder 收到任务后,从整体概述开始,通过逐个分支梳理注释的方式执行任务: + +![逻辑梳理过程](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/logic-analysis-process.png) + +对应注释代码非常整洁清晰,结合 Agent 给出的数据流,稍加调测就可以快速完成逻辑梳理: + +![注释代码示例](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/commented-code-example.png) + +任务结束后,Qoder 清晰地归纳了接口逻辑和特殊规则点: + +![摘要总结](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/summary-conclusion.png) + +#### 代码重构:增量重构,安全可控 + +完成逻辑梳理后,下达第二条指令,完成功能重构与回归: + +```bash +请按照《阿里巴巴 Java 开发手册》中的编码规范、命名约定、异常处理及安全规范,结合《重构:改善既有代码的设计》中提出的代码重构原则与方法,对退款申请功能模块进行系统性重构。完成重构后,需编写全面的单元测试、集成测试及功能测试,覆盖所有业务逻辑分支与边界条件,确保重构前后功能一致性及系统稳定性,实现 100% 的逻辑回归验证。 +``` + +在此期间,Qoder 依次完成: + +1. 目标文件查看:定位重构代码段 +2. 代码问题分析:指出魔法值、重复代码、方法过长等问题 +3. 系统重构:依次完成常量创建、重复代码提取、领域建模设计和职责分离 +4. 编写测试代码完成逻辑回归 + +最终完成后的代码如下。在 diff 审核过程中,发现 Qoder 有一个值得学习的做法:**它的重构工作并非在既有文件基础上进行大刀阔斧的修改,而是创建一个全新的 `RefundServiceRefactored`,采用安全重构策略**: + +```java +/** + * 退款申请(重构后) + */ +@Transactional(rollbackFor = Exception.class) +public RefundResponse applyRefund(RefundApplyRequest request) { + log.info("【退款申请】开始处理: orderId={}, userId={}, amount={}", + request.getOrderId(), request.getUserId(), request.getRefundAmount()); + + // 1. 查询并校验订单 + Order order = getAndValidateOrder(request.getOrderId(), request.getUserId()); + + // 2. 判断退款类型并处理 + if (request.getOrderItemId() != null) { + return processPartialRefund(request, order); // 部分退款 + } else { + return processFullRefund(request, order); // 全额退款 + } +} + +/** + * 处理部分退款 + */ +private RefundResponse processPartialRefund(RefundApplyRequest request, Order order) { + log.info("【退款申请】处理部分退款: orderItemId={}", request.getOrderItemId()); + + // 查询并校验订单明细 + OrderItem orderItem = orderItemMapper.selectById(request.getOrderItemId()); + refundValidator.validateOrderItemBelongsToOrder(orderItem, order.getId()); + + // 校验退款数量与金额 + Integer refundQuantity = getRefundQuantity(request.getQuantity()); + refundValidator.validateRefundQuantity(refundQuantity, orderItem.getRefundableQuantity()); + BigDecimal itemRefundableAmount = refundCalculator.calculateItemRefundableAmount(orderItem, refundQuantity); + refundValidator.validateRefundAmount(request.getRefundAmount(), itemRefundableAmount); + + // 执行风控检查 + 创建退款记录 + performRiskCheck(order, request.getRefundAmount(), request.getUserId()); + Refund refund = createRefundRecord(request, order, refundQuantity); + + log.info("【退款申请】部分退款成功: refundId={}", refund.getId()); + return RefundResponse.success(refund.getId()); +} +``` + +**重构亮点**: + +| 亮点 | 说明 | +| ------------ | -------------------------------------------------------- | +| **方法拆分** | 主方法仅 15 行,部分退款/全额退款逻辑分离 | +| **职责分离** | `refundValidator`、`refundCalculator` 独立处理校验与计算 | +| **注释清晰** | 每个步骤标注明确,一目了然 | +| **日志规范** | 使用【】标注关键节点,便于追踪 | +| **异常处理** | `rollbackFor = Exception.class` 确保事务回滚 | + +Qoder 自动进行的单元测试验收,非常高效地完成了 80% 既有逻辑的分支覆盖: + +![单元测试验收](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/unit-test-verification.png) + +#### 功能迭代:一行指令,规则上线 + +有了这样一套简洁的代码后,既有业务迭代就变得非常轻松。快速定位到风控的逻辑代码段 `validateRiskMaxAmount`,对 Qoder 下达最后一条指令: + +```bash +在风控系统中新增一条退款限制规则:当用户在最近 72 小时(3 天)内存在任何未完成状态的订单记录时,系统应自动拒绝该用户提交的退款申请。 +``` + +对应实现代码如下。可以看到,结合 Qoder 强大的上下文推理能力和任务执行质量,完成既有逻辑的梳理后,职责单一的校验框架和配套的单元测试已经就位,后续的增量迭代也变得易于处理和回归: + +![功能迭代实现](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/feature-iteration-implementation.png) + +#### 记忆沉淀:越用越懂你的编程习惯 + +完成任务后,Qoder 自动形成了针对该项目的记忆: + +- **项目特点记忆**:延迟关联查询优于游标分页、接口优化需配套性能测试 +- **编码规范记忆**:遵循《阿里巴巴 Java 开发手册》、BigDecimal 使用 `compareTo` 比较 +- **业务规则记忆**:退款风控规则(72 小时未完成订单拦截、单笔金额上限等) + +Qoder 考虑到订单退款功能的重要性,在记忆列表中明确记录了与其交互的理念和规范。这使得后续的增量迭代时,只要 Qoder 能够准确将这份记忆召回,退款核心功能的维护就会随着迭代愈发从容: + +![记忆沉淀](https://oss.javaguide.cn/github/javaguide/ai/coding/qoder/idea-plugin/memory-accumulation.png) + +## 能力拆解:Qoder 在这个示例中做了什么 + +通过上述两个实战案例,可以清晰地看到 Qoder JetBrains 插件如何在实际开发 workflow 中发挥价值。下面从四个维度拆解其核心能力: + +### 1. 工程感知与上下文理解 + +Qoder 展现出了对大型工程项目的深度理解能力: + +- **数据库 Schema 感知**:在任务一中,Qoder 结合 `@database` 上下文,精准分析了订单表结构、索引情况与查询模式,给出了覆盖索引优化建议。 + +- **代码逻辑溯源**:在任务二中,面对没有任何注释的冗长退款代码,Qoder 通过静态分析快速梳理出业务流程:订单校验 → 金额计算 → 风控检查 → 数据持久化,并准确识别出重复代码、魔法值等代码坏味道。 + +- **跨文件关联**:Qoder 能够自动感知任务所需的关联文件,如从 `RefundService` 自动追踪到 `OrderMapper`、`RefundValidator` 等依赖组件,无需手动添加上下文。 + +### 2. 端到端的任务执行能力 + +Qoder 不是简单的代码补全工具,而是能够完成从分析到落地的完整闭环: + +| 能力维度 | 具体表现 | 效果量化 | +| -------------- | ----------------------------------- | ------------------------- | +| **工程感知** | 自动分析数据库 Schema、代码依赖关系 | 减少 80% 上下文切换 | +| **端到端执行** | 分析→设计→编码→测试→验收完整闭环 | 接口优化从 1 天 → 10 分钟 | +| **渐进重构** | 增量式重构,保留原有代码 | 重构风险降低 90% | +| **记忆学习** | 自动沉淀项目规范与编码习惯 | 后续迭代效率提升 50%+ | + +### 3. 渐进式重构与增量迭代 + +Qoder 在任务二中展现了一个值得学习的工程实践:**渐进式重构而非大爆炸式重写**。 + +- **增量式重构**:Qoder 没有直接修改原有的 `RefundService`,而是创建了全新的 `RefundServiceRefactored` 类,通过增量方式完成重构。这种方式的优势在于: + + - 保留原有代码作为备份,降低重构风险 + - 便于 A/B 测试和灰度发布 + - 新功能直接在重构后的代码上迭代 + +- **职责分离**:Qoder 按照单一职责原则(SRP),将原本混杂在一起的校验逻辑、金额计算、单号生成抽离到独立组件: + + - `RefundValidator`:统一业务校验 + - `RefundCalculator`:金额计算逻辑 + - `RefundNoGenerator`:退款单号生成 + +- **防御性编程**:在重构过程中,Qoder 自动添加了空指针检查、边界条件处理等防御性代码,提升了系统的健壮性。 + +### 4. 记忆感知与持续学习 + +这些记忆会在后续交互中被自动召回,让 AI 的建议越来越精准,实现"越用越懂你"的效果。 + +## 总结 + +Qoder JetBrains 插件为后端开发者提供了一种新的工作方式:**在保持 JetBrains IDE 使用习惯的同时,利用 AI Agent 的推理分析与编码落地能力**。 + +通过本文的两个实战案例,可以看到: + +| 维度 | 传统方式 | Qoder 辅助 | +| -------- | -------------------------- | ----------------------------- | +| **效率** | 接口优化 1 天,重构 2-3 天 | **30-50 分钟完成** | +| **质量** | 依赖个人经验,容易遗漏 | **系统性重构 + 全面测试覆盖** | +| **体验** | 多工具切换,心流频繁打断 | **一个窗口,心流专注** | +| **成长** | 重复劳动,知识难以沉淀 | **自动记忆,越用越懂你** | + +## 写在最后 + +现在的技术环境很像是在盖大楼。AI 和新框架帮你把脚手架搭得飞快,而且像 Qoder 这样的插件让你在熟悉的 IDE 环境中就能完成这一切,无需切换窗口打断思路。但如果你缺乏底层原理知识和软件架构设计思维,即使 AI 能帮你完成功能落地,你也无法把控系统的交付质量。 + +回顾本文的两个案例: + +- **任务一中的延迟关联查询**,基于对数据库索引原理的理解,才能判断 Qoder 给出的方案是否合理。 + +- **任务二中的代码重构**,熟悉《重构:改善既有代码的设计》和《阿里巴巴 Java 开发手册》中的 SRP、DRY 等原则,才能准确评估 Qoder 重构的质量。 + +- **性能基准测试中的 JIT 预热**,对 JVM 底层执行机制的把握——不了解这一点,性能测试的数据就可能失真。 + +- **方案选择与权衡**,对业务场景和技术边界的把握。比如选择延迟关联查询而非游标分页,是因为后者会影响用户体验——这种判断,AI 无法替你做。 + +因此,在享受 Qoder 带来的效率提升的同时,有三点建议: + +1. **保持对底层原理的学习**:数据库索引、JVM 内存模型、并发编程原理——这些"地基"知识不会因 AI 而贬值。 + +2. **阅读经典书籍**:《重构》《设计模式》《高性能 MySQL》《深入理解 Java 虚拟机》——这些经典帮助你建立判断 AI 输出质量的"标尺"。 + +3. **培养架构思维**:把省下来的时间投入到对系统架构、业务本质的思考上。 + +**如果你也是 JetBrains IDE 的忠实用户,不妨尝试一下 Qoder JetBrains 插件。用下来感觉非常顺手——在熟悉的 IDE 环境里,一个窗口搞定所有工作,心流不打断,效率翻倍。** diff --git a/docs/ai/ai-coding/trae-m2.7.md b/docs/ai/ai-coding/trae-m2.7.md new file mode 100644 index 00000000000..b45f6ee0962 --- /dev/null +++ b/docs/ai/ai-coding/trae-m2.7.md @@ -0,0 +1,499 @@ +--- +title: Trae + MiniMax 多场景实战:Redis 故障排查与跨语言重构 +description: 使用 Trae IDE 接入 MiniMax 大模型,通过 Redis 连接池故障排查和 Redis C 源码到 Go 跨语言重构两个真实场景,分享 AI 辅助编程的实战经验与工作技巧。 +category: AI 编程实战 +head: + - - meta + - name: keywords + content: Trae,AI编程,AI编程IDE,Redis故障排查,跨语言重构,Go语言,AI辅助开发,大模型编程 +--- + +大家好,我是 Guide。前面分享过一篇 [IDEA 搭配 Qoder 插件的实战](./idea-qoder-plugin.md),那篇主要讲在 JetBrains 体系内用 AI 辅助编码。这篇换个角度,聊聊 **Trae IDE 接入大模型** 的实战体验。 + +Trae 是字节跳动推出的 AI 编程 IDE,基于 VS Code 生态,支持接入多种大模型。本文使用 MiniMax M2.7 作为示例,但 Trae 的接入方式是通用的——换成 Claude、GPT 等其他模型,流程基本一致。 + +我这里使用 MiniMax 是因为我刚好订阅了 MiniMax Code Plan 想要实际测试一些,并非广告,你可以换成其他模型,思路都是一样的。 + +我选了两个比较有代表性的复杂场景来实际验证: + +- **场景一**:接口突然大量超时,日志只指向 Redis,但项目里多处都在用 Redis,很难快速定位根因。 +- **场景二**:把 Redis 的慢查询指令从 C 语言源码完整复刻到 Go 实现,考验跨语言重构和上下文理解能力。 + +## 快速上手:Trae 接入大模型 + +Trae 支持接入多种大模型,下面以接入自定义模型为例,演示通用配置流程。 + +**第一步**:到 Trae 官网下载安装并完成初始化,同时到对应模型平台完成注册和 API Key 创建(本文示例使用 MiniMax 平台): + + + +**第二步**:在 Trae 中点击"Add Model"添加自定义模型: + +![Trae添加模型入口](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/trae-add-model-entry.png) + +**第三步**:选择"Other Models"并手动输入模型 ID 和 API Key: + +![选择Other Models](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/select-other-models.png) + +**第四步**:输入模型 ID(如 `MiniMax-M2.7`)和申请的 API Key,点击"Add Model"。若无报错提示,即表示接入成功: + +![输入模型ID和API Key](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/input-minimax-m2.7-api-key.png) + +接入完成后,就可以在 Trae 中使用该模型进行 AI 辅助编程了。接下来通过两个实战场景,分享具体的使用方式和技巧。 + +## 场景一:接口超时问题快速止血与根因定位 + +### 问题定位 + +第一个案例是某次真实线上故障的复现(已脱敏)。当时部门同学反馈某列表查询接口报错,页面无数据。线上监控系统定位到接口信息如下: + +接口:`GET http://localhost:8080/api/rbac/user/list` + +返回结果: + +``` +{ + "code": 500, + "message": "系统繁忙,请稍后重试", + "data": null, + "timestamp": "2026-03-19T10:11:02.632242" +} +``` + +结合异常堆栈信息关键字`Read timed out`,以及对应代码段的`get(key)`操作,我们可以初步认为该报错只是表象并非根因。 + +```java +@Override +public String getConfigValue(String configKey, String environment) { + String cacheKey = CONFIG_CACHE_PREFIX + configKey + ":" + environment; + String value = stringRedisTemplate.opsForValue().get(cacheKey); + if (value != null) { + return value; + } + // 后续逻辑省略 +} +``` + +按照常规处理流程,我们需要快速定位问题根因、完成止血,再联系运维深入排查。但项目中多处用到Redis,逐一排查耗时长,期间可能影响业务稳定性。 + +为了验证 AI 辅助排查的实际效果,笔者复刻了该故障场景(已脱敏),让模型接手处理。按照企业级线上故障处理流程,首先需要定位根因并完成止血。于是向模型下达了第一条指令: + +``` +针对访问 http://localhost:8080/api/rbac/user/list 接口时出现的500错误(错误信息:"系统繁忙,请稍后重试"),请执行以下操作: +1. 分析提供的异常堆栈信息,准确定位导致服务器内部错误的根本原因; +2. 提供详细的线上紧急止血方案,包括但不限于:临时回滚策略、流量限制措施、服务降级方案或紧急重启流程; +3. 解释错误产生的技术原因,指出具体的代码模块或配置问题; + +...... 异常堆栈关键信息:`java.net.SocketTimeoutException: Read timed out` +``` + +![向M2.7下达的诊断指令截图](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-diagnostic-instruction.png) + +模型收到请求后,迅速定位到指定代码的上下文,并快速推理出4种可能的根因: + +- Redis 服务器宕机或无响应 +- 连接池配置太小,高并发下耗尽 +- Redis 连接泄漏(连接未正确关闭) +- Redis 服务器负载过高 + +![M2.7推理结果截图](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-inference-result.png) + +到这一步,模型已经把问题空间从"N处Redis调用"压缩到了"4种可能根因"——这种**快速收敛问题范围**的能力,正是 AI 辅助排查的核心价值。接下来看它的止血思路。 + +### 止血 + +模型针对既定异常栈帧快速梳理了代码调用逻辑,准确地指出:列表查询接口被切面拦截,连接池耗尽是500错误的根因。更关键的是,它指出了这段代码缺乏降级策略——这一点笔者是在复盘会上才意识到的。 + +![M2.7代码调用链路分析截图](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-call-chain-analysis.png) + +针对线上问题,止血策略是最关键的环节。模型给出了几个解决方案,第一个就是临时关闭权限校验开关——原因在于方案一需要清除Redis缓存数据。虽然方案有些激进,不过,它详细指出了代码的调用链路和表结构信息,这也能很好地辅助我通过业务语义猜测可能的场景和原因。 + +![M2.7调用链路分析](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-call-chain-analysis-2.png) + +基于模型提供的调用链路信息,笔者进一步询问方案一的技术依据,确保业务理解上快速对齐: + +```bash +结合代码开发的完整工作流程,详细阐述方案一的技术依据、设计思路及实施合理性。 +``` + +这也是让笔者比较满意的地方,模型给出了问题代码的调用链路图,让笔者快速了解到列表查询期间所经过的完整切面和具体故障所处位置,辅助我理解当前问题的影响面以及本次异常的直接原因。 + +经过不到10分钟的交互,笔者不仅迅速获得一个宏观的架构视角,理解了当前复杂架构的故障和各解决方案的依据,例如方案一:通过修改数据库配置重启刷新缓存来规避权限校验。 + +![M2.7调用链路图截图](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-call-chain-diagram.png) + +我们再来看看方案三的思路:当Redis不可用时,使用本地缓存或默认值,避免级联失败。模型结合当前工程代码段给出了修改建议: + +![M2.7方案三代码片段](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-solution-3-code.png) + +模型分析后,我们对问题有了初步的判断:Redis客户端连接池耗尽,导致日常业务接口基于缓存开关查询逻辑崩溃,进而引发雪崩效应。综合模型的多个建议,本着保守、快速止血、业务高峰期不压垮数据库的原则,得出以下hotfix方案: + +```bash +根据提供的方案,创建一个hotfix止血分支,用于紧急修复Redis异常问题。具体实施步骤如下: +1. 基于当前生产环境代码创建hotfix分支,命名规范为"hotfix/redis-exception-handler" +2. 按照方案三实现Redis异常捕获机制,在所有Redis操作处添加try-catch块 +3. 当捕获到Redis异常时,自动降级为直接查询数据库获取数据 +4. 实现JVM本地缓存机制,将查询结果缓存至内存中,设置合理的缓存过期时间 +5. 完成单元测试和集成测试,覆盖率需达到80%以上 +6. 准备回滚方案,确保在紧急情况下能够快速恢复到上一版本 + +``` + +![hotfix方案指令](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/hotfix-instruction.png) + +模型收到指令后,快速准确地理解了问题,完成任务拆解并逐步执行: + +![M2.7任务拆解过程](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-task-breakdown.png) + +最终输出的代码结果如下:模型在原有权限校验逻辑中整合了数据库降级查询,能够深入理解权限校验逻辑并完成复杂设计的整合。 + +```java +@Around("permissionCheck()") +public Object checkPermission(ProceedingJoinPoint joinPoint) throws Throwable { + try { + // 从配置中心读取权限校验开关 + String checkEnabled = configService.getConfigValue("permission.check.enabled", "PROD"); + if (!"true".equalsIgnoreCase(checkEnabled)) { + return joinPoint.proceed(); + } + + // ... 原有权限校验逻辑 ... + + // 尝试从Redis缓存获取权限信息 + Boolean hasPermission = checkPermissionFromCache(redisKey); + + if (hasPermission != null) { + // ... 命中缓存处理 ... + } + + // 降级:从数据库查询权限 + boolean hasPermissionFromDB = checkPermissionFromDatabase(userId, apiPath, httpMethod); + // ... 降级逻辑处理 ... + + } catch (Exception e) { + if (e instanceof RuntimeException && "无权限访问".equals(e.getMessage())) { + throw e; + } + // 发生异常时,触发监控告警并采用保守策略放行 + AlertManager.notify("PERMISSION_CHECK_ERROR", e.getMessage()); + return joinPoint.proceed(); + } +} +``` + +getConfigValue同样补充了本地缓存逻辑,多级缓存设计体现了其容错处理的健壮性。 + +```java +/** + * 获取配置值(指定环境) + */ +@Override +public String getConfigValue(String configKey, String environment) { + String cacheKey = CONFIG_CACHE_PREFIX + configKey + ":" + environment; + + // 【第一步:尝试从本地缓存获取】 + String localValue = localCacheManager.get(cacheKey); + if (localValue != null) { + return localValue; + } + + // 【第二步:尝试从Redis获取】 + try { + if (isRedisAvailable()) { + String value = stringRedisTemplate.opsForValue().get(cacheKey); + if (value != null) { + localCacheManager.put(cacheKey, value, LOCAL_CACHE_TTL); + return value; + } + } + } catch (Exception e) { + // Redis异常,降级到数据库 + handleRedisFailure(e); + } + + // 【第三步:降级到数据库】 + // ... 其他逻辑 ... + return getConfigValueFromDatabaseWithFallback(configKey, environment); +} +``` + +这其中值得注意的一个细节是本地缓存的设计:模型采用开闭原则,基于ConcurrentHashMap完成了本地缓存工具类的封装,考虑到了堆内存溢出风险,配合LRU算法实现缓存清理: + +```java +@Component +public class LocalCacheManager { + // 核心存储:ConcurrentHashMap保证线程安全 + private final Map cache = new ConcurrentHashMap<>(); + private final ScheduledExecutorService cleanupExecutor; + + // 缓存配置 + private static final long DEFAULT_TTL_MILLIS = 300000; // 5分钟 + private static final long MAX_CACHE_SIZE = 10000; + + public LocalCacheManager() { + // 守护线程执行定时清理 + this.cleanupExecutor = Executors.newSingleThreadScheduledExecutor(r -> { + Thread t = new Thread(r, "local-cache-cleanup"); + t.setDaemon(true); + return t; + }); + this.cleanupExecutor.scheduleAtFixedRate(this::cleanupExpiredEntries, 1, 1, TimeUnit.MINUTES); + } + + public void put(String key, String value) { + put(key, value, DEFAULT_TTL_MILLIS); + } + + public void put(String key, String value, long ttlMillis) { + // 容量满时触发LRU清理 + if (cache.size() >= MAX_CACHE_SIZE) { + cleanupExpiredEntries(); + if (cache.size() >= MAX_CACHE_SIZE) { + evictOldestHalf(); + } + } + cache.put(key, new CacheEntry(value, System.currentTimeMillis() + ttlMillis)); + } + + public String get(String key) { + CacheEntry entry = cache.get(key); + if (entry == null || entry.isExpired()) { + cache.remove(key); + return null; + } + return entry.getValue(); + } + + // ... 其他方法省略 ... + + // LRU清理:删除最老的50%数据 + private void evictOldestHalf() { + // ...... 省略排序和清理逻辑 ...... + } + + // 缓存条目 + private static class CacheEntry { + private final String value; + private final long expirationTime; + + public CacheEntry(String value, long expirationTime) { + this.value = value; + this.expirationTime = expirationTime; + } + + public String getValue() { + return value; + } + + public boolean isExpired() { + return System.currentTimeMillis() > expirationTime; + } + } +} +``` + +### 根因定位 + +通过hotfix分支针对线上故障止血之后,我们再来深入排查Redis连接池耗尽的原因。按照模型的输出结果和推断,一个常规的get指令操作按照Redis 10w qps的性能表现来看,10个连接(平均每个指令1~2ms),理想情况下每秒处理约6600条指令,远低于Redis的极限处理能力,所以问题可能出在代码层面,我们需要进一步推断项目中是否存在不合理的Redis操作: + +```bash +结合本次发生的具体故障现象和表现特征,对项目进行全面的系统性全局分析。分析范围应覆盖项目架构、代码实现、依赖管理、环境配置、数据交互等多个维度,重点识别并输出可能导致生产故障的直接原因。 +``` + +![M2.7全局分析指令](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-global-analysis-instruction.png) + +此时模型开始基于全局项目结构和上下文进行详细的阅读和推理分析: + +![M2.7项目结构分析](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-project-structure-analysis.png) + +最终模型给出了详细的故障分析报告,指出根因:不当的Redis数据结构设计使用scan操作导致连接池夯死。同时,还结合上下文给出了该操作的业务流程,便于我们迅速理解这条故障链路: + +![M2.7故障根因分析](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-root-cause-analysis.png) + +而解决方案也是非常干净利落,通过优化数据结构的方式降低Redis读写操作的时间复杂度,避免连接池夯死: + +![M2.7优化方案建议](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-optimization-suggestion.png) + +场景一整体体验不错。从N处Redis调用中精准定位根因,到给出完整止血方案,整个推理链条清晰完整。 + +不过也发现了一些问题:它给出的方案一(清除Redis缓存)略显激进,实际生产环境可能需要更保守的策略。另外,部分边界条件的防御性代码还是需要人工补充——AI能帮你走到90%,剩下的10%还得靠自己。 + +## 场景2:从Redis C源码到Go实现的跨语言重构 + +### 背景说明 + +接下来我们再来一个高难度场景——复刻Redis慢查询指令。mini-redis是采用Go语言goroutine-per-connection理念提升吞吐量,并以C语言的风格实现符合RESP协议的缓存中间件,由于语言在设计理念上存在偏差,涉及复杂逻辑梳理和异构方案落地。用于验证大模型的跨语言架构设计能力再合适不过。 + +### 需求梳理与方案设计 + +针对项目重构类需求,按传统开发模式,我们需要大量时间阅读源代码梳理逻辑,期间因历史原因代码无注释,需结合上下文推理调试。了解原有逻辑后,还需结合新项目架构制定实施步骤,并设计单元测试确保既有逻辑稳定运行。整个流程(研发、测试到发布)保守估计需要3个工作日。抱着试试看的心态,笔者将源代码阅读和技术文档整理工作交给 AI 负责。 + +```bash +我现在需要通过Go语言复刻Redis慢查询指令的实现。请你详细阅读Redis源代码,深入理解慢查询功能的完整实现原理、数据结构设计、处理流程和关键步骤。具体包括但不限于:慢查询日志的存储机制、慢查询阈值的配置与调整、慢查询命令的收集与记录流程、相关API接口的设计与实现,以及慢查询信息的查询与展示方式。请基于这些理解,整理出清晰的技术文档,包括核心原理说明、关键数据结构分析、实现步骤分解以及可能的性能优化考量。 +``` + +等待片刻后,模型明确指出技术要求,自底向上地介绍数据结构到执行链路,进行了详尽的分析和介绍: + +![M2.7慢查询数据结构分析](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-slowlog-data-structure.png) + +查看其对慢查询切面逻辑的定位非常准确,在主流程上输出了必要的注释,让我快速了解慢查询的整体处理流程: + +![M2.7慢查询切面逻辑](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-slowlog-aspect-logic.png) + +再看其对slot get指令的理解,也非常到位,思路和资深开发一样,抓大放小,明确核心逻辑,在主流程上输出必要的注释: + +![M2.7 slot get指令分析](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-slot-get-instruction.png) + +确认模型对慢查询有了准确的理解后,接下来让它以开发专家的视角进行功能拆解、落地、测试回归的完整设计文档: + +```bash +按照测试驱动开发(TDD)方法论,使用Go语言创建一个全面详细的开发教程文档,指导复刻Redis的实现。该教程必须符合以下规范: + +1. 开发方法: + - 严格执行测试驱动开发工作流程:先编写会失败的测试,然后实现最简代码以通过测试,最后进行重构 + - 采用类似于原始Redis C语言实现的面向过程的编程风格 + - 尽可能使用纯Go语法和标准库 + +2. 教程结构: + - 从项目设置和环境配置说明开始 + - 按Redis功能拆分为逻辑模块进行开发 + - 针对每个模块/特性,提供: + a. 明确的测试用例定义,包含预期输入和输出 + b. 逐步的代码实现,附带逐行解释 + c. 明确的测试命令和验证流程 + d. 预期测试结果和成功标准 + +3. 技术要求: + - 包含所有组件的完整代码片段 + - 指定确切的文件结构和命名规范 + - 详细说明编译和测试命令 + - 解释常见问题的调试流程 + - 在适用时参考相关的Redis C源代码模式 + +4. 实现细节: + - 从核心数据结构(字符串、列表、哈希等)开始 + - 逐步推进到命令处理和协议实现 + - 包含网络层和客户端-服务器通信 + - 涵盖持久化机制(RDB/AOF) + - 按照相同的行为模式实现基本的Redis命令 + +5. 测试要求: + - 为每个组件提供完整的测试代码 + - 解释测试断言和验证方法 + - 包含单元测试和集成测试 + - 指定如何运行测试并解读结果 + - 详细说明如何根据Redis规范验证正确行为 + +该教程应足够全面,让具备中级Go知识的开发者能够按照指定方法成功构建一个功能类似的Redis系统。 +``` + +等待片刻后,我们收到一份设计文档。模型结合Redis源代码上下文,梳理出慢查询的核心脉络和关键定义,并规划出完整的开发步骤: +![慢查询设计文档](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-slowlog-design-doc.png) + +### 编码实现 + +我们从Redis源代码中抽取设计文档后,为确保C语言工程的设计思路能在个人Go语言项目工程规范中准确落地,将其复制到mini-redis项目,让模型分析方案的可行性和修改建议: + +![M2.7可行性分析](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-feasibility-analysis.png) + +等待片刻后模型完成文档最后的可行性分析和整理,我们开始对其设计方案进行进一步的复核确认。从项目概述上可以看到,模型针对mini-redis项目结构进行了分析,准确地定位到慢查询可以直接复用的链表结构体并完成文档微调: + +![M2.7链表结构体分析](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-linked-list-structure.png) + +再来看看最关键的数据结构实现思路,模型也结合mini-redis的编码规范,生成了Go语言风格的结构体: + +![M2.7 Go风格结构体](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-go-style-struct.png) + +针对慢查询时间测量,有个细节值得提一下。个人实现的指令处理入口和原生Redis有些设计上的出入:由于Go语言语法糖特性,笔者对指针、指针函数以及文件编排做了特殊处理。模型准确地基于笔者的协程模型定位到时间测量的切面,完成前置计时和后置统计,实现慢查询监控。 + +![M2.7时间测量切面](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-time-measurement-aspect.png) + +最后就是核心的慢查询指令实现,无论是参数解析还是指令查询和响应处理函数,模型都结合笔者的当前项目封装的逻辑给出了明确的编码方案: + +![M2.7慢查询指令实现](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-slowlog-command-implementation.png) + +经过仔细复核设计文档,整体开发思路基本一致,但在代码组织细节上仍有调优空间——例如模型将`slowlog`指令独立成文件,而未遵循项目惯例统一放入`command.go`。考虑到慢查询功能并非核心内存读写指令,且其日志管理逻辑相对独立,这一处理也算合理折中。权衡之后,我们决定保留模型的实现方式,同时手动调整部分文件布局以符合既有工程规范,随后推进剩余开发工作。 + +这一细节也提示我们:AI生成的代码架构虽具合理性,但与既有工程规范的适配仍需人工把关。 + +另外提一句,整个慢查询功能的实现过程中,模型有两次生成了不符合项目风格的代码(比如错误处理方式),需要手动调整。这不是大问题,但说明完全依赖AI生成还是不行的。 + +### 验收 + +因为笔者明确指定了TDD的开发模型,所以模型在这期间结合输出反馈和文档说明完成自循环修复,最终结合mini-redis的项目风格完成了慢查询指令的复刻。 + +得益于 AI 的推理和重构能力,在验收过程中我们有了更多的构思空间。之前一直因为源代码梳理总结和技术验收成本过大,导致 redis.conf 配置加载逻辑一直没有实现。 + +因为笔者需要将慢查询时间设置为0,方便对慢查询指令做最后的验收工作,所以笔者索性再次对其提出加载配置的需求: + +![M2.7配置加载实现](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/m2.7-config-loading.png) + +整个逻辑梳理和开发工作不到1小时,笔者顺利完成了慢查询指令复刻和验收,为了演示慢查询功能,将mini-redis的慢查询阈值设置为0: + +```bash +# 慢查询阈值(微秒) +# 执行时间超过此值的命令会被记录到慢查询日志中 +# 负值表示禁用慢查询日志,0 表示记录所有命令 +# 默认值:10000(10毫秒) +slowlog-log-slower-than 0 +``` + +启动mini-redis服务端后,键入slowlog get 默认返回空: + +![slowlog get初始状态](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/slowlog-get-initial-state.png) + +执行简单的set操作后,键入slowlog get,这条指令如预期被判定为慢查询指令并输出: + +![slowlog get记录set命令](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/slowlog-get-record-set-command.png) + +同理,我们依次键入后续几条指令,也都准确按照链表头插法入队,实现按照时间降序排列输出: + +![slowlog get多条记录](https://oss.javaguide.cn/github/javaguide/ai/coding/m2.7/slowlog-get-multiple-records.png) + +## 实战总结:AI 辅助编程的工作流思考 + +通过两个典型场景的实战,总结一下使用 Trae + 大模型辅助编程的一些经验和思考。 + +### AI 辅助编程能做什么 + +在上述两个场景中,AI 辅助编程展现出了几个核心能力: + +| 能力维度 | 场景表现 | 说明 | +| -------------- | ---------------------------------------- | ---------------------------------------- | +| 故障诊断与止血 | 场景一:快速定位连接池问题,提供降级方案 | 推理链条完整,能从异常栈帧梳理到调用链路 | +| 代码上下文理解 | 场景一:结合数据库 Schema 分析查询瓶颈 | 不局限于单文件,能关联跨模块的依赖关系 | +| 跨语言代码迁移 | 场景二:C 到 Go 的慢查询复刻 | 核心逻辑准确,工程规范适配有优化空间 | +| 复杂系统理解 | 场景二:Redis 源码分析 | 能把握设计意图,输出结构化技术文档 | + +### 实战中的经验与踩坑 + +**做得好的地方**: + +- **快速收敛问题范围**:场景一中,模型从 N 处 Redis 调用快速定位到 4 种可能根因,再到最终确认 scan 操作导致连接池夯死,整个推理链条清晰 +- **多层级方案输出**:止血方案、根因分析、长期优化建议分层给出,符合实际排障流程 +- **TDD 自循环修复**:场景二中,指定 TDD 模式后,模型能根据测试反馈自我修复,减少人工干预 + +**需要注意的地方**: + +- **方案激进**:模型给出的某些方案(如清除 Redis 缓存)可能过于激进,生产环境需要更保守的策略,这一点必须人工把关 +- **工程规范适配**:生成的代码结构虽合理,但与个人/团队既有规范的契合度需要磨合。比如场景二中 `slowlog` 指令的文件组织就需要手动调整 +- **边界情况处理**:部分极端场景的防御性代码建议人工补充——AI 能帮你走到 90%,剩下的 10% 还得靠自己 +- **长流程一致性**:在复杂项目的持续迭代中,需要关注上下文记忆的衰减问题 + +### 使用 Trae + 大模型的一些建议 + +1. **提供完整上下文**:明确约束条件、编码规范、项目结构,模型输出质量会好很多 +2. **分阶段确认**:复杂架构不要一次性让 AI 生成过多代码,分阶段确认和调整更可控 +3. **关键决策人工把控**:架构层面的选择(如缓存策略、降级方案)需要开发者根据业务场景判断,AI 无法替你做 +4. **善用 TDD 模式**:指定测试驱动开发流程,让模型在测试反馈中自我修复,效率更高 + +## 写在最后 + +Trae 作为 AI 编程 IDE,在接入大模型后的体验是流畅的——Agent 模式下的上下文理解、任务拆解、代码生成、测试验收形成了完整的工作流。 + +但工具终究只是工具。回顾本文的两个场景: + +- **场景一的 Redis 故障排查**,需要对 Redis 连接池机制、scan 命令的时间复杂度有清晰认知,才能判断模型给出的分析是否合理。 +- **场景二的跨语言重构**,需要对 Redis 源码的设计理念、Go 语言的工程规范有深入理解,才能评估重构方案的质量。 + +AI 编程工具能显著缩短"从想法到代码"的时间,但对底层原理的掌握、对系统架构的判断力,依然需要开发者自身去积累。用好 AI 的前提,是比 AI 更懂你在做什么。 diff --git a/docs/ai/rag/rag-basis.md b/docs/ai/rag/rag-basis.md index 589b91dcce6..86306e9663e 100644 --- a/docs/ai/rag/rag-basis.md +++ b/docs/ai/rag/rag-basis.md @@ -10,7 +10,7 @@ head: # RAG 基础概念面试题总结 -去年面字节的时候,面试官问我:”你们项目里的知识库问答是怎么做的?” 我说:”直接调 OpenAI 的 API,把文档塞进去让模型自己读。” +去年面字节的时候,面试官问我:“你们项目里的知识库问答是怎么做的?” 我说:“直接调 OpenAI 的 API,把文档塞进去让模型自己读。” 空气突然安静了三秒。我看到面试官的眉头皱了一下,才意识到事情不对——当时我们项目的文档有 20 多万字,每次请求都超 Token 上限,而且模型根本记不住上周刚更新的接口文档。 @@ -26,8 +26,6 @@ head: 6. RAG 与传统搜索引擎的区别是什么? 7. ⭐️ RAG 的核心优势和局限性分别是什么? -在前面的文章中,我已经分享了 7 道 AI 编程相关的开放性面试题,阅读 5w+,300+ 点赞:[面试官:”你连 Claude Code 都没用过吗?”,我怼回去:”就没用过又怎么了?”](https://mp.weixin.qq.com/s/AkBNmyrcmZsgkSzvJNmO7g)。 - ## ⭐️ 什么是 RAG? **RAG (Retrieval-Augmented Generation,检索增强生成)** 是一种将强大的**信息检索 (Information Retrieval, IR)** 技术与**生成式大语言模型 (LLM)** 相结合的框架。 @@ -235,7 +233,7 @@ RAG 的核心优势和局限性可以从**知识管理、工程落地和性能 ## ⭐️ 更多 RAG 高频面试题 -上面的内容摘自我的[星球](https://mp.weixin.qq.com/s/H2eKimiAbemEDoEsFyWT9g)实战项目教程: [《SpringAI 智能面试平台+RAG 知识库》](https://mp.weixin.qq.com/s/q9UjF53OG0rQVQu92UOKlQ)。内容安排如下(已经更完,一共 13w+ 字) +上面的内容摘自我的[星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)实战项目教程: [《SpringAI 智能面试平台+RAG 知识库》](https://javaguide.cn/zhuanlan/interview-guide.html)。内容安排如下(已经更完,一共 13w+ 字) ![配套教程内容概览](https://oss.javaguide.cn/xingqiu/pratical-project/interview-guide/tutorial-overview.png) @@ -258,7 +256,7 @@ RAG(检索增强生成)是当下企业级 AI 应用最核心的技术栈之 1. **RAG 是什么**:先从知识库检索相关内容,再让 LLM 基于检索结果生成回答,从而减少幻觉、提升可追溯性 2. **为什么需要 RAG**:解决 LLM 的知识时效性、私有数据访问、幻觉三大核心问题 -3. **RAG vs 传统搜索**:RAG 是"信息综合器",传统搜索是"相关性排序器" +3. **RAG vs 传统搜索**:RAG 是“信息综合器”,传统搜索是“相关性排序器” 4. **核心优势**:知识时效性、降低幻觉、数据安全、领域适应性强 5. **局限性**:检索依赖性、上下文窗口限制、工程复杂度、Token 成本 diff --git a/docs/ai/rag/rag-vector-store.md b/docs/ai/rag/rag-vector-store.md index 6ec818506b7..420d6c369d9 100644 --- a/docs/ai/rag/rag-vector-store.md +++ b/docs/ai/rag/rag-vector-store.md @@ -307,7 +307,7 @@ PostgreSQL 最大的优势,也是它在 AI 时代甩开对手的“王牌” ## ⭐️ 更多 RAG 高频面试题 -上面的内容摘自我的[星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)实战项目教程:[《SpringAI 智能面试平台+RAG 知识库》](https://javaguide.cn/zhuanlan/interview-guide.html)。内容安排如下(已经更完,一共 13w+ 字) +上面的内容摘自我的[星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)实战项目教程: [《SpringAI 智能面试平台+RAG 知识库》](https://javaguide.cn/zhuanlan/interview-guide.html)。内容安排如下(已经更完,一共 13w+ 字) ![配套教程内容概览](https://oss.javaguide.cn/xingqiu/pratical-project/interview-guide/tutorial-overview.png) @@ -315,9 +315,9 @@ Spring AI 和 RAG 面试题两篇加起来就接近 60 道题目,主打一个 ![RAG 面试题](https://oss.javaguide.cn/xingqiu/pratical-project/interview-guide/rag-interview-questions.png) -**项目地址**(欢迎 Star 鼓励): +**项目地址** (欢迎 Star 鼓励): -- GitHub: +- Github: - Gitee: 完整代码完全免费开源,没有 Pro 版本或者付费版! @@ -350,4 +350,4 @@ Spring AI 和 RAG 面试题两篇加起来就接近 60 道题目,主打一个 2. **动手实践**:用 pgvector 或 Milvus 搭建一个向量检索 Demo,感受不同索引的性能差异 3. **关注调优**:索引参数(ef_search、nprobe)对召回率和延迟的权衡,需要根据业务场景调优 -向量数据库是 RAG 的"心脏",选对方案、调好参数,是构建高性能 RAG 系统的关键。 +向量数据库是 RAG 的“心脏”,选对方案、调好参数,是构建高性能 RAG 系统的关键。 diff --git a/docs/java/basis/java-basic-questions-01.md b/docs/java/basis/java-basic-questions-01.md index e94ed828592..a80ae30dbb3 100644 --- a/docs/java/basis/java-basic-questions-01.md +++ b/docs/java/basis/java-basic-questions-01.md @@ -636,7 +636,7 @@ flowchart TB public class Test { // 成员变量,存放在堆中 int a = 10; - // 被 static 修饰的成员变量,JDK 1.7 及之前位于方法区,1.8 后存放于元空间,均不存放于堆中。 + // 被 static 修饰的成员变量,JDK 1.6 及之前位于永久代,1.7 后移出永久代,一直存放在堆中。 // 变量属于类,不属于对象。 static int b = 20; diff --git a/docs/java/new-features/java8-tutorial-translate.md b/docs/java/new-features/java8-tutorial-translate.md index 311825508b1..44833fd75b1 100644 --- a/docs/java/new-features/java8-tutorial-translate.md +++ b/docs/java/new-features/java8-tutorial-translate.md @@ -592,7 +592,7 @@ for (int i = 0; i < max; i++) { ```java //串行排序 long t0 = System.nanoTime(); -long count = values.stream().sorted().count(); +long count = Arrays.stream(list.stream().sorted().toArray()).count(); System.out.println(count); long t1 = System.nanoTime(); @@ -612,7 +612,7 @@ sequential sort took: 709 ms//串行排序所用的时间 //并行排序 long t0 = System.nanoTime(); -long count = values.parallelStream().sorted().count(); +long count = Arrays.stream(list.parallelStream().sorted().toArray()).count(); System.out.println(count); long t1 = System.nanoTime(); diff --git a/docs/system-design/framework/spring/spring-common-annotations.md b/docs/system-design/framework/spring/spring-common-annotations.md index 3a2b006c8ea..5135603b5de 100644 --- a/docs/system-design/framework/spring/spring-common-annotations.md +++ b/docs/system-design/framework/spring/spring-common-annotations.md @@ -1,5 +1,5 @@ --- -title: Spring&SpringBoot常用注解总结 +title: Spring&SpringMVC&SpringBoot常用注解总结 description: Spring和SpringBoot常用注解大全,涵盖@Autowired、@Component、@RequestMapping等核心注解的用法详解。 category: 框架 tag: @@ -1025,4 +1025,10 @@ public class MyServiceTest extends TestBase { // Assuming TestBase provides Spri } ``` + + +## 注解分类总结 + +(表格) +