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

350 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 步骤3代码质量检查
## ⚠️ 执行前必读规范
**🔥 重要在执行本步骤之前AI必须先完整阅读同级目录下的 `README.md` 文件!**
该README文件包含
- 🎯 执行前准备和用户信息收集要求
- 🔄 强制执行原则和分步执行流程
- 🔥 修改后立即重新执行当前步骤的强制规则
- 📝 文件修改记录规范和版本号递增规则
- 🧪 测试文件调试规范和测试指令使用规范
- 🚨 全局约束和游戏服务器特殊要求
**不阅读README直接执行步骤将导致执行不规范违反项目要求**
---
## 🎯 检查目标
清理和优化代码质量消除未使用代码、规范常量定义、处理TODO项。
## 🧹 未使用代码清理
### 清理未使用的导入
```typescript
// ❌ 错误:导入未使用的模块
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';
```
### 清理未使用的变量
```typescript
// ❌ 错误:定义但未使用的变量
const unusedVariable = 'test';
let tempData = [];
// ✅ 正确:删除未使用的变量
// 只保留实际使用的变量
```
### 清理未使用的方法
```typescript
// ❌ 错误:定义但未调用的私有方法
private generateVerificationCode(): string {
// 如果这个方法没有被调用,应该删除
}
// ✅ 正确:删除未使用的私有方法
// 或者确保方法被正确调用
```
## 📊 常量定义规范
### 使用SCREAMING_SNAKE_CASE
```typescript
// ✅ 正确:使用全大写+下划线
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;
```
### 提取魔法数字为常量
```typescript
// ❌ 错误:使用魔法数字
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行
- **原则**:一个方法只做一件事
- **拆分**:复杂方法拆分为多个小方法
### 方法拆分示例
```typescript
// ❌ 错误方法过长超过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> {
// 邮箱检查逻辑
}
```
## 🔄 代码重复消除
### 识别重复代码
```typescript
// ❌ 错误:重复的验证逻辑
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处理
```typescript
// ❌ 错误包含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连接管理
```typescript
// ✅ 正确:完整的连接管理
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 {
// 心跳检测逻辑
}
}
```
### 双模式服务质量
```typescript
// ✅ 正确:确保两种模式行为一致
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 {
// 与数据库模式相同的实体构建逻辑
}
}
```
### 属性测试质量
```typescript
// ✅ 正确:完整的属性测试实现
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字段
-**仅提供检查报告**:说明检查结果,确认符合规范
**不能跳过重新检查环节!**