CodeBuddy高级进阶教程
CodeBuddy 高级进阶教程
深度掌握 CodeBuddy,释放 AI 编程的极致潜能
目录
进阶概述
本教程面向已经掌握 CodeBuddy 基础用法的开发者,帮助你深入理解其高级特性,构建符合团队需求的高效 AI 编程工作流。
前置要求:
- ✅ 已安装并熟悉 CodeBuddy 基础操作
- ✅ 了解常用的命令行操作
- ✅ 具备一定的编程经验
高级配置
系统提示词自定义
CodeBuddy 提供三种自定义系统提示词的方式,让你完全掌控 AI 的行为模式。
1. 完全替换系统提示词
使用 --system-prompt 参数,移除所有默认指令:
codebuddy --system-prompt "你是只编写带类型注解代码的 Python 专家,遵循 PEP 8 规范,注重代码可读性和性能"
适用场景: 需要完全定制 AI 行为的专用场景。
2. 从文件加载提示词
使用 --system-prompt-file 参数,确保提示词的可重现性和版本控制:
# 创建提示词文件
cat > my-prompt.txt << 'EOF'
你是资深的后端工程师,专精于高并发系统设计。
编码原则:
1. 优先考虑性能和可扩展性
2. 使用异步 I/O 处理并发请求
3. 添加详细的性能监控日志
4. 所有公共 API 必须有完整的类型注解
EOF
# 使用文件加载提示词
codebuddy -p --system-prompt-file my-prompt.txt "设计一个高性能的用户认证系统"
适用场景: 团队协作,需要统一 AI 编码标准。
3. 追加系统提示词
使用 --append-system-prompt 参数,在保留默认功能的基础上添加特定指令:
codebuddy --append-system-prompt "始终使用 TypeScript 并包含 JSDoc 注释"
适用场景: 大多数用例,推荐方式。
权限模式配置
CodeBuddy 支持三种权限模式,根据安全需求选择:
| 模式 | 说明 | 使用命令 |
|---|---|---|
| auto | 自动模式,对可信操作自动授权 | codebuddy --permission-mode auto |
| plan | 计划模式,先展示计划再执行 | codebuddy --permission-mode plan |
| manual | 手动模式,每步操作都需要确认 | codebuddy --permission-mode manual |
多模型切换
根据任务类型选择最合适的模型:
# 使用特定模型
codebuddy --model deepseek-v3.1
# 设置文生图模型
codebuddy --text-to-image-model your-image-model
# 设置图生图模型
codebuddy --image-to-image-model your-edit-model
模型选择建议:
- 代码生成: DeepSeek-V3.1
- 复杂推理: DeepSeek-R1
- 中文对话: 混元 Turbo S
- 快速响应: 混元 Lite
MCP 生态集成
MCP (Model Context Protocol) 是 CodeBuddy 的核心竞争力,让 AI 能够调用外部工具和服务。
什么是 MCP
MCP 是一个开放协议,允许 AI 助手与外部系统进行标准化交互,实现:
- 🔄 自动化测试和部署
- 📊 数据库查询和分析
- 🔐 安全扫描和合规检查
- 📧 通知和协作集成
配置 MCP 服务器
# 初始化 MCP 配置
codebuddy mcp init
# 添加 MCP 服务器
codebuddy mcp add github
codebuddy mcp add docker
codebuddy mcp add postgres
常用 MCP 服务器
GitHub MCP
# 添加 GitHub MCP
codebuddy mcp add github
# 使用示例
codebuddy "检查我的 PR 是否有冲突"
codebuddy "分析最近一周的提交记录"
Docker MCP
# 添加 Docker MCP
codebuddy mcp add docker
# 使用示例
codebuddy "重启所有停止的容器"
codebuddy "检查镜像占用空间"
PostgreSQL MCP
# 添加 PostgreSQL MCP
codebuddy mcp add postgres
# 使用示例
codebuddy "查询用户表中注册日期最近的 10 个用户"
codebuddy "优化慢查询"
自定义 MCP 服务器
创建自定义 MCP 工具:
// mcp-tools/custom-tool.js
module.exports = {
name: 'custom-analyzer',
description: '自定义代码分析工具',
execute: async (params) => {
// 实现你的逻辑
return {
result: '分析完成',
metrics: params
};
}
};
自定义智能体与 Skills
自定义智能体让你能够创建专门的 AI 助手,处理特定类型的任务。Skills 是智能体的核心能力单元,定义了智能体可以执行的具体操作。
理解 Agent 与 Skills 的关系
Agent (智能体)
├── System Prompt (系统提示词): 定义智能体的角色和职责
├── Skills (技能集): 智能体可执行的具体能力
│ ├── Code Analysis (代码分析)
│ ├── Test Generation (测试生成)
│ ├── Documentation (文档生成)
│ └── Custom Skills (自定义技能)
├── Tools (工具集): 可调用的外部工具
└── Configuration (配置): 参数和行为设置
创建项目级智能体
基础智能体配置
在项目根目录创建智能体配置:
# .codebuddy/agents/backend-reviewer.yaml
name: Backend Reviewer
description: 专注于后端代码审查的智能体
version: 1.0.0
# 系统提示词: 定义智能体的角色
system_prompt: |
你是后端代码审查专家,专注于:
- Java/后端代码质量检查
- 数据库查询优化
- API 接口设计规范
- 性能和安全性分析
审查标准:
1. 遵循阿里巴巴 Java 开发规范
2. 识别 N+1 查询问题
3. 检查事务管理是否正确
4. 验证异常处理是否完善
# Skills 定义: 智能体的能力集合
skills:
# Skill 1: 代码审查
- name: code_review
description: 审查 Java 代码质量和规范
enabled: true
config:
check_style: true
check_performance: true
check_security: true
frameworks:
- spring-boot
- mybatis
- jpa
# Skill 2: 数据库优化
- name: database_optimization
description: 分析和优化数据库查询
enabled: true
config:
check_n_plus_one: true
suggest_indexes: true
analyze_slow_queries: true
# Skill 3: API 文档生成
- name: api_documentation
description: 生成 RESTful API 文档
enabled: true
config:
format: markdown
include_examples: true
include_auth_requirements: true
# Skill 4: 单元测试生成
- name: test_generation
description: 为 Java 类生成单元测试
enabled: true
config:
framework: junit5
mock_framework: mockito
coverage_target: 80
# 可用的工具
tools:
- maven
- gradle
- sonarqube
- checkstyle
- pmd
# 环境配置
environment:
java_version: "17"
build_tool: "maven"
创建企业级 Java 审查智能体
# .codebuddy/agents/java-enterprise-auditor.yaml
name: Java Enterprise Auditor
description: 企业级 Java 代码审计智能体
version: 2.0.0
author: DevOps Team
# 系统提示词
system_prompt: |
你是企业级 Java 代码审计专家,严格遵循:
- 阿里巴巴 Java 开发手册(泰山版)
- 企业内部安全规范
- 金融行业安全标准
- 数据保护法规(如 GDPR、个人信息保护法)
审查重点:
1. 安全漏洞(SQL 注入、XSS、CSRF、反序列化)
2. 性能问题(内存泄漏、线程池配置、连接池配置)
3. 代码质量(重复代码、复杂度、命名规范)
4. 业务逻辑(事务一致性、并发控制、幂等性)
输出要求:
- 问题按严重程度分级(严重/高危/中危/低危/提示)
- 提供具体的代码位置和修复建议
- 生成可执行的修复代码
- 评估修复风险和影响范围
# Skills 详细定义
skills:
# Skill: 安全审计
- name: security_audit
description: 执行全面的安全审计
enabled: true
priority: high
config:
check_items:
- sql_injection
- xss
- csrf
- path_traversal
- insecure_deserialization
- weak_encryption
- hardcoded_secrets
- ldap_injection
frameworks:
- spring-security
- shiro
- apache-shiro
# Skill: 性能分析
- name: performance_analysis
description: 分析代码性能瓶颈
enabled: true
priority: high
config:
check_items:
- memory_leaks
- thread_pool_config
- connection_pool_config
- cache_efficiency
- database_query_performance
- n_plus_one_queries
- unnecessary_object_creation
thresholds:
method_complexity: 10
class_complexity: 50
cyclomatic_complexity: 15
# Skill: 代码规范检查
- name: style_check
description: 检查代码规范和最佳实践
enabled: true
priority: medium
config:
checkstyle_rules: google_checks.xml
pmd_rules: rulesets/java/quickstart.xml
spotbugs_enabled: true
# Skill: 依赖分析
- name: dependency_analysis
description: 分析项目依赖安全性
enabled: true
priority: high
config:
check_vulnerabilities: true
check_licenses: true
check_outdated: true
allowed_licenses:
- Apache-2.0
- MIT
- BSD-3-Clause
# Skill: 架构评估
- name: architecture_review
description: 评估代码架构设计
enabled: true
priority: medium
config:
check_solid_principles: true
check_design_patterns: true
check_layering: true
check_coupling: true
# 工具集成
tools:
maven:
enabled: true
goals:
- compile
- test
- checkstyle:check
- pmd:check
- spotbugs:check
- dependency-check
sonarqube:
enabled: true
url: ${SONARQUBE_URL}
quality_gate: true
jenkins:
enabled: true
pipeline_integration: true
# 输出配置
output:
format:
- console
- markdown
- json
include_code_examples: true
include_fix_suggestions: true
generate_report: true
# 审查规则
review_rules:
severity_levels:
critical:
auto_fail: true
examples:
- hardcoded_passwords
- sql_injection_vulnerabilities
- memory_leaks
high:
examples:
- n_plus_one_queries
- missing_error_handling
- insecure_random
medium:
examples:
- code_duplication
- poor_naming
- missing_documentation
low:
examples:
- unused_imports
- magic_numbers
使用 Skills 的实战示例
示例 1: 使用 Java 审查智能体
# 启动 CodeBuddy
codebuddy
# 初始化项目
> /init
# 使用智能体进行代码审查
> 使用 java-enterprise-auditor 智能体审查以下文件:
@src/main/java/com/company/user/service/UserService.java
@src/main/java/com/company/user/controller/UserController.java
@src/main/java/com/company/user/repository/UserRepository.java
重点检查:
1. SQL 注入风险
2. 事务管理是否正确
3. N+1 查询问题
4. 敏感信息是否加密
被审查的 Java 代码示例:
// src/main/java/com/company/user/service/UserService.java
package com.company.user.service;
import com.company.user.entity.User;
import com.company.user.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
// 问题 1: 没有输入验证
// 问题 2: SQL 注入风险(如果使用原生 SQL)
public User findUserById(Long userId) {
return userRepository.findById(userId).orElse(null);
}
// 问题 3: 可能存在 N+1 查询
@Transactional
public List<User> findUsersWithOrders(List<Long> userIds) {
List<User> users = userRepository.findAllById(userIds);
// 这里会触发 N+1 查询
for (User user : users) {
user.getOrders().size(); // 触发延迟加载
}
return users;
}
// 问题 4: 敏感信息明文存储
public void createUser(String username, String password, String email) {
User user = new User();
user.setUsername(username);
user.setPassword(password); // 密码未加密
user.setEmail(email);
userRepository.save(user);
}
// 问题 5: 事务边界不清晰
@Transactional
public void updateUserProfile(Long userId, String email) {
User user = findUserById(userId);
user.setEmail(email);
userRepository.save(user);
// 这里调用外部服务可能导致事务超时
externalService.sendEmail(user);
}
// 问题 6: 异常处理不当
public User getUserByEmail(String email) {
try {
return userRepository.findByEmail(email);
} catch (Exception e) {
// 吞掉异常,无法追踪问题
return null;
}
}
}
CodeBuddy 审查结果:
# 📋 Java Enterprise Auditor 审查报告
## 🔴 严重问题 (Critical)
### 1. 密码明文存储
**位置:** `UserService.java:32`
**风险等级:** 🔴 Critical
**问题描述:** 用户密码未加密直接存储,存在严重安全隐患
**当前代码:**
```java
user.setPassword(password); // 密码未加密
修复建议:
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Autowired
private BCryptPasswordEncoder passwordEncoder;
public void createUser(String username, String password, String email) {
User user = new User();
user.setUsername(username);
user.setPassword(passwordEncoder.encode(password)); // 加密存储
user.setEmail(email);
userRepository.save(user);
}
影响范围: 所有用户账户安全
修复优先级: 立即修复
2. SQL 注入风险
位置: UserService.java:18
风险等级: 🔴 Critical
问题描述: 如果 UserRepository 使用原生 SQL,存在 SQL 注入风险
修复建议:
// 使用 JPA 的参数化查询
public User findUserById(Long userId) {
return userRepository.findById(userId)
.orElseThrow(() -> new UserNotFoundException("User not found: " + userId));
}
🟠 高危问题 (High)
3. N+1 查询问题
位置: UserService.java:24-30
风险等级: 🟠 High
问题描述: 在循环中访问关联关系,导致 N+1 查询
当前代码:
for (User user : users) {
user.getOrders().size(); // 触发延迟加载
}
修复建议:
// 使用 JOIN FETCH 一次性加载
@Transactional
public List<User> findUsersWithOrders(List<Long> userIds) {
return userRepository.findAllWithOrders(userIds);
}
// Repository 中添加
@Query("SELECT u FROM User u LEFT JOIN FETCH u.orders WHERE u.id IN :userIds")
List<User> findAllWithOrders(@Param("userIds") List<Long> userIds);
4. 事务边界不清晰
位置: UserService.java:41-47
风险等级: 🟠 High
问题描述: 在事务方法中调用外部服务,可能导致事务超时或死锁
修复建议:
// 将事务操作和外部调用分离
@Transactional
public void updateUserProfile(Long userId, String email) {
User user = findUserById(userId);
user.setEmail(email);
userRepository.save(user);
}
// 单独处理外部调用
public void sendNotification(Long userId) {
User user = findUserById(userId);
externalService.sendEmail(user);
}
🟡 中危问题 (Medium)
5. 缺少输入验证
位置: UserService.java:18
风险等级: 🟡 Medium
问题描述: findUserById 方法没有验证输入参数
修复建议:
public User findUserById(Long userId) {
if (userId == null || userId <= 0) {
throw new IllegalArgumentException("Invalid user ID");
}
return userRepository.findById(userId)
.orElseThrow(() -> new UserNotFoundException("User not found: " + userId));
}
6. 异常处理不当
位置: UserService.java:49-55
风险等级: 🟡 Medium
问题描述: 吞掉异常,无法追踪问题
修复建议:
public User getUserByEmail(String email) {
if (email == null || email.trim().isEmpty()) {
throw new IllegalArgumentException("Email cannot be null or empty");
}
try {
return userRepository.findByEmail(email)
.orElseThrow(() -> new UserNotFoundException("User not found: " + email));
} catch (DataAccessException e) {
log.error("Failed to find user by email: {}", email, e);
throw new ServiceException("Failed to retrieve user", e);
}
}
📊 审查统计
- 审查文件数: 3
- 发现问题数: 6
- 严重问题: 2
- 高危问题: 2
- 中危问题: 2
- 代码覆盖率: 待检测
🔧 自动化修复
CodeBuddy 可以自动生成修复代码。运行以下命令:
> 为以上所有问题生成修复代码,创建新的分支
这将自动:
- 创建新分支
fix/security-audit-issues - 生成修复代码
- 运行测试验证修复
- 创建 PR 请求
#### 示例 2: 使用 Skills 生成单元测试
```bash
# 使用 test_generation Skill
> 使用 java-enterprise-auditor 的 test_generation skill 为以下类生成单元测试:
@src/main/java/com/company/user/service/UserService.java
要求:
1. 使用 JUnit 5
2. 使用 Mockito 模拟依赖
3. 覆盖率达到 80% 以上
4. 包含正常场景和异常场景
生成的测试代码:
// src/test/java/com/company/user/service/UserServiceTest.java
package com.company.user.service;
import com.company.user.entity.User;
import com.company.user.exception.UserNotFoundException;
import com.company.user.repository.UserRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
@DisplayName("UserService 单元测试")
class UserServiceTest {
@Mock
private UserRepository userRepository;
@Mock
private PasswordEncoder passwordEncoder;
@Mock
private ExternalService externalService;
@InjectMocks
private UserService userService;
private User testUser;
@BeforeEach
void setUp() {
testUser = User.builder()
.id(1L)
.username("testuser")
.password("encodedPassword")
.email("test@example.com")
.build();
}
@Test
@DisplayName("根据 ID 查找用户 - 成功")
void findUserById_Success() {
// Given
when(userRepository.findById(1L)).thenReturn(Optional.of(testUser));
// When
User result = userService.findUserById(1L);
// Then
assertThat(result).isNotNull();
assertThat(result.getId()).isEqualTo(1L);
assertThat(result.getUsername()).isEqualTo("testuser");
verify(userRepository, times(1)).findById(1L);
}
@Test
@DisplayName("根据 ID 查找用户 - 用户不存在")
void findUserById_UserNotFound() {
// Given
when(userRepository.findById(999L)).thenReturn(Optional.empty());
// When & Then
assertThatThrownBy(() -> userService.findUserById(999L))
.isInstanceOf(UserNotFoundException.class)
.hasMessageContaining("User not found: 999");
verify(userRepository, times(1)).findById(999L);
}
@Test
@DisplayName("根据 ID 查找用户 - 无效 ID")
void findUserById_InvalidId() {
// When & Then
assertThatThrownBy(() -> userService.findUserById(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Invalid user ID");
assertThatThrownBy(() -> userService.findUserById(-1L))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Invalid user ID");
verify(userRepository, never()).findById(anyLong());
}
@Test
@DisplayName("创建用户 - 成功")
void createUser_Success() {
// Given
when(passwordEncoder.encode("rawPassword")).thenReturn("encodedPassword");
when(userRepository.save(any(User.class))).thenAnswer(invocation -> invocation.getArgument(0));
// When
userService.createUser("newuser", "rawPassword", "new@example.com");
// Then
verify(passwordEncoder, times(1)).encode("rawPassword");
verify(userRepository, times(1)).save(argThat(user ->
user.getUsername().equals("newuser") &&
user.getPassword().equals("encodedPassword") &&
user.getEmail().equals("new@example.com")
));
}
@Test
@DisplayName("根据邮箱查找用户 - 成功")
void getUserByEmail_Success() {
// Given
when(userRepository.findByEmail("test@example.com")).thenReturn(Optional.of(testUser));
// When
User result = userService.getUserByEmail("test@example.com");
// Then
assertThat(result).isNotNull();
assertThat(result.getEmail()).isEqualTo("test@example.com");
verify(userRepository, times(1)).findByEmail("test@example.com");
}
@Test
@DisplayName("根据邮箱查找用户 - 邮箱为空")
void getUserByEmail_EmptyEmail() {
// When & Then
assertThatThrownBy(() -> userService.getUserByEmail(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Email cannot be null or empty");
assertThatThrownBy(() -> userService.getUserByEmail(""))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Email cannot be null or empty");
verify(userRepository, never()).findByEmail(any());
}
@Test
@DisplayName("根据邮箱查找用户 - 数据库异常")
void getUserByEmail_DatabaseException() {
// Given
when(userRepository.findByEmail("test@example.com"))
.thenThrow(new RuntimeException("Database connection failed"));
// When & Then
assertThatThrownBy(() -> userService.getUserByEmail("test@example.com"))
.isInstanceOf(ServiceException.class)
.hasMessageContaining("Failed to retrieve user");
verify(userRepository, times(1)).findByEmail("test@example.com");
}
@Test
@DisplayName("批量查找用户及其订单 - 解决 N+1 问题")
void findUsersWithOrders_WithJoinFetch() {
// Given
List<Long> userIds = Arrays.asList(1L, 2L, 3L);
User user1 = User.builder().id(1L).username("user1").build();
User user2 = User.builder().id(2L).username("user2").build();
User user3 = User.builder().id(3L).username("user3").build();
when(userRepository.findAllWithOrders(userIds))
.thenReturn(Arrays.asList(user1, user2, user3));
// When
List<User> result = userService.findUsersWithOrders(userIds);
// Then
assertThat(result).hasSize(3);
verify(userRepository, times(1)).findAllWithOrders(userIds);
// 验证没有触发额外的查询
verify(userRepository, never()).findById(anyLong());
}
}
创建自定义 Skill
Skill 配置文件结构
# .codebuddy/skills/custom-skill.yaml
name: my_custom_skill
display_name: 自定义技能
description: 我自己的自定义技能
version: 1.0.0
# Skill 类型
type: analysis
# analysis | generation | transformation | validation
# 执行配置
execution:
mode: synchronous
timeout: 300
retry_count: 3
# 输入参数定义
inputs:
- name: source_files
type: array
required: true
description: 要处理的源文件列表
- name: analysis_depth
type: enum
required: false
default: medium
options:
- shallow
- medium
- deep
description: 分析深度
# 输出参数定义
outputs:
- name: analysis_report
type: object
description: 分析结果报告
- name: metrics
type: object
description: 性能指标
# 技能配置
config:
rules:
enabled: true
file: .codebuddy/rules/custom-rules.json
templates:
enabled: true
directory: .codebuddy/templates
integrations:
- sonarqube
- jira
实现自定义 Skill 逻辑
// .codebuddy/skills/my-custom-skill.js
class MyCustomSkill {
constructor(config) {
this.config = config;
this.name = 'my_custom_skill';
}
/**
* 执行技能
* @param {Object} params 输入参数
* @param {Object} context 执行上下文
* @returns {Promise<Object>} 执行结果
*/
async execute(params, context) {
const { source_files, analysis_depth } = params;
try {
// 1. 验证输入
this.validateInputs(params);
// 2. 执行分析
const analysisResults = await this.analyzeFiles(source_files, analysis_depth, context);
// 3. 生成报告
const report = this.generateReport(analysisResults);
// 4. 计算指标
const metrics = this.calculateMetrics(analysisResults);
return {
success: true,
data: {
analysis_report: report,
metrics: metrics
}
};
} catch (error) {
return {
success: false,
error: error.message,
stack: error.stack
};
}
}
/**
* 验证输入参数
*/
validateInputs(params) {
if (!params.source_files || !Array.isArray(params.source_files)) {
throw new Error('source_files must be an array');
}
if (params.source_files.length === 0) {
throw new Error('source_files cannot be empty');
}
}
/**
* 分析文件
*/
async analyzeFiles(files, depth, context) {
const results = [];
for (const file of files) {
const fileContent = await context.readFile(file);
const analysis = await this.analyzeFile(file, fileContent, depth);
results.push(analysis);
}
return results;
}
/**
* 分析单个文件
*/
async analyzeFile(filePath, content, depth) {
// 这里实现具体的分析逻辑
const lines = content.split('\n');
const issues = [];
// 示例: 检测代码复杂度
if (depth === 'deep') {
const complexity = this.calculateComplexity(content);
if (complexity > 10) {
issues.push({
type: 'complexity',
severity: 'warning',
message: `High complexity detected: ${complexity}`,
line: this.findMostComplexLine(content)
});
}
}
return {
file: filePath,
lines: lines.length,
issues: issues,
metrics: {
complexity: this.calculateComplexity(content),
maintainability: this.calculateMaintainability(content)
}
};
}
/**
* 计算代码复杂度
*/
calculateComplexity(content) {
// 简化的圈复杂度计算
const patterns = [
/if\s*\(/g,
/else\s+if\s*\(/g,
/for\s*\(/g,
/while\s*\(/g,
/catch\s*\(/g,
/\&\&/g,
/\|\|/g
];
let complexity = 1; // 基础复杂度
for (const pattern of patterns) {
const matches = content.match(pattern);
if (matches) {
complexity += matches.length;
}
}
return complexity;
}
/**
* 计算可维护性指数
*/
calculateMaintainability(content) {
// 简化的可维护性计算
const lines = content.split('\n').length;
const complexity = this.calculateComplexity(content);
const comments = (content.match(/\/\*[\s\S]*?\*\//g) || []).length;
// MI = 171 - 5.2 * ln(vol) - 0.23 * cyclomatic - 16.2 * ln(lines)
// 这里使用简化版本
return Math.max(0, 100 - (complexity * 2) - (lines / 10));
}
/**
* 生成报告
*/
generateReport(results) {
const totalFiles = results.length;
const totalIssues = results.reduce((sum, r) => sum + r.issues.length, 0);
const avgComplexity = results.reduce((sum, r) => sum + r.metrics.complexity, 0) / totalFiles;
return {
summary: {
total_files: totalFiles,
total_issues: totalIssues,
avg_complexity: avgComplexity.toFixed(2)
},
details: results
};
}
/**
* 计算指标
*/
calculateMetrics(results) {
return {
execution_time: Date.now(),
files_processed: results.length,
issues_found: results.reduce((sum, r) => sum + r.issues.length, 0)
};
}
}
module.exports = MyCustomSkill;
注册自定义 Skill
# .codebuddy/agents/custom-agent.yaml
name: Custom Agent
description: 使用自定义技能的智能体
system_prompt: |
你是自定义智能体,可以使用自定义技能进行代码分析。
skills:
- name: my_custom_skill
enabled: true
config:
analysis_depth: deep
- name: code_review
enabled: true
Skills 最佳实践
- 单一职责: 每个 Skill 只做一件事
- 可配置性: 通过配置文件灵活调整行为
- 可测试性: 为每个 Skill 编写单元测试
- 错误处理: 完善的错误处理和日志记录
- 性能优化: 避免阻塞操作,使用异步处理
- 文档完善: 提供清晰的使用文档和示例
Skills 调用方式
# 方式 1: 通过智能体调用
> 使用 java-enterprise-auditor 智能体执行 security_audit skill
# 方式 2: 直接调用 Skill
> 执行 database_optimization skill,分析 @src/main/resources/mapper/*.xml
# 方式 3: 组合多个 Skills
> 依次执行以下 skills:
1. security_audit
2. performance_analysis
3. code_review
生成综合报告
Agent 和 Skills 配置文件完整示例
# .codebuddy/agents/java-fullstack-agent.yaml
name: Java FullStack Agent
display_name: Java 全栈开发助手
description: 专业的 Java 全栈开发智能体
version: 3.0.0
author: DevOps Team
# 系统提示词
system_prompt: |
你是 Java 全栈开发专家,精通以下技术栈:
**后端技术:**
- Java 17+, Spring Boot 3.x
- Spring Data JPA, MyBatis
- Spring Security, JWT
- Redis, RabbitMQ
- MySQL, PostgreSQL, MongoDB
**前端技术:**
- React 18+, Vue 3
- TypeScript
- Ant Design, Element Plus
**DevOps:**
- Docker, Kubernetes
- Jenkins, GitLab CI
- Prometheus, Grafana
**最佳实践:**
- 遵循阿里巴巴 Java 开发手册
- RESTful API 设计规范
- 前后端分离架构
- 微服务设计原则
**输出要求:**
- 代码必须完整可运行
- 包含必要的注释和文档
- 遵循命名规范
- 考虑性能和安全性
# Skills 集合
skills:
# 后端开发
- name: backend_crud
display_name: CRUD 代码生成
description: 自动生成增删改查代码
type: generation
enabled: true
config:
frameworks:
- spring-boot
- spring-data-jpa
include_validation: true
include_documentation: true
- name: api_design
display_name: API 设计
description: 设计 RESTful API 接口
type: generation
enabled: true
config:
follow_restful: true
include_swagger: true
include_error_handling: true
# 前端开发
- name: frontend_component
display_name: 前端组件生成
description: 生成 React/Vue 组件
type: generation
enabled: true
config:
framework: react
typescript: true
include_styled_components: true
- name: state_management
display_name: 状态管理
description: 实现状态管理逻辑
type: generation
enabled: true
config:
library: redux-toolkit
include_async_actions: true
# 数据库设计
- name: database_schema
display_name: 数据库设计
description: 设计数据库表结构
type: generation
enabled: true
config:
database: postgresql
include_indexes: true
include_relationships: true
- name: query_optimization
display_name: 查询优化
description: 优化 SQL 查询
type: analysis
enabled: true
config:
check_n_plus_one: true
suggest_indexes: true
# 测试
- name: test_generation
display_name: 测试生成
description: 生成单元测试和集成测试
type: generation
enabled: true
config:
backend_framework: junit5
frontend_framework: jest
coverage_target: 80
# 部署
- name: docker_compose
display_name: Docker Compose 生成
description: 生成 Docker Compose 配置
type: generation
enabled: true
config:
include_database: true
include_redis: true
include_nginx: true
- name: kubernetes_manifest
display_name: Kubernetes 配置
description: 生成 Kubernetes 部署配置
type: generation
enabled: true
config:
include_hpa: true
include_configmap: true
include_secret: true
# 文档
- name: api_documentation
display_name: API 文档
description: 生成 API 文档
type: generation
enabled: true
config:
format: markdown
include_examples: true
include_auth_requirements: true
- name: architecture_documentation
display_name: 架构文档
description: 生成架构设计文档
type: generation
enabled: true
config:
include_diagrams: true
include_decision_records: true
# 工具集
tools:
maven:
enabled: true
version: 3.9
node:
enabled: true
version: 18
docker:
enabled: true
version: 24
kubectl:
enabled: true
version: 1.28
# 环境配置
environment:
java:
version: "17"
maven:
version: "3.9.5"
node:
version: "18.17.0"
package_manager: "npm"
database:
type: "postgresql"
version: "15"
cache:
type: "redis"
version: "7"
# 代码规范
code_standards:
java:
style_guide: "alibaba-java-coding-guidelines"
checkstyle: "google_checks.xml"
pmd: "rulesets/java/quickstart.xml"
javascript:
style_guide: "airbnb"
eslint: "airbnb-base"
typescript:
style_guide: "airbnb-typescript"
eslint: "airbnb-typescript/base"
# 输出配置
output:
format:
- code
- markdown
- json
include:
- comments
- examples
- tests
- documentation
structure:
follow_project_structure: true
create_backup: true
# 安全配置
security:
check_vulnerabilities: true
check_hardcoded_secrets: true
check_sql_injection: true
check_xss: true
enforce_https: true
# 性能配置
performance:
optimize_queries: true
enable_caching: true
lazy_loading: true
pagination_enabled: true
# 监控配置
monitoring:
include_metrics: true
include_logging: true
include_tracing: true
alerting_enabled: true
使用完整智能体
# 启动 CodeBuddy
codebuddy
# 初始化项目
> /init
# 使用 Java 全栈智能体创建完整功能
> 使用 java-fullstack-agent 智能体创建一个用户管理功能:
需求:
1. 后端 API(用户 CRUD、认证、授权)
2. 前端页面(用户列表、详情、编辑)
3. 数据库表结构
4. 单元测试
5. API 文档
6. Docker 部署配置
技术栈:
- Spring Boot 3.x + JPA + PostgreSQL
- React 18 + TypeScript + Ant Design
- JWT 认证
- Docker Compose
这将会自动生成:
- 后端完整的代码结构
- 前端组件和页面
- 数据库迁移脚本
- 单元测试代码
- API 文档
- Docker Compose 配置
- 部署脚本
斜杠命令系统
斜杠命令是提升效率的神器,可以将复杂操作封装为简单指令。
项目级命令
在项目中创建共享命令:
# 创建命令目录
mkdir -p .codebuddy/commands
# 创建代码审查命令
cat > .codebuddy/commands/review.md << 'EOF'
请对当前代码进行全面审查,重点关注:
1. 安全漏洞(如 SQL 注入、XSS)
2. 性能问题(如 N+1 查询、内存泄漏)
3. 代码规范(如命名、格式)
4. 业务逻辑错误
EOF
# 创建性能优化命令
cat > .codebuddy/commands/optimize.md << 'EOF'
分析当前代码的性能瓶颈,并提供具体的优化建议:
1. 识别不必要的计算
2. 建议缓存策略
3. 推荐索引优化
4. 并行化机会
EOF
参数化命令
使用 $ARGUMENTS 占位符创建灵活的命令:
# 创建问题修复命令
cat > .codebuddy/commands/fix-issue.md << 'EOF'
修复工单 #$ARGUMENTS 中描述的问题。
步骤:
1. 理解问题根因
2. 在代码库中定位相关代码
3. 实现修复方案
4. 添加回归测试
5. 更新相关文档
6. 生成规范的提交信息
EOF
# 使用方法
/fix-issue 123
个人级命令
创建在所有项目中都有效的个人命令:
# 创建个人命令目录
mkdir -p ~/.codebuddy/commands
# 创建安全审查命令
cat > ~/.codebuddy/commands/security-audit.md << 'EOF'
对代码进行安全审计,检查:
- 敏感信息泄露风险
- 不安全的第三方库
- 配置文件暴露风险
- API 权限配置
EOF
命令组织技巧
.codebuddy/
├── commands/
│ ├── review/
│ │ ├── frontend.md # 前端代码审查
│ │ └── backend.md # 后端代码审查
│ ├── test/
│ │ ├── unit.md # 单元测试生成
│ │ └── integration.md # 集成测试生成
│ └── refactor/
│ └── cleanup.md # 代码清理
└── agents/
└── custom-agent.yaml
RAG 知识库构建
RAG (Retrieval-Augmented Generation) 技术让 CodeBuddy 能够利用企业私有知识,提供更精准的代码建议。
为什么需要 RAG
解决 AI 编程的三大痛点:
- 知识时效性: AI 模型训练数据滞后,无法覆盖最新技术动态
- 上下文理解局限: 难以捕捉跨文件依赖关系
- 幻觉与安全风险: 可能生成不符合企业规范的代码
创建企业知识库
步骤 1: 准备知识文档
支持的文档格式:
- Markdown (.md)
- Text (.txt)
- Word (.docx)
- PDF (.pdf)
- 代码文件 (.js, .py, .java 等)
步骤 2: 上传文档
在 CodeBuddy IDE 中:
- 打开知识库管理面板
- 创建新的知识库
- 上传相关文档
- 等待索引完成
步骤 3: 配置知识库
# .codebuddy/knowledge-base.yaml
name: Enterprise Standards
description: 企业编码规范和最佳实践
documents:
- coding-standards.md
- api-specifications.md
- security-guidelines.md
- architecture-docs/
embedding_model: text-embedding-ada-002
chunk_size: 1000
chunk_overlap: 200
知识库最佳实践
- 文档组织: 按主题分类,保持结构清晰
- 定期更新: 及时添加新的规范和文档
- 版本控制: 知识库文档纳入版本管理
- 质量监控: 定期评估知识库的有效性
使用知识库
# 启用知识库
codebuddy --knowledge-base enterprise-standards
# 查询知识库
codebuddy "根据我们的编码规范,实现用户认证功能"
性能优化技巧
1. 项目初始化优化
使用 /init 命令预先构建项目知识图谱:
# 首次使用项目时
codebuddy
> /init
# 项目结构发生重大变化时
> /clear
> /init
优势:
- ✅ 理解更准确: AI 能更准确理解代码结构和业务逻辑
- ✅ 响应更快速: 避免重复扫描文件
- ✅ 建议更精准: 基于全局视图提供更符合项目架构的建议
- ✅ 成本优化: 减少 30-50% 的 Token 消耗
2. 上下文管理
有效使用 @ 引用
# 引用单个文件
@src/utils/helpers.js 解释这个函数的用途
# 引用多个文件
@src/api/user.js @src/models/user.js 分析用户认证流程
# 引用整个代码库
#Codebase 这个项目的整体架构是什么?
上下文窗口优化
- 🎯 只包含相关文件
- 📦 使用模块化引用
- 🔍 避免冗余信息
- 💾 及时清理不必要的历史对话
3. 并行任务处理
利用 CodeBuddy 的多任务并行能力:
# 终端 1: 处理前端
codebuddy "重构 React 组件使用 Hooks"
# 终端 2: 处理后端
codebuddy "优化 API 响应时间"
# 终端 3: 生成文档
codebuddy "为 API 生成 Swagger 文档"
4. 缓存策略
# 启用缓存
codebuddy --cache-enabled
# 清除缓存
codebuddy --cache-clear
企业级部署
私有化部署
企业可以部署私有化的 CodeBuddy 服务:
# docker-compose.yml
version: '3.8'
services:
codebuddy:
image: tencent/codebuddy-enterprise:latest
ports:
- "8080:8080"
environment:
- MODEL_ENDPOINT=https://your-model-endpoint
- DATABASE_URL=postgresql://user:pass@db:5432/codebuddy
- REDIS_URL=redis://redis:6379
volumes:
- ./data:/app/data
- ./config:/app/config
depends_on:
- db
- redis
db:
image: postgres:15
environment:
- POSTGRES_DB=codebuddy
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
redis:
image: redis:7
团队协作配置
统一编码规范
创建团队共享的配置文件:
// .codebuddy/team-config.json
{
"codeStyle": {
"language": "TypeScript",
"indentation": "spaces",
"indentSize": 2,
"quotes": "single",
"semicolons": true
},
"reviewRules": [
"no-console",
"no-any",
"prefer-const"
],
"testFramework": "jest",
"documentationFormat": "JSDoc"
}
权限管理
# .codebuddy/permissions.yaml
roles:
- name: developer
permissions:
- read_code
- write_code
- run_tests
- generate_documentation
- name: senior_developer
permissions:
- read_code
- write_code
- run_tests
- generate_documentation
- refactor_code
- deploy_staging
- name: tech_lead
permissions:
- all
CI/CD 集成
GitHub Actions 示例
# .github/workflows/codebuddy-review.yml
name: CodeBuddy Review
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install CodeBuddy
run: npm install -g @tencent-ai/codebuddy-code
- name: Run Code Review
run: |
codebuddy -p --dangerously-skip-permissions \
"审查这个 PR 的代码变更,重点检查安全漏洞和性能问题" \
> review-report.txt
- name: Comment Review
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const report = fs.readFileSync('review-report.txt', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: report
});
高级调试技巧
1. 查看详细日志
# 启用详细日志
export DEBUG=codebuddy:*
codebuddy
# 或在命令中指定
codebuddy --log-level debug
2. 对话历史恢复
# 恢复最近的对话
codebuddy --continue
# 恢复特定对话
codebuddy --resume <session-id>
# 在非交互模式下继续
codebuddy --continue --print "继续我的任务"
3. 性能分析
# 分析响应时间
codebuddy --profile
# 统计 Token 使用
codebuddy --stats
4. 错误排查
常见错误及解决方案
错误 1: 模型响应超时
# 增加超时时间
codebuddy --timeout 120
错误 2: 上下文窗口溢出
# 减少上下文大小
codebuddy --context-size 8000
错误 3: 权限拒绝
# 使用自动授权模式
codebuddy --permission-mode auto
实战案例
案例 1: 从零构建 RESTful API
场景: 使用 Node.js + Express + MongoDB 构建一个完整的电商后端 API
原始需求
用户希望构建一个电商平台的后端 API,需要实现:
- 用户注册、登录、JWT 认证
- 商品 CRUD 操作
- 购物车管理
- 订单处理
- 支付集成(模拟)
步骤 1: 项目初始化
# 创建项目目录
mkdir ecommerce-api
cd ecommerce-api
# 初始化 Node.js 项目
npm init -y
# 安装依赖
npm install express mongoose dotenv jsonwebtoken bcryptjs
npm install -D nodemon jest supertest
使用 CodeBuddy 自动生成配置文件:
codebuddy
> /init
> 生成 package.json 配置,包含完整的脚本命令
> 生成 .env.example 文件,列出所有环境变量
生成的 package.json:
{
"name": "ecommerce-api",
"version": "1.0.0",
"description": "电商后端 API",
"main": "src/server.js",
"scripts": {
"start": "node src/server.js",
"dev": "nodemon src/server.js",
"test": "jest --coverage",
"test:watch": "jest --watch",
"lint": "eslint src/",
"lint:fix": "eslint src/ --fix"
},
"dependencies": {
"express": "^4.18.2",
"mongoose": "^8.0.0",
"dotenv": "^16.3.1",
"jsonwebtoken": "^9.0.2",
"bcryptjs": "^2.4.3"
},
"devDependencies": {
"nodemon": "^3.0.1",
"jest": "^29.7.0",
"supertest": "^6.3.3"
}
}
步骤 2: 创建数据库模型
使用 CodeBuddy 生成 Mongoose 模型:
> @schemas/user.schema.js 基于以下需求生成用户模型:
- 用户名、邮箱、密码(加密)
- 用户角色(普通用户、管理员)
- 创建时间、更新时间
- 索引优化
生成的 User 模型:
// src/models/User.js
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
unique: true,
trim: true,
minlength: 3,
maxlength: 50
},
email: {
type: String,
required: true,
unique: true,
trim: true,
lowercase: true,
match: [/^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/, '请输入有效的邮箱地址']
},
password: {
type: String,
required: true,
minlength: 6,
select: false
},
role: {
type: String,
enum: ['user', 'admin'],
default: 'user'
},
isActive: {
type: Boolean,
default: true
}
}, {
timestamps: true
});
// 创建索引
userSchema.index({ email: 1 });
userSchema.index({ username: 1 });
// 密码加密中间件
userSchema.pre('save', async function(next) {
if (!this.isModified('password')) return next();
try {
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
next();
} catch (error) {
next(error);
}
});
// 验证密码方法
userSchema.methods.comparePassword = async function(candidatePassword) {
return await bcrypt.compare(candidatePassword, this.password);
};
// 生成 JWT Token
userSchema.methods.generateToken = function() {
return jwt.sign(
{ id: this._id, role: this.role },
process.env.JWT_SECRET,
{ expiresIn: process.env.JWT_EXPIRE || '7d' }
);
};
module.exports = mongoose.model('User', userSchema);
类似地生成 Product 模型:
// src/models/Product.js
const mongoose = require('mongoose');
const productSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true,
maxlength: 200
},
description: {
type: String,
required: true,
maxlength: 2000
},
price: {
type: Number,
required: true,
min: 0
},
category: {
type: String,
required: true,
enum: ['electronics', 'clothing', 'books', 'home', 'other']
},
stock: {
type: Number,
required: true,
min: 0,
default: 0
},
images: [{
type: String
}],
rating: {
type: Number,
default: 0,
min: 0,
max: 5
},
reviews: [{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
rating: Number,
comment: String,
createdAt: {
type: Date,
default: Date.now
}
}],
isActive: {
type: Boolean,
default: true
}
}, {
timestamps: true
});
// 创建复合索引
productSchema.index({ category: 1, price: 1 });
productSchema.index({ name: 'text', description: 'text' });
// 虚拟字段
productSchema.virtual('isInStock').get(function() {
return this.stock > 0;
});
// 实例方法: 更新库存
productSchema.methods.updateStock = function(quantity) {
this.stock -= quantity;
if (this.stock < 0) this.stock = 0;
return this.save();
};
module.exports = mongoose.model('Product', productSchema);
步骤 3: 实现认证中间件
使用 CodeBuddy 生成认证中间件:
> @middlewares/auth.js 生成 JWT 认证中间件,包含:
- Token 验证
- 角色检查
- 错误处理
// src/middlewares/auth.js
const jwt = require('jsonwebtoken');
const User = require('../models/User');
// 验证 Token
exports.authenticate = async (req, res, next) => {
try {
const token = req.header('Authorization')?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({
success: false,
message: '未提供认证令牌'
});
}
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const user = await User.findById(decoded.id).select('-password');
if (!user || !user.isActive) {
return res.status(401).json({
success: false,
message: '用户不存在或已被禁用'
});
}
req.user = user;
next();
} catch (error) {
if (error.name === 'JsonWebTokenError') {
return res.status(401).json({
success: false,
message: '无效的令牌'
});
}
if (error.name === 'TokenExpiredError') {
return res.status(401).json({
success: false,
message: '令牌已过期'
});
}
return res.status(500).json({
success: false,
message: '认证失败',
error: error.message
});
}
};
// 角色授权
exports.authorize = (...roles) => {
return (req, res, next) => {
if (!roles.includes(req.user.role)) {
return res.status(403).json({
success: false,
message: `需要 ${roles.join(' 或 ')} 权限`
});
}
next();
};
};
// 可选认证(允许游客访问)
exports.optionalAuth = async (req, res, next) => {
try {
const token = req.header('Authorization')?.replace('Bearer ', '');
if (token) {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const user = await User.findById(decoded.id).select('-password');
if (user && user.isActive) {
req.user = user;
}
}
next();
} catch (error) {
// 忽略错误,继续执行
next();
}
};
步骤 4: 创建控制器
用户认证控制器:
// src/controllers/authController.js
const User = require('../models/User');
const crypto = require('crypto');
// 用户注册
exports.register = async (req, res) => {
try {
const { username, email, password, role } = req.body;
// 检查用户是否已存在
const existingUser = await User.findOne({
$or: [{ email }, { username }]
});
if (existingUser) {
return res.status(400).json({
success: false,
message: '用户名或邮箱已被使用'
});
}
// 创建用户
const user = await User.create({
username,
email,
password,
role: role || 'user'
});
// 生成 Token
const token = user.generateToken();
res.status(201).json({
success: true,
message: '注册成功',
data: {
user: {
id: user._id,
username: user.username,
email: user.email,
role: user.role
},
token
}
});
} catch (error) {
res.status(500).json({
success: false,
message: '注册失败',
error: error.message
});
}
};
// 用户登录
exports.login = async (req, res) => {
try {
const { email, password } = req.body;
// 查找用户(包含密码字段)
const user = await User.findOne({ email }).select('+password');
if (!user || !user.isActive) {
return res.status(401).json({
success: false,
message: '邮箱或密码错误'
});
}
// 验证密码
const isMatch = await user.comparePassword(password);
if (!isMatch) {
return res.status(401).json({
success: false,
message: '邮箱或密码错误'
});
}
// 生成 Token
const token = user.generateToken();
res.json({
success: true,
message: '登录成功',
data: {
user: {
id: user._id,
username: user.username,
email: user.email,
role: user.role
},
token
}
});
} catch (error) {
res.status(500).json({
success: false,
message: '登录失败',
error: error.message
});
}
};
// 获取当前用户信息
exports.getMe = async (req, res) => {
try {
const user = await User.findById(req.user.id);
res.json({
success: true,
data: {
user: {
id: user._id,
username: user.username,
email: user.email,
role: user.role,
createdAt: user.createdAt
}
}
});
} catch (error) {
res.status(500).json({
success: false,
message: '获取用户信息失败',
error: error.message
});
}
};
// 更新用户信息
exports.updateProfile = async (req, res) => {
try {
const { username, email } = req.body;
const user = await User.findById(req.user.id);
// 检查用户名/邮箱是否被占用
if (username && username !== user.username) {
const existingUser = await User.findOne({ username });
if (existingUser) {
return res.status(400).json({
success: false,
message: '用户名已被使用'
});
}
user.username = username;
}
if (email && email !== user.email) {
const existingUser = await User.findOne({ email });
if (existingUser) {
return res.status(400).json({
success: false,
message: '邮箱已被使用'
});
}
user.email = email;
}
await user.save();
res.json({
success: true,
message: '更新成功',
data: {
user: {
id: user._id,
username: user.username,
email: user.email,
role: user.role
}
}
});
} catch (error) {
res.status(500).json({
success: false,
message: '更新失败',
error: error.message
});
}
};
商品控制器:
// src/controllers/productController.js
const Product = require('../models/Product');
// 获取所有商品(支持分页、筛选、排序)
exports.getProducts = async (req, res) => {
try {
const { page = 1, limit = 10, category, minPrice, maxPrice, search, sort } = req.query;
// 构建查询条件
const query = { isActive: true };
if (category) {
query.category = category;
}
if (minPrice !== undefined || maxPrice !== undefined) {
query.price = {};
if (minPrice !== undefined) query.price.$gte = Number(minPrice);
if (maxPrice !== undefined) query.price.$lte = Number(maxPrice);
}
if (search) {
query.$text = { $search: search };
}
// 构建排序
let sortOption = {};
if (sort) {
const sortFields = sort.split(',');
sortFields.forEach(field => {
if (field.startsWith('-')) {
sortOption[field.substring(1)] = -1;
} else {
sortOption[field] = 1;
}
});
} else {
sortOption = { createdAt: -1 };
}
// 执行查询
const products = await Product.find(query)
.sort(sortOption)
.skip((page - 1) * limit)
.limit(Number(limit));
const total = await Product.countDocuments(query);
res.json({
success: true,
data: {
products,
pagination: {
page: Number(page),
limit: Number(limit),
total,
pages: Math.ceil(total / limit)
}
}
});
} catch (error) {
res.status(500).json({
success: false,
message: '获取商品列表失败',
error: error.message
});
}
};
// 获取单个商品详情
exports.getProduct = async (req, res) => {
try {
const product = await Product.findById(req.params.id);
if (!product || !product.isActive) {
return res.status(404).json({
success: false,
message: '商品不存在'
});
}
res.json({
success: true,
data: { product }
});
} catch (error) {
res.status(500).json({
success: false,
message: '获取商品详情失败',
error: error.message
});
}
};
// 创建商品(仅管理员)
exports.createProduct = async (req, res) => {
try {
const product = await Product.create({
...req.body,
createdBy: req.user.id
});
res.status(201).json({
success: true,
message: '商品创建成功',
data: { product }
});
} catch (error) {
res.status(500).json({
success: false,
message: '创建商品失败',
error: error.message
});
}
};
// 更新商品(仅管理员)
exports.updateProduct = async (req, res) => {
try {
const product = await Product.findByIdAndUpdate(
req.params.id,
req.body,
{ new: true, runValidators: true }
);
if (!product) {
return res.status(404).json({
success: false,
message: '商品不存在'
});
}
res.json({
success: true,
message: '商品更新成功',
data: { product }
});
} catch (error) {
res.status(500).json({
success: false,
message: '更新商品失败',
error: error.message
});
}
};
// 删除商品(仅管理员)
exports.deleteProduct = async (req, res) => {
try {
const product = await Product.findByIdAndUpdate(
req.params.id,
{ isActive: false },
{ new: true }
);
if (!product) {
return res.status(404).json({
success: false,
message: '商品不存在'
});
}
res.json({
success: true,
message: '商品删除成功'
});
} catch (error) {
res.status(500).json({
success: false,
message: '删除商品失败',
error: error.message
});
}
};
// 添加商品评论
exports.addReview = async (req, res) => {
try {
const { rating, comment } = req.body;
const product = await Product.findById(req.params.id);
if (!product) {
return res.status(404).json({
success: false,
message: '商品不存在'
});
}
// 检查是否已评论
const alreadyReviewed = product.reviews.find(
review => review.user.toString() === req.user.id.toString()
);
if (alreadyReviewed) {
return res.status(400).json({
success: false,
message: '您已经评论过该商品'
});
}
// 添加评论
product.reviews.push({
user: req.user.id,
rating,
comment
});
// 更新商品评分
product.rating = product.reviews.reduce((acc, item) => item.rating + acc, 0) / product.reviews.length;
await product.save();
res.json({
success: true,
message: '评论添加成功',
data: { product }
});
} catch (error) {
res.status(500).json({
success: false,
message: '添加评论失败',
error: error.message
});
}
};
步骤 5: 定义路由
// src/routes/authRoutes.js
const express = require('express');
const router = express.Router();
const { authenticate } = require('../middlewares/auth');
const authController = require('../controllers/authController');
router.post('/register', authController.register);
router.post('/login', authController.login);
router.get('/me', authenticate, authController.getMe);
router.put('/profile', authenticate, authController.updateProfile);
module.exports = router;
// src/routes/productRoutes.js
const express = require('express');
const router = express.Router();
const { authenticate, authorize } = require('../middlewares/auth');
const productController = require('../controllers/productController');
// 公开路由
router.get('/', productController.getProducts);
router.get('/:id', productController.getProduct);
// 需要认证的路由
router.post('/:id/reviews', authenticate, productController.addReview);
// 管理员路由
router.post('/', authenticate, authorize('admin'), productController.createProduct);
router.put('/:id', authenticate, authorize('admin'), productController.updateProduct);
router.delete('/:id', authenticate, authorize('admin'), productController.deleteProduct);
module.exports = router;
步骤 6: 主应用入口
// src/server.js
require('dotenv').config();
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
// 导入路由
const authRoutes = require('./routes/authRoutes');
const productRoutes = require('./routes/productRoutes');
// 创建 Express 应用
const app = express();
// 中间件
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// 请求日志中间件
app.use((req, res, next) => {
console.log(`${req.method} ${req.path} - ${new Date().toISOString()}`);
next();
});
// 健康检查
app.get('/health', (req, res) => {
res.json({ status: 'OK', timestamp: new Date() });
});
// API 路由
app.use('/api/auth', authRoutes);
app.use('/api/products', productRoutes);
// 404 处理
app.use((req, res) => {
res.status(404).json({
success: false,
message: '路由不存在'
});
});
// 错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(err.status || 500).json({
success: false,
message: err.message || '服务器内部错误',
...(process.env.NODE_ENV === 'development' && { stack: err.stack })
});
});
// 数据库连接
mongoose.connect(process.env.MONGODB_URI)
.then(() => console.log('MongoDB 连接成功'))
.catch(err => console.error('MongoDB 连接失败:', err));
// 启动服务器
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`服务器运行在端口 ${PORT}`);
});
module.exports = app;
步骤 7: 使用 CodeBuddy 生成测试
> @tests/auth.test.js 为认证控制器生成完整的单元测试
> @tests/product.test.js 为商品控制器生成完整的单元测试
生成的测试示例:
// tests/auth.test.js
const request = require('supertest');
const mongoose = require('mongoose');
const app = require('../src/server');
const User = require('../src/models/User');
describe('Auth API Tests', () => {
beforeAll(async () => {
await mongoose.connect(process.env.MONGODB_URI_TEST);
});
afterEach(async () => {
await User.deleteMany({});
});
afterAll(async () => {
await mongoose.connection.close();
});
describe('POST /api/auth/register', () => {
it('应该成功注册新用户', async () => {
const response = await request(app)
.post('/api/auth/register')
.send({
username: 'testuser',
email: 'test@example.com',
password: 'password123'
});
expect(response.status).toBe(201);
expect(response.body.success).toBe(true);
expect(response.body.data).toHaveProperty('token');
expect(response.body.data.user.email).toBe('test@example.com');
});
it('应该拒绝重复的邮箱', async () => {
await User.create({
username: 'user1',
email: 'test@example.com',
password: 'password123'
});
const response = await request(app)
.post('/api/auth/register')
.send({
username: 'user2',
email: 'test@example.com',
password: 'password123'
});
expect(response.status).toBe(400);
expect(response.body.message).toContain('已被使用');
});
it('应该验证密码长度', async () => {
const response = await request(app)
.post('/api/auth/register')
.send({
username: 'testuser',
email: 'test@example.com',
password: '123'
});
expect(response.status).toBe(400);
});
});
describe('POST /api/auth/login', () => {
beforeEach(async () => {
await User.create({
username: 'testuser',
email: 'test@example.com',
password: 'password123'
});
});
it('应该成功登录', async () => {
const response = await request(app)
.post('/api/auth/login')
.send({
email: 'test@example.com',
password: 'password123'
});
expect(response.status).toBe(200);
expect(response.body.success).toBe(true);
expect(response.body.data).toHaveProperty('token');
});
it('应该拒绝错误的密码', async () => {
const response = await request(app)
.post('/api/auth/login')
.send({
email: 'test@example.com',
password: 'wrongpassword'
});
expect(response.status).toBe(401);
expect(response.body.message).toContain('邮箱或密码错误');
});
});
describe('GET /api/auth/me', () => {
let token;
beforeEach(async () => {
const user = await User.create({
username: 'testuser',
email: 'test@example.com',
password: 'password123'
});
token = user.generateToken();
});
it('应该返回当前用户信息', async () => {
const response = await request(app)
.get('/api/auth/me')
.set('Authorization', `Bearer ${token}`);
expect(response.status).toBe(200);
expect(response.body.data.user.email).toBe('test@example.com');
});
it('应该拒绝没有 token 的请求', async () => {
const response = await request(app)
.get('/api/auth/me');
expect(response.status).toBe(401);
});
});
});
步骤 8: 使用自定义斜杠命令优化工作流
# 创建项目级命令
mkdir -p .codebuddy/commands
# 创建数据库重置命令
cat > .codebuddy/commands/reset-db.md << 'EOF'
清空数据库中的所有测试数据,并插入初始测试数据:
1. 创建 3 个测试用户(1 个管理员,2 个普通用户)
2. 创建 20 个测试商品(涵盖所有分类)
3. 返回所有创建的数据的详细信息
EOF
# 创建生成 API 文档命令
cat > .codebuddy/commands/gen-api-doc.md << 'EOF'
扫描所有路由文件,生成完整的 API 文档:
1. 提取所有路由端点
2. 生成请求示例
3. 生成响应示例
4. 输出 Markdown 格式文档
EOF
# 使用命令
/reset-db
/gen-api-doc
本案例关键点总结:
- ✅ 使用
/init初始化项目上下文 - ✅ 通过
@文件名精准引用相关文件 - ✅ 利用 CodeBuddy 自动生成模型、控制器、测试
- ✅ 使用自定义斜杠命令简化重复操作
- ✅ 生成完整的测试用例确保代码质量
- ✅ 自动化文档生成
案例 2: React 组件重构与优化
场景: 将一个复杂的、性能低下的 React 列表组件重构为高性能版本
原始代码(存在性能问题)
// src/components/UserList.jsx
import React, { useState, useEffect } from 'react';
import { getUserList } from '../api/user';
const UserList = ({ filters, onUserSelect }) => {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(false);
const [selectedUsers, setSelectedUsers] = useState(new Set());
// 问题 1: 不合理的依赖导致频繁重新渲染
useEffect(() => {
fetchUsers();
}, [filters, onUserSelect]); // onUserSelect 每次渲染都会改变
// 问题 2: 同步的 fetch 导致界面卡顿
const fetchUsers = async () => {
setLoading(true);
const data = await getUserList(filters);
setUsers(data);
setLoading(false);
};
// 问题 3: 每次渲染都创建新的函数和对象
const handleUserClick = (userId) => {
const newSelected = new Set(selectedUsers);
if (newSelected.has(userId)) {
newSelected.delete(userId);
} else {
newSelected.add(userId);
}
setSelectedUsers(newSelected);
};
// 问题 4: 没有使用虚拟滚动,大量数据时性能差
// 问题 5: 内联样式对象每次渲染都重新创建
return (
<div style={{ padding: '20px' }}>
{loading ? (
<div style={{ textAlign: 'center' }}>加载中...</div>
) : (
<div>
{users.map((user) => (
<div
key={user.id}
style={{
padding: '10px',
margin: '5px 0',
border: '1px solid #ddd',
cursor: 'pointer',
backgroundColor: selectedUsers.has(user.id) ? '#e6f7ff' : 'white'
}}
onClick={() => handleUserClick(user.id)}
>
<div style={{ fontWeight: 'bold' }}>{user.name}</div>
<div style={{ color: '#666' }}>{user.email}</div>
</div>
))}
</div>
)}
</div>
);
};
export default UserList;
使用 CodeBuddy 进行重构
步骤 1: 代码分析
codebuddy
> @src/components/UserList.jsx 分析这个组件的性能问题:
1. 识别所有导致不必要的重新渲染的原因
2. 找出内存泄漏的风险点
3. 评估在 1000+ 数据量下的性能表现
CodeBuddy 分析结果:
# UserList 组件性能分析报告
## 主要问题
1. **不合理的 useEffect 依赖**
- onUserSelect 作为依赖会导致每次父组件渲染时都重新获取数据
- 影响: 不必要的 API 调用和网络请求
2. **同步的数据处理**
- fetchUsers 在 useEffect 中同步调用
- 影响: 阻塞 UI 线程,导致界面卡顿
3. **函数重复创建**
- handleUserClick 每次渲染都创建新函数
- 影响: 子组件不必要的重新渲染
4. **缺少虚拟滚动**
- 直接渲染所有用户项
- 影响: 1000+ 数据时严重性能问题
5. **内联样式对象**
- 每个 item 都创建新的样式对象
- 影响: 增加内存分配和垃圾回收压力
6. **缺少请求取消**
- 组件卸载时未取消正在进行的请求
- 影响: 可能导致内存泄漏和状态更新错误
## 优化建议优先级
- 高优先级: 问题 4(虚拟滚动)、问题 6(请求取消)
- 中优先级: 问题 1(依赖优化)、问题 3(函数稳定化)
- 低优先级: 问题 2(异步处理)、问题 5(样式优化)
步骤 2: 使用 CodeBuddy 生成优化后的代码
> 基于以上分析,重构 UserList 组件:
1. 使用 useMemo 和 useCallback 优化性能
2. 添加请求取消功能
3. 实现虚拟滚动
4. 优化样式处理
5. 添加错误边界和加载状态优化
重构后的代码:
// src/components/UserList.jsx
import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import { getUserList } from '../api/user';
import VirtualizedList from './VirtualizedList';
import styles from './UserList.module.css';
// 使用常量避免重复创建
const LIST_ITEM_HEIGHT = 80;
const OVERSCAN_COUNT = 5;
const UserList = React.memo(({ filters, onUserSelect }) => {
// 状态管理
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [selectedUsers, setSelectedUsers] = useState(new Set());
const [totalCount, setTotalCount] = useState(0);
// Ref 用于存储取消令牌
const abortControllerRef = useRef(null);
// 优化: 使用 useCallback 稳定化函数
const handleUserClick = useCallback((userId) => {
setSelectedUsers(prev => {
const newSelected = new Set(prev);
if (newSelected.has(userId)) {
newSelected.delete(userId);
} else {
newSelected.add(userId);
}
return newSelected;
});
}, []);
// 优化: 稳定化的回调函数
const stableOnUserSelect = useCallback((user) => {
onUserSelect?.(user);
}, [onUserSelect]);
// 优化: 仅在 filters 变化时重新获取数据
const fetchUsers = useCallback(async (signal) => {
try {
setLoading(true);
setError(null);
const response = await getUserList(filters, { signal });
// 检查请求是否被取消
if (signal.aborted) return;
setUsers(response.users || []);
setTotalCount(response.totalCount || 0);
} catch (err) {
// 忽略取消错误
if (err.name === 'AbortError') return;
setError(err.message || '获取用户列表失败');
console.error('Fetch users error:', err);
} finally {
if (!signal.aborted) {
setLoading(false);
}
}
}, [filters]); // 仅依赖 filters
// 优化: 正确的依赖管理
useEffect(() => {
// 取消之前的请求
if (abortControllerRef.current) {
abortControllerRef.current.abort();
}
// 创建新的 AbortController
abortControllerRef.current = new AbortController();
const { signal } = abortControllerRef.current;
// 获取数据
fetchUsers(signal);
// 清理函数
return () => {
if (abortControllerRef.current) {
abortControllerRef.current.abort();
}
};
}, [fetchUsers]); // 仅依赖 fetchUsers
// 优化: 使用 useMemo 缓存计算结果
const listData = useMemo(() => {
return users.map(user => ({
id: user.id,
data: user,
isSelected: selectedUsers.has(user.id)
}));
}, [users, selectedUsers]);
// 优化: 渲染项组件
const renderItem = useCallback((item, index) => {
const { data: user, isSelected } = item;
return (
<div
className={`${styles.userItem} ${isSelected ? styles.selected : ''}`}
onClick={() => handleUserClick(user.id)}
onDoubleClick={() => stableOnUserSelect(user)}
>
<div className={styles.userName}>{user.name}</div>
<div className={styles.userEmail}>{user.email}</div>
<div className={styles.userMeta}>
<span>角色: {user.role}</span>
<span>状态: {user.isActive ? '活跃' : '禁用'}</span>
</div>
</div>
);
}, [handleUserClick, stableOnUserSelect]);
// 优化: 空状态和错误处理
if (error && !users.length) {
return (
<div className={styles.errorContainer}>
<div className={styles.errorIcon}>⚠️</div>
<div className={styles.errorMessage}>{error}</div>
<button
className={styles.retryButton}
onClick={() => fetchUsers(new AbortController().signal)}
>
重试
</button>
</div>
);
}
if (!loading && !users.length) {
return (
<div className={styles.emptyContainer}>
<div className={styles.emptyIcon}>📭</div>
<div className={styles.emptyMessage}>暂无用户数据</div>
</div>
);
}
return (
<div className={styles.container}>
{/* 统计信息 */}
<div className={styles.header}>
<span className={styles.totalCount}>
共 {totalCount} 位用户
</span>
<span className={styles.selectedCount}>
已选择 {selectedUsers.size} 位
</span>
</div>
{/* 加载状态 */}
{loading && (
<div className={styles.loadingOverlay}>
<div className={styles.spinner} />
<div className={styles.loadingText}>加载中...</div>
</div>
)}
{/* 虚拟滚动列表 */}
<VirtualizedList
items={listData}
renderItem={renderItem}
itemHeight={LIST_ITEM_HEIGHT}
overscanCount={OVERSCAN_COUNT}
className={styles.list}
/>
</div>
);
});
UserList.displayName = 'UserList';
export default UserList;
配套的样式文件:
/* src/components/UserList.module.css */
.container {
display: flex;
flex-direction: column;
height: 100%;
padding: 20px;
background: #f5f5f5;
}
.header {
display: flex;
justify-content: space-between;
padding: 12px 16px;
margin-bottom: 16px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.totalCount,
.selectedCount {
font-size: 14px;
color: #666;
font-weight: 500;
}
.selectedCount {
color: #1890ff;
}
.list {
flex: 1;
overflow-y: auto;
border-radius: 8px;
background: white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.userItem {
padding: 16px;
margin: 8px;
border: 1px solid #e8e8e8;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s ease;
background: white;
}
.userItem:hover {
border-color: #1890ff;
box-shadow: 0 2px 8px rgba(24, 144, 255, 0.15);
transform: translateY(-1px);
}
.userItem.selected {
background: #e6f7ff;
border-color: #1890ff;
}
.userName {
font-size: 16px;
font-weight: 600;
color: #333;
margin-bottom: 4px;
}
.userEmail {
font-size: 14px;
color: #666;
margin-bottom: 8px;
}
.userMeta {
display: flex;
gap: 16px;
font-size: 12px;
color: #999;
}
.loadingOverlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.9);
z-index: 10;
}
.spinner {
width: 32px;
height: 32px;
border: 3px solid #f0f0f0;
border-top-color: #1890ff;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.loadingText {
margin-top: 12px;
color: #666;
font-size: 14px;
}
.errorContainer,
.emptyContainer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60px 20px;
text-align: center;
}
.errorIcon,
.emptyIcon {
font-size: 48px;
margin-bottom: 16px;
}
.errorMessage,
.emptyMessage {
font-size: 16px;
color: #666;
margin-bottom: 20px;
}
.retryButton {
padding: 8px 24px;
background: #1890ff;
color: white;
border: none;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
transition: background 0.2s;
}
.retryButton:hover {
background: #40a9ff;
}
虚拟滚动组件:
// src/components/VirtualizedList.jsx
import React, { useState, useRef, useEffect, useCallback } from 'react';
import styles from './VirtualizedList.module.css';
const VirtualizedList = ({
items,
renderItem,
itemHeight,
overscanCount = 3,
className = ''
}) => {
const [scrollTop, setScrollTop] = useState(0);
const [containerHeight, setContainerHeight] = useState(0);
const containerRef = useRef(null);
// 监听容器大小变化
useEffect(() => {
const container = containerRef.current;
if (!container) return;
const resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
setContainerHeight(entry.contentRect.height);
}
});
resizeObserver.observe(container);
return () => resizeObserver.disconnect();
}, []);
// 处理滚动事件
const handleScroll = useCallback((e) => {
setScrollTop(e.target.scrollTop);
}, []);
// 计算可见范围
const { startIndex, endIndex } = useMemo(() => {
const visibleCount = Math.ceil(containerHeight / itemHeight);
const start = Math.max(0, Math.floor(scrollTop / itemHeight) - overscanCount);
const end = Math.min(
items.length - 1,
Math.ceil((scrollTop + containerHeight) / itemHeight) + overscanCount
);
return { startIndex: start, endIndex: end };
}, [scrollTop, containerHeight, itemHeight, overscanCount, items.length]);
// 计算总高度
const totalHeight = useMemo(() => {
return items.length * itemHeight;
}, [items.length, itemHeight]);
// 计算偏移量
const offsetY = useMemo(() => {
return startIndex * itemHeight;
}, [startIndex, itemHeight]);
// 获取可见项
const visibleItems = useMemo(() => {
return items.slice(startIndex, endIndex + 1);
}, [items, startIndex, endIndex]);
return (
<div
ref={containerRef}
className={`${styles.virtualList} ${className}`}
onScroll={handleScroll}
>
<div
className={styles.spacer}
style={{ height: totalHeight }}
>
<div
className={styles.content}
style={{
transform: `translateY(${offsetY}px)`
}}
>
{visibleItems.map((item, index) => (
<div
key={item.id || index}
style={{ height: itemHeight }}
>
{renderItem(item, startIndex + index)}
</div>
))}
</div>
</div>
</div>
);
};
export default VirtualizedList;
步骤 3: 使用 CodeBuddy 生成性能测试
> 为重构后的 UserList 组件生成性能测试:
1. 测试 1000+ 数据量下的渲染性能
2. 测试频繁筛选时的性能
3. 测试内存使用情况
4. 生成性能对比报告
生成的性能测试代码:
// src/components/__tests__/UserList.performance.test.jsx
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import UserList from '../UserList';
import * as userApi from '../../api/user';
// Mock API
jest.mock('../../api/user');
// 生成大量测试数据
const generateMockUsers = (count) => {
return Array.from({ length: count }, (_, i) => ({
id: `user-${i}`,
name: `用户 ${i + 1}`,
email: `user${i + 1}@example.com`,
role: i % 3 === 0 ? 'admin' : 'user',
isActive: i % 10 !== 0
}));
};
describe('UserList Performance Tests', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.useRealTimers();
});
describe('大规模数据渲染性能', () => {
it('应该在 100ms 内渲染 1000 条数据', async () => {
const mockUsers = generateMockUsers(1000);
userApi.getUserList.mockResolvedValue({
users: mockUsers,
totalCount: 1000
});
const startTime = performance.now();
render(<UserList filters={{}} />);
await waitFor(() => {
expect(screen.queryByText('加载中...')).not.toBeInTheDocument();
});
const endTime = performance.now();
const renderTime = endTime - startTime;
console.log(`1000 条数据渲染时间: ${renderTime.toFixed(2)}ms`);
expect(renderTime).toBeLessThan(100);
});
it('应该在 200ms 内渲染 10000 条数据', async () => {
const mockUsers = generateMockUsers(10000);
userApi.getUserList.mockResolvedValue({
users: mockUsers,
totalCount: 10000
});
const startTime = performance.now();
render(<UserList filters={{}} />);
await waitFor(() => {
expect(screen.queryByText('加载中...')).not.toBeInTheDocument();
});
const endTime = performance.now();
const renderTime = endTime - startTime;
console.log(`10000 条数据渲染时间: ${renderTime.toFixed(2)}ms`);
expect(renderTime).toBeLessThan(200);
});
});
describe('频繁筛选性能', () => {
it('应该在 50ms 内响应筛选变化', async () => {
const mockUsers = generateMockUsers(1000);
userApi.getUserList.mockResolvedValue({
users: mockUsers,
totalCount: 1000
});
const { rerender } = render(
<UserList filters={{ role: 'user' }} />
);
await waitFor(() => {
expect(screen.queryByText('加载中...')).not.toBeInTheDocument();
});
const startTime = performance.now();
// 快速切换筛选条件
for (let i = 0; i < 5; i++) {
rerender(<UserList filters={{ role: i % 2 === 0 ? 'user' : 'admin' }} />);
await waitFor(() => {
expect(screen.queryByText('加载中...')).not.toBeInTheDocument();
});
}
const endTime = performance.now();
const filterTime = endTime - startTime;
console.log(`5 次筛选切换总时间: ${filterTime.toFixed(2)}ms`);
expect(filterTime).toBeLessThan(250); // 平均每次 < 50ms
});
});
describe('内存使用', () => {
it('不应该有明显的内存泄漏', async () => {
const mockUsers = generateMockUsers(1000);
userApi.getUserList.mockResolvedValue({
users: mockUsers,
totalCount: 1000
});
const getMemoryUsage = () => {
if (performance.memory) {
return performance.memory.usedJSHeapSize;
}
return null;
};
const initialMemory = getMemoryUsage();
// 渲染和卸载多次
for (let i = 0; i < 10; i++) {
const { unmount } = render(<UserList filters={{}} />);
await waitFor(() => {
expect(screen.queryByText('加载中...')).not.toBeInTheDocument();
});
unmount();
}
// 等待垃圾回收
await new Promise(resolve => setTimeout(resolve, 1000));
const finalMemory = getMemoryUsage();
if (initialMemory && finalMemory) {
const memoryIncrease = (finalMemory - initialMemory) / 1024 / 1024;
console.log(`内存增长: ${memoryIncrease.toFixed(2)}MB`);
// 内存增长不应超过 10MB
expect(memoryIncrease).toBeLessThan(10);
}
});
});
describe('滚动性能', () => {
it('应该流畅滚动,不出现卡顿', async () => {
const mockUsers = generateMockUsers(10000);
userApi.getUserList.mockResolvedValue({
users: mockUsers,
totalCount: 10000
});
const { container } = render(<UserList filters={{}} />);
await waitFor(() => {
expect(screen.queryByText('加载中...')).not.toBeInTheDocument();
});
const listContainer = container.querySelector('.list');
const frameTimes = [];
let frameCount = 0;
const measureFrame = () => {
const start = performance.now();
return new Promise(resolve => {
requestAnimationFrame(() => {
const end = performance.now();
frameTimes.push(end - start);
frameCount++;
if (frameCount < 60) {
measureFrame().then(resolve);
} else {
resolve();
}
});
});
};
// 模拟滚动
if (listContainer) {
listContainer.scrollTop = 0;
for (let i = 0; i < 100; i++) {
listContainer.scrollTop = i * 100;
await new Promise(resolve => setTimeout(resolve, 16));
}
}
const avgFrameTime = frameTimes.reduce((a, b) => a + b, 0) / frameTimes.length;
console.log(`平均帧时间: ${avgFrameTime.toFixed(2)}ms`);
console.log(`预期 FPS: ${1000 / avgFrameTime.toFixed(0)}`);
// 平均帧时间应小于 16.67ms (60 FPS)
expect(avgFrameTime).toBeLessThan(16.67);
});
});
});
本案例关键点总结:
- ✅ 使用 CodeBuddy 深度分析性能问题
- ✅ 应用 React 性能优化最佳实践
- ✅ 实现虚拟滚动处理大数据量
- ✅ 使用 useMemo、useCallback、React.memo 优化
- ✅ 添加请求取消防止内存泄漏
- ✅ 生成完整的性能测试验证优化效果
案例 3: 自动化 CI/CD 工作流
场景: 使用 CodeBuddy Code 构建完整的 CI/CD 自动化流程
项目结构
project/
├── .github/
│ └── workflows/
│ ├── ci.yml
│ ├── cd.yml
│ └── code-review.yml
├── .codebuddy/
│ ├── commands/
│ │ ├── test.md
│ │ ├── build.md
│ │ └── deploy.md
│ └── agents/
│ └── ci-agent.yaml
├── src/
├── tests/
└── Dockerfile
步骤 1: 创建 CodeBuddy CI 智能体
# .codebuddy/agents/ci-agent.yaml
name: CI Agent
description: 专门用于 CI/CD 流程的智能体
system_prompt: |
你是 CI/CD 专家,专注于:
- 代码质量检查
- 自动化测试执行
- 构建和部署优化
- 性能监控和告警
capabilities:
- code_analysis
- test_execution
- build_optimization
- deployment_automation
tools:
- eslint
- jest
- docker
- kubernetes
步骤 2: 创建自定义命令
# 创建测试命令
cat > .codebuddy/commands/test.md << 'EOF'
执行完整的测试流程:
1. 运行单元测试,生成覆盖率报告
2. 运行集成测试
3. 运行端到端测试
4. 汇总测试结果
5. 如果测试失败,提供详细的失败原因分析
EOF
# 创建构建命令
cat > .codebuddy/commands/build.md << 'EOF'
执行构建流程:
1. 清理旧的构建产物
2. 执行依赖检查和安全扫描
3. 构建生产版本
4. 生成构建报告
5. 优化构建产物大小
EOF
# 创建部署命令
cat > .codebuddy/commands/deploy.md << 'EOF'
执行部署流程:
1. 验证部署前检查清单
2. 构建并推送 Docker 镜像
3. 更新 Kubernetes 部署配置
4. 执行灰度发布
5. 验证部署健康状态
6. 准备回滚方案
EOF
步骤 3: GitHub Actions CI 配置
# .github/workflows/ci.yml
name: CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
code-quality:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install CodeBuddy
run: npm install -g @tencent-ai/codebuddy-code
- name: Run CodeBuddy Code Review
run: |
codebuddy -p --dangerously-skip-permissions \
--agent ci-agent \
"对当前的代码变更进行全面审查,重点关注:
1. 代码规范问题
2. 潜在的安全漏洞
3. 性能问题
4. 测试覆盖率不足的文件
生成详细的审查报告" \
> code-review-report.txt
- name: Upload Code Review Report
uses: actions/upload-artifact@v3
with:
name: code-review-report
path: code-review-report.txt
- name: Comment PR with Review Results
if: github.event_name == 'pull_request'
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const report = fs.readFileSync('code-review-report.txt', 'utf8');
// 添加评论
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## 🤖 CodeBuddy 代码审查报告\n\n${report}`
});
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install CodeBuddy
run: npm install -g @tencent-ai/codebuddy-code
- name: Run tests with CodeBuddy
run: |
codebuddy -p --dangerously-skip-permissions \
"/test" \
> test-results.txt
- name: Upload test results
uses: actions/upload-artifact@v3
if: always()
with:
name: test-results
path: test-results.txt
- name: Upload coverage reports
uses: codecov/codecov-action@v3
if: always()
with:
files: ./coverage/lcov.info
security-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Run npm audit
run: npm audit --audit-level=moderate
- name: Install CodeBuddy
run: npm install -g @tencent-ai/codebuddy-code
- name: Run security scan with CodeBuddy
run: |
codebuddy -p --dangerously-skip-permissions \
"进行安全扫描,检查:
1. 硬编码的密钥和密码
2. SQL 注入风险
3. XSS 漏洞
4. 不安全的依赖
生成安全报告" \
> security-report.txt
- name: Upload security report
uses: actions/upload-artifact@v3
with:
name: security-report
path: security-report.txt
build:
runs-on: ubuntu-latest
needs: [code-quality, test, security-scan]
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install CodeBuddy
run: npm install -g @tencent-ai/codebuddy-code
- name: Build with CodeBuddy
run: |
codebuddy -p --dangerously-skip-permissions \
"/build" \
> build-report.txt
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: build-artifacts
path: dist/
- name: Upload build report
uses: actions/upload-artifact@v3
with:
name: build-report
path: build-report.txt
步骤 4: GitHub Actions CD 配置
# .github/workflows/cd.yml
name: CD Pipeline
on:
push:
branches: [main]
tags: ['v*']
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to Container Registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy-staging:
runs-on: ubuntu-latest
needs: build-and-push
if: github.ref == 'refs/heads/develop'
environment:
name: staging
url: https://staging.example.com
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install CodeBuddy
run: npm install -g @tencent-ai/codebuddy-code
- name: Deploy to staging
run: |
codebuddy -p --dangerously-skip-permissions \
"/deploy" \
--env staging \
> deploy-staging-report.txt
- name: Run smoke tests
run: |
curl -f https://staging.example.com/health || exit 1
- name: Upload deploy report
uses: actions/upload-artifact@v3
with:
name: deploy-staging-report
path: deploy-staging-report.txt
deploy-production:
runs-on: ubuntu-latest
needs: build-and-push
if: startsWith(github.ref, 'refs/tags/v')
environment:
name: production
url: https://example.com
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install CodeBuddy
run: npm install -g @tencent-ai/codebuddy-code
- name: Create deployment plan
run: |
codebuddy -p --dangerously-skip-permissions \
"为生产环境部署制定详细计划,包括:
1. 灰度发布策略
2. 监控指标
3. 回滚方案
4. 风险评估" \
> deployment-plan.txt
- name: Review deployment plan
run: cat deployment-plan.txt
- name: Deploy to production
run: |
codebuddy -p --dangerously-skip-permissions \
"/deploy" \
--env production \
--plan deployment-plan.txt \
> deploy-production-report.txt
- name: Run health checks
run: |
for i in {1..10}; do
if curl -f https://example.com/health; then
echo "Health check passed"
exit 0
fi
echo "Health check failed, retrying... ($i/10)"
sleep 30
done
echo "Health check failed after 10 attempts"
exit 1
- name: Monitor deployment
run: |
codebuddy -p --dangerously-skip-permissions \
"监控生产环境部署后的指标:
1. 错误率
2. 响应时间
3. 资源使用情况
持续监控 30 分钟" \
--duration 30m
- name: Notify team
if: always()
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const report = fs.readFileSync('deploy-production-report.txt', 'utf8');
// 发送通知(可以使用 Slack、Teams 等)
console.log('Deployment notification:', report);
步骤 5: 创建 Dockerfile
# 使用 CodeBuddy 优化的 Dockerfile
FROM node:18-alpine AS builder
# 安装 CodeBuddy
RUN npm install -g @tencent-ai/codebuddy-code
# 设置工作目录
WORKDIR /app
# 复制依赖文件
COPY package*.json ./
# 使用 CodeBuddy 优化依赖安装
RUN codebuddy -p "分析 package.json,优化依赖安装策略" && \
npm ci --only=production
# 复制源代码
COPY . .
# 使用 CodeBuddy 进行构建优化
RUN codebuddy -p "/build" && \
npm run build
# 生产镜像
FROM node:18-alpine
WORKDIR /app
# 复制构建产物
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node healthcheck.js || exit 1
# 启动应用
CMD ["node", "dist/server.js"]
步骤 6: Kubernetes 部署配置
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
labels:
app: myapp
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
version: v1.0.0
spec:
containers:
- name: app
image: ghcr.io/username/myapp:latest
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: "production"
- name: PORT
value: "3000"
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: app-service
spec:
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: LoadBalancer
步骤 7: 使用 CodeBuddy 生成监控脚本
codebuddy -p "生成 Kubernetes 监控脚本,包括:
1. Pod 健康状态检查
2. 资源使用监控
3. 日志聚合
4. 告警配置" \
> k8s/monitor.sh
生成的监控脚本:
#!/bin/bash
# k8s/monitor.sh
NAMESPACE="production"
APP_NAME="myapp"
echo "📊 开始监控应用..."
# 获取 Pod 状态
echo "📋 Pod 状态:"
kubectl get pods -n $NAMESPACE -l app=$APP_NAME
# 获取资源使用
echo "💾 资源使用情况:"
kubectl top pods -n $NAMESPACE -l app=$APP_NAME
# 检查日志
echo "📝 最近日志:"
kubectl logs -n $NAMESPACE -l app=$APP_NAME --tail=50
# 检查事件
echo "⚠️ 最近事件:"
kubectl get events -n $NAMESPACE --sort-by='.lastTimestamp' | tail -20
# 检查 HPA 状态
echo "📈 HPA 状态:"
kubectl get hpa -n $NAMESPACE
# 健康检查
echo "🏥 健康检查:"
kubectl exec -n $NAMESPACE -l app=$APP_NAME -- curl -f http://localhost:3000/health
echo "✅ 监控完成!"
本案例关键点总结:
- ✅ 使用 CodeBuddy 智能体自动化 CI/CD 流程
- ✅ 创建自定义命令封装复杂操作
- ✅ 集成 CodeBuddy 到 GitHub Actions
- ✅ 自动化代码审查、测试、构建、部署
- ✅ 实现灰度发布和回滚机制
- ✅ 生成监控和告警脚本
总结与进阶路径
掌握层次
| 层次 | 技能 | 标志 |
|---|---|---|
| 入门 | 基础补全、对话交互 | 能独立完成日常编码任务 |
| 熟练 | 自定义命令、MCP 集成 | 能优化团队工作流 |
| 精通 | 智能体开发、RAG 构建 | 能构建企业级解决方案 |
| 专家 | 性能优化、架构设计 | 能主导 AI 编程转型 |
持续学习资源
开启你的 AI 编程进阶之旅! 🚀
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)