Files
whale-town-end/docs/ai-reading/step3-code-quality.md
moyin 5af44f95d5 style: 完善代码规范和测试覆盖
- 新增多个模块的单元测试文件,提升测试覆盖率
- 完善AI-Reading文档系统,包含7步代码检查流程
- 新增集成测试和属性测试框架
- 优化项目结构和配置文件
- 清理过时的规范文档,统一使用新的检查标准
2026-01-12 20:09:03 +08:00

9.7 KiB
Raw Blame History

步骤3代码质量检查

⚠️ 执行前必读规范

🔥 重要在执行本步骤之前AI必须先完整阅读同级目录下的 README.md 文件!

该README文件包含

  • 🎯 执行前准备和用户信息收集要求
  • 🔄 强制执行原则和分步执行流程
  • 🔥 修改后立即重新执行当前步骤的强制规则
  • 📝 文件修改记录规范和版本号递增规则
  • 🧪 测试文件调试规范和测试指令使用规范
  • 🚨 全局约束和游戏服务器特殊要求

不阅读README直接执行步骤将导致执行不规范违反项目要求


🎯 检查目标

清理和优化代码质量消除未使用代码、规范常量定义、处理TODO项。

🧹 未使用代码清理

清理未使用的导入

// ❌ 错误:导入未使用的模块
import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
import { User, Admin } from './user.entity';
import * as crypto from 'crypto'; // 未使用
import { RedisService } from '../redis/redis.service'; // 未使用

// ✅ 正确:只导入使用的模块
import { Injectable, NotFoundException } from '@nestjs/common';
import { User } from './user.entity';

清理未使用的变量

// ❌ 错误:定义但未使用的变量
const unusedVariable = 'test';
let tempData = [];

// ✅ 正确:删除未使用的变量
// 只保留实际使用的变量

清理未使用的方法

// ❌ 错误:定义但未调用的私有方法
private generateVerificationCode(): string {
  // 如果这个方法没有被调用,应该删除
}

// ✅ 正确:删除未使用的私有方法
// 或者确保方法被正确调用

📊 常量定义规范

使用SCREAMING_SNAKE_CASE

// ✅ 正确:使用全大写+下划线
const SALT_ROUNDS = 10;
const MAX_LOGIN_ATTEMPTS = 5;
const DEFAULT_PAGE_SIZE = 20;
const WEBSOCKET_TIMEOUT = 30000;
const MAX_ROOM_CAPACITY = 100;

// ❌ 错误:使用小驼峰
const saltRounds = 10;
const maxLoginAttempts = 5;
const defaultPageSize = 20;

提取魔法数字为常量

// ❌ 错误:使用魔法数字
if (attempts > 5) {
  throw new Error('Too many attempts');
}
setTimeout(callback, 30000);

// ✅ 正确:提取为常量
const MAX_LOGIN_ATTEMPTS = 5;
const WEBSOCKET_TIMEOUT = 30000;

if (attempts > MAX_LOGIN_ATTEMPTS) {
  throw new Error('Too many attempts');
}
setTimeout(callback, WEBSOCKET_TIMEOUT);

📏 方法长度检查

长度限制

  • 建议方法不超过50行
  • 原则:一个方法只做一件事
  • 拆分:复杂方法拆分为多个小方法

方法拆分示例

// ❌ 错误方法过长超过50行
async processUserRegistration(userData: CreateUserDto): Promise<User> {
  // 验证用户数据
  // 检查邮箱是否存在
  // 生成密码哈希
  // 创建用户记录
  // 发送欢迎邮件
  // 记录操作日志
  // 返回用户信息
  // ... 超过50行的复杂逻辑
}

// ✅ 正确:拆分为多个小方法
async processUserRegistration(userData: CreateUserDto): Promise<User> {
  await this.validateUserData(userData);
  await this.checkEmailExists(userData.email);
  const hashedPassword = await this.generatePasswordHash(userData.password);
  const user = await this.createUserRecord({ ...userData, password: hashedPassword });
  await this.sendWelcomeEmail(user.email);
  await this.logUserRegistration(user.id);
  return user;
}

private async validateUserData(userData: CreateUserDto): Promise<void> {
  // 验证逻辑
}

private async checkEmailExists(email: string): Promise<void> {
  // 邮箱检查逻辑
}

🔄 代码重复消除

识别重复代码

// ❌ 错误:重复的验证逻辑
async createUser(userData: CreateUserDto): Promise<User> {
  if (!userData.email || !userData.name) {
    throw new BadRequestException('Required fields missing');
  }
  if (!this.isValidEmail(userData.email)) {
    throw new BadRequestException('Invalid email format');
  }
  // 创建用户逻辑
}

async updateUser(id: string, userData: UpdateUserDto): Promise<User> {
  if (!userData.email || !userData.name) {
    throw new BadRequestException('Required fields missing');
  }
  if (!this.isValidEmail(userData.email)) {
    throw new BadRequestException('Invalid email format');
  }
  // 更新用户逻辑
}

// ✅ 正确:抽象为可复用方法
async createUser(userData: CreateUserDto): Promise<User> {
  this.validateUserData(userData);
  // 创建用户逻辑
}

async updateUser(id: string, userData: UpdateUserDto): Promise<User> {
  this.validateUserData(userData);
  // 更新用户逻辑
}

private validateUserData(userData: CreateUserDto | UpdateUserDto): void {
  if (!userData.email || !userData.name) {
    throw new BadRequestException('Required fields missing');
  }
  if (!this.isValidEmail(userData.email)) {
    throw new BadRequestException('Invalid email format');
  }
}

🚫 TODO项处理强制要求

处理原则

最终文件不能包含TODO项,必须:

  1. 真正实现功能
  2. 删除未完成代码

常见TODO处理

// ❌ 错误包含TODO项的代码
async getUserProfile(id: string): Promise<UserProfile> {
  // TODO: 实现用户档案查询
  throw new Error('Not implemented');
}

async sendSmsVerification(phone: string): Promise<void> {
  // TODO: 集成短信服务提供商
  throw new Error('SMS service not implemented');
}

// ✅ 正确:真正实现功能
async getUserProfile(id: string): Promise<UserProfile> {
  const profile = await this.userProfileRepository.findOne({ 
    where: { userId: id } 
  });
  
  if (!profile) {
    throw new NotFoundException('用户档案不存在');
  }
  
  return profile;
}

// ✅ 正确:如果功能不需要,删除方法
// 删除sendSmsVerification方法及其调用

🎮 游戏服务器特殊质量要求

WebSocket连接管理

// ✅ 正确:完整的连接管理
const MAX_CONNECTIONS_PER_ROOM = 100;
const CONNECTION_TIMEOUT = 30000;
const HEARTBEAT_INTERVAL = 10000;

@WebSocketGateway()
export class LocationBroadcastGateway {
  private readonly connections = new Map<string, Socket>();
  
  handleConnection(client: Socket): void {
    this.validateConnection(client);
    this.setupHeartbeat(client);
    this.trackConnection(client);
  }
  
  private validateConnection(client: Socket): void {
    // 连接验证逻辑
  }
  
  private setupHeartbeat(client: Socket): void {
    // 心跳检测逻辑
  }
}

双模式服务质量

// ✅ 正确:确保两种模式行为一致
const DEFAULT_USER_STATUS = UserStatus.PENDING;
const MAX_BATCH_SIZE = 1000;

@Injectable()
export class UsersMemoryService {
  private readonly users = new Map<string, User>();
  
  async create(userData: CreateUserDto): Promise<User> {
    this.validateUserData(userData);
    const user = this.buildUserEntity(userData);
    this.users.set(user.id, user);
    return user;
  }
  
  private validateUserData(userData: CreateUserDto): void {
    // 与数据库模式相同的验证逻辑
  }
  
  private buildUserEntity(userData: CreateUserDto): User {
    // 与数据库模式相同的实体构建逻辑
  }
}

属性测试质量

// ✅ 正确:完整的属性测试实现
import * as fc from 'fast-check';

const PROPERTY_TEST_RUNS = 1000;
const MAX_USER_ID = 1000000;

describe('AdminService Properties', () => {
  it('should handle any valid user status update', () => {
    fc.assert(fc.property(
      fc.integer({ min: 1, max: MAX_USER_ID }),
      fc.constantFrom(...Object.values(UserStatus)),
      async (userId, status) => {
        try {
          const result = await adminService.updateUserStatus(userId, status);
          expect(result).toBeDefined();
          expect(result.status).toBe(status);
        } catch (error) {
          expect(error).toBeInstanceOf(NotFoundException || BadRequestException);
        }
      }
    ), { numRuns: PROPERTY_TEST_RUNS });
  });
});

🔍 检查执行步骤

  1. 扫描未使用的导入

    • 检查每个import语句是否被使用
    • 删除未使用的导入
  2. 扫描未使用的变量和方法

    • 检查变量是否被引用
    • 检查私有方法是否被调用
    • 删除未使用的代码
  3. 检查常量定义

    • 识别魔法数字和字符串
    • 提取为SCREAMING_SNAKE_CASE常量
    • 确保常量命名清晰
  4. 检查方法长度

    • 统计每个方法的行数
    • 识别超过50行的方法
    • 建议拆分复杂方法
  5. 识别重复代码

    • 查找相似的代码块
    • 抽象为可复用的工具方法
    • 消除代码重复
  6. 处理所有TODO项

    • 搜索所有TODO注释
    • 要求真正实现功能或删除代码
    • 确保最终文件无TODO项
  7. 游戏服务器特殊检查

    • WebSocket连接管理完整性
    • 双模式服务行为一致性
    • 属性测试实现质量

🔥 重要提醒

如果在本步骤中执行了任何修改操作删除未使用代码、提取常量、实现TODO项等必须立即重新执行步骤3的完整检查

  • 执行修改 → 🔥 立即重新执行步骤3 → 提供验证报告 → 等待用户确认
  • 执行修改 → 直接进入步骤4错误做法

🚨 重要强调:纯检查步骤不更新修改记录 如果检查发现代码质量已经符合规范,无需任何修改,则:

  • 禁止添加检查记录:不要添加"AI代码检查步骤3代码质量检查和优化"
  • 禁止更新时间戳:不要修改@lastModified字段
  • 禁止递增版本号:不要修改@version字段
  • 仅提供检查报告:说明检查结果,确认符合规范

不能跳过重新检查环节!