# 步骤4:架构分层检查 ## ⚠️ 执行前必读规范 **🔥 重要:在执行本步骤之前,AI必须先完整阅读同级目录下的 `README.md` 文件!** 该README文件包含: - 🎯 执行前准备和用户信息收集要求 - 🔄 强制执行原则和分步执行流程 - 🔥 修改后立即重新执行当前步骤的强制规则 - 📝 文件修改记录规范和版本号递增规则 - 🧪 测试文件调试规范和测试指令使用规范 - 🚨 全局约束和游戏服务器特殊要求 **不阅读README直接执行步骤将导致执行不规范,违反项目要求!** --- ## 🎯 检查目标 检查架构分层的合规性,确保Core层和Business层职责清晰、依赖关系正确。 ## 🏗️ 架构层级识别 ### 项目分层结构 ``` src/ ├── gateway/ # Gateway层:网关层(HTTP协议处理) │ ├── auth/ # 认证网关 │ ├── users/ # 用户网关 │ └── admin/ # 管理网关 ├── business/ # Business层:业务逻辑层 │ ├── auth/ # 认证业务 │ ├── users/ # 用户业务 │ └── admin/ # 管理业务 ├── core/ # Core层:技术实现层 │ ├── db/ # 数据访问 │ ├── redis/ # 缓存服务 │ └── utils/ # 工具服务 └── common/ # 公共层:通用组件 ``` ### 4层架构说明 **Gateway Layer(网关层)** - 位置:`src/gateway/` - 职责:HTTP协议处理、数据验证、路由管理、认证守卫、错误转换 - 依赖:Business层 **Business Layer(业务层)** - 位置:`src/business/` - 职责:业务逻辑实现、业务流程控制、服务协调、业务规则验证 - 依赖:Core层 **Core Layer(核心层)** - 位置:`src/core/` - 职责:数据访问、基础设施、外部系统集成、技术实现细节 - 依赖:无(或第三方库) ### 检查范围 - **限制范围**:仅检查当前执行检查的文件夹 - **不跨模块**:不考虑其他同层功能模块 - **专注职责**:确保当前模块职责清晰 - **按层检查**:根据文件夹所在层级应用对应的检查规则 ## 🌐 Gateway层规范检查 ### 职责定义 **Gateway层专注HTTP协议处理,不包含业务逻辑** ### Gateway层协议处理示例 ```typescript // ✅ 正确:Gateway层只做协议转换 @Controller('auth') export class LoginController { constructor(private readonly loginService: LoginService) {} @Post('login') async login(@Body() loginDto: LoginDto, @Res() res: Response): Promise { // 1. 接收HTTP请求,使用DTO验证 // 2. 调用Business层服务 const result = await this.loginService.login({ identifier: loginDto.identifier, password: loginDto.password }); // 3. 将业务响应转换为HTTP响应 this.handleResponse(result, res); } private handleResponse(result: any, res: Response): void { if (result.success) { res.status(HttpStatus.OK).json(result); } else { const statusCode = this.getErrorStatusCode(result); res.status(statusCode).json(result); } } } // ❌ 错误:Gateway层包含业务逻辑 @Controller('auth') export class LoginController { @Post('login') async login(@Body() loginDto: LoginDto): Promise { // 错误:在Controller中实现业务逻辑 const user = await this.userRepository.findOne({ where: { username: loginDto.identifier } }); if (!user) { throw new NotFoundException('用户不存在'); } const isValid = await bcrypt.compare(loginDto.password, user.password); if (!isValid) { throw new UnauthorizedException('密码错误'); } // ... 更多业务逻辑 } } ``` ### Gateway层依赖关系检查 ```typescript // ✅ 允许的导入 import { Controller, Post, Body, Res } from '@nestjs/common'; # NestJS框架 import { Response } from 'express'; # Express类型 import { LoginService } from '../../business/auth/login.service'; # Business层服务 import { LoginDto } from './dto/login.dto'; # 同层DTO import { JwtAuthGuard } from './jwt_auth.guard'; # 同层Guard // ❌ 禁止的导入 import { LoginCoreService } from '../../core/login_core/login_core.service'; # 跳过Business层直接调用Core层 import { UsersRepository } from '../../core/db/users/users.repository'; # 直接访问数据层 import { RedisService } from '../../core/redis/redis.service'; # 直接访问技术服务 ``` ### Gateway层文件类型检查 ```typescript // ✅ Gateway层应该包含的文件类型 - *.controller.ts # HTTP控制器 - *.dto.ts # 数据传输对象 - *.guard.ts # 认证/授权守卫 - *.decorator.ts # 参数装饰器 - *.interceptor.ts # 拦截器 - *.filter.ts # 异常过滤器 - *.gateway.module.ts # 网关模块 // ❌ Gateway层不应该包含的文件类型 - *.service.ts # 业务服务(应在Business层) - *.repository.ts # 数据仓库(应在Core层) - *.entity.ts # 数据实体(应在Core层) ``` ### Gateway层职责检查清单 - [ ] Controller方法是否只做协议转换? - [ ] 是否使用DTO进行数据验证? - [ ] 是否调用Business层服务而非Core层? - [ ] 是否有统一的错误处理机制? - [ ] 是否包含Swagger API文档? - [ ] 是否使用限流和超时保护? ## 🔧 Core层规范检查 ### 职责定义 **Core层专注技术实现,不包含业务逻辑** ### 命名规范检查 #### 业务支撑模块(使用_core后缀) 专门为特定业务功能提供技术支撑: ```typescript ✅ 正确示例: src/core/location_broadcast_core/ # 为位置广播业务提供技术支撑 src/core/admin_core/ # 为管理员业务提供技术支撑 src/core/user_auth_core/ # 为用户认证业务提供技术支撑 src/core/zulip_core/ # 为Zulip集成提供技术支撑 ❌ 错误示例: src/core/location_broadcast/ # 应该是location_broadcast_core src/core/admin/ # 应该是admin_core ``` #### 通用工具模块(不使用后缀) 提供可复用的数据访问或技术服务: ```typescript ✅ 正确示例: src/core/db/user_profiles/ # 通用的用户档案数据访问 src/core/redis/ # 通用的Redis技术封装 src/core/utils/logger/ # 通用的日志工具服务 src/core/db/zulip_accounts/ # 通用的Zulip账户数据访问 ❌ 错误示例: src/core/db/user_profiles_core/ # 应该是user_profiles(通用工具) src/core/redis_core/ # 应该是redis(通用工具) ``` ### 命名判断流程 ``` 1. 模块是否专门为某个特定业务功能服务? ├─ 是 → 检查模块名称是否体现业务领域 │ ├─ 是 → 使用 _core 后缀 │ └─ 否 → 重新设计模块职责 └─ 否 → 模块是否提供通用的技术服务? ├─ 是 → 不使用 _core 后缀 └─ 否 → 重新评估模块定位 2. 实际案例判断: - user_profiles: 通用的用户档案数据访问 → 不使用后缀 ✓ - location_broadcast_core: 专门为位置广播业务服务 → 使用_core后缀 ✓ - redis: 通用的缓存技术服务 → 不使用后缀 ✓ - zulip_core: 专门为Zulip集成业务服务 → 使用_core后缀 ✓ ``` ### Core层技术实现示例 ```typescript // ✅ 正确:Core层专注技术实现 @Injectable() export class LocationBroadcastCoreService { /** * 广播位置更新到指定房间 * * 技术实现: * 1. 验证WebSocket连接状态 * 2. 序列化位置数据 * 3. 通过Socket.IO广播消息 * 4. 记录广播性能指标 * 5. 处理广播异常和重试 */ async broadcastToRoom(roomId: string, data: PositionData): Promise { const room = this.server.sockets.adapter.rooms.get(roomId); if (!room) { throw new NotFoundException(`Room ${roomId} not found`); } this.server.to(roomId).emit('position-update', data); this.metricsService.recordBroadcast(roomId, data.userId); } } // ❌ 错误:Core层包含业务逻辑 @Injectable() export class LocationBroadcastCoreService { async broadcastUserPosition(userId: string, position: Position): Promise { // 错误:包含了用户权限检查的业务概念 const user = await this.userService.findById(userId); if (user.status !== UserStatus.ACTIVE) { throw new ForbiddenException('用户状态不允许位置广播'); } } } ``` ### Core层依赖关系检查 ```typescript // ✅ 允许的导入 import { Injectable } from '@nestjs/common'; # NestJS框架 import { Server } from 'socket.io'; # 第三方技术库 import { RedisService } from '../redis/redis.service'; # 其他Core层模块 import * as crypto from 'crypto'; # Node.js内置模块 // ❌ 禁止的导入 import { UserBusinessService } from '../../business/users/user.service'; # Business层模块 import { AdminController } from '../../business/admin/admin.controller'; # Business层模块 ``` ## 💼 Business层规范检查 ### 职责定义 **Business层专注业务逻辑实现,不关心底层技术细节** ### 业务逻辑完备性检查 ```typescript // ✅ 正确:完整的业务逻辑 @Injectable() export class UserBusinessService { /** * 用户注册业务流程 * * 业务逻辑: * 1. 验证用户信息完整性 * 2. 检查用户名/邮箱是否已存在 * 3. 验证邮箱格式和域名白名单 * 4. 生成用户唯一标识 * 5. 设置默认用户权限 * 6. 发送欢迎邮件 * 7. 记录注册日志 * 8. 返回注册结果 */ async registerUser(registerData: RegisterUserDto): Promise { await this.validateUserBusinessRules(registerData); const user = await this.userCoreService.create(registerData); await this.emailService.sendWelcomeEmail(user.email); await this.logService.recordUserRegistration(user.id); return this.buildUserResult(user); } } // ❌ 错误:业务逻辑不完整 @Injectable() export class UserBusinessService { async registerUser(registerData: RegisterUserDto): Promise { // 只是简单调用数据库保存,缺少业务验证和流程 return this.userRepository.save(registerData); } } ``` ### Business层依赖关系检查 ```typescript // ✅ 允许的导入 import { UserCoreService } from '../../core/user_auth_core/user_core.service'; # 对应Core层业务支撑 import { CacheService } from '../../core/redis/cache.service'; # Core层通用工具 import { EmailService } from '../../core/utils/email.service'; # Core层通用工具 import { OtherBusinessService } from '../other/other.service'; # 其他Business层(谨慎) // ❌ 禁止的导入 import { createConnection } from 'typeorm'; # 直接技术实现 import * as Redis from 'ioredis'; # 直接技术实现 import { DatabaseConnection } from '../../core/db/connection'; # 底层技术细节 ``` ## 🚨 常见架构违规 ### Gateway层违规示例 ```typescript // ❌ 错误:Gateway层包含业务逻辑 @Controller('users') export class UserController { @Post('register') async register(@Body() registerDto: RegisterDto): Promise { // 违规:在Controller中实现业务验证 if (registerDto.age < 18) { throw new BadRequestException('用户年龄必须大于18岁'); } // 违规:在Controller中协调多个服务 const user = await this.userCoreService.create(registerDto); await this.emailService.sendWelcomeEmail(user.email); await this.zulipService.createAccount(user); return user; } } // ❌ 错误:Gateway层直接调用Core层 @Controller('auth') export class LoginController { constructor( private readonly loginCoreService: LoginCoreService, // 违规:跳过Business层 ) {} @Post('login') async login(@Body() loginDto: LoginDto): Promise { // 违规:直接调用Core层服务 return this.loginCoreService.login(loginDto); } } ``` ### Business层违规示例 ```typescript // ❌ 错误:Business层包含技术实现细节 @Injectable() export class UserBusinessService { async createUser(userData: CreateUserDto): Promise { // 违规:直接操作Redis连接 const redis = new Redis({ host: 'localhost', port: 6379 }); await redis.set(`user:${userData.id}`, JSON.stringify(userData)); // 违规:直接写SQL语句 const sql = 'INSERT INTO users (name, email) VALUES (?, ?)'; await this.database.query(sql, [userData.name, userData.email]); } } ``` ### Core层违规示例 ```typescript // ❌ 错误:Core层包含业务逻辑 @Injectable() export class DatabaseService { async saveUser(userData: CreateUserDto): Promise { // 违规:包含用户注册的业务验证 if (userData.age < 18) { throw new BadRequestException('用户年龄必须大于18岁'); } // 违规:包含业务规则 if (userData.email.endsWith('@competitor.com')) { throw new ForbiddenException('不允许竞争对手注册'); } } } ``` ## 🎮 游戏服务器架构特殊检查 ### WebSocket Gateway分层 ```typescript // ✅ 正确:Gateway在Business层,调用Core层服务 @WebSocketGateway() export class LocationBroadcastGateway { constructor( private readonly locationBroadcastCore: LocationBroadcastCoreService, private readonly userProfiles: UserProfilesService, ) {} @SubscribeMessage('position_update') async handlePositionUpdate(client: Socket, data: PositionData): Promise { // 业务逻辑:验证、权限检查 await this.validateUserPermission(client.userId); // 调用Core层技术实现 await this.locationBroadcastCore.broadcastToRoom(client.roomId, data); } } ``` ### 双模式服务分层 ```typescript // ✅ 正确:Business层统一接口,Core层不同实现 @Injectable() export class UsersBusinessService { constructor( @Inject('USERS_SERVICE') private readonly usersCore: UsersMemoryService | UsersDatabaseService, ) {} async createUser(userData: CreateUserDto): Promise { // 业务逻辑:验证、权限、流程 await this.validateUserBusinessRules(userData); // 调用Core层(内存或数据库模式) const user = await this.usersCore.create(userData); // 业务逻辑:后续处理 await this.sendWelcomeNotification(user); return user; } } ``` ## 🔧 NestJS依赖注入检查(重要) ### 依赖注入完整性检查 **在NestJS中,如果一个类(如Guard、Service、Controller)需要注入其他服务,必须确保该服务在模块的imports中可访问。** ### 常见依赖注入问题 ```typescript // ❌ 错误:JwtAuthGuard需要LoginCoreService,但模块未导入LoginCoreModule @Module({ imports: [ AuthModule, // AuthModule虽然导入了LoginCoreModule,但没有重新导出 ], providers: [ JwtAuthGuard, // 错误:无法注入LoginCoreService ], }) export class AuthGatewayModule {} @Injectable() export class JwtAuthGuard { constructor( private readonly loginCoreService: LoginCoreService, // 注入失败! ) {} } // ✅ 正确方案1:直接导入需要的Core模块 @Module({ imports: [ AuthModule, LoginCoreModule, // 直接导入,使LoginCoreService可用 ], providers: [ JwtAuthGuard, // 现在可以成功注入LoginCoreService ], }) export class AuthGatewayModule {} // ✅ 正确方案2:在中间模块重新导出 @Module({ imports: [LoginCoreModule], exports: [LoginCoreModule], // 重新导出,让导入AuthModule的模块也能访问 }) export class AuthModule {} ``` ### 依赖注入检查规则 #### 1. 检查Provider的构造函数依赖 ```typescript // 对于每个Provider(Service、Guard、Interceptor等) @Injectable() export class SomeGuard { constructor( private readonly serviceA: ServiceA, // 依赖1 private readonly serviceB: ServiceB, // 依赖2 ) {} } // 检查清单: // ✓ ServiceA是否在当前模块的imports中? // ✓ ServiceB是否在当前模块的imports中? // ✓ 如果不在,是否需要添加对应的Module到imports? ``` #### 2. 检查Module的导出完整性 ```typescript // ❌ 错误:导入了模块但没有导出,导致上层模块无法访问 @Module({ imports: [LoginCoreModule], providers: [LoginService], exports: [LoginService], // 只导出了LoginService,没有导出LoginCoreModule }) export class AuthModule {} // 如果上层模块需要直接使用LoginCoreService: @Module({ imports: [AuthModule], // 无法访问LoginCoreService providers: [JwtAuthGuard], // JwtAuthGuard需要LoginCoreService,会失败 }) export class AuthGatewayModule {} // ✅ 正确:根据需要导出Module @Module({ imports: [LoginCoreModule], providers: [LoginService], exports: [ LoginService, LoginCoreModule, // 导出Module,让上层也能访问 ], }) export class AuthModule {} ``` #### 3. 检查跨层依赖的模块导入 ```typescript // Gateway层的Guard直接依赖Core层Service的情况 @Injectable() export class JwtAuthGuard { constructor( private readonly loginCoreService: LoginCoreService, // 直接依赖Core层 ) {} } // 检查清单: // ✓ AuthGatewayModule是否导入了LoginCoreModule? // ✓ 如果通过AuthModule间接导入,AuthModule是否导出了LoginCoreModule? // ✓ 是否符合架构分层原则(Gateway可以直接依赖Core用于技术实现)? ``` ### 依赖注入检查步骤 1. **扫描所有Injectable类** - 找出所有使用@Injectable()装饰器的类 - 包括Service、Guard、Interceptor、Pipe等 2. **分析构造函数依赖** - 检查每个类的constructor参数 - 列出所有需要注入的服务 3. **检查Module的imports** - 确认每个依赖的服务是否在Module的imports中 - 检查imports的Module是否导出了需要的服务 4. **验证依赖链完整性** - 如果A模块导入B模块,B模块导入C模块 - 确认A模块是否能访问C模块的服务(取决于B是否导出C) 5. **检查常见错误模式** - Guard/Interceptor依赖Service但模块未导入 - 中间模块导入但未导出,导致上层无法访问 - 循环依赖问题 ### 依赖注入错误识别 #### 典型错误信息 ``` Nest can't resolve dependencies of the JwtAuthGuard (?). Please make sure that the argument LoginCoreService at index [0] is available in the AuthGatewayModule context. ``` #### 错误分析流程 ``` 1. 识别问题类:JwtAuthGuard 2. 识别缺失依赖:LoginCoreService(索引0) 3. 识别所在模块:AuthGatewayModule 4. 检查解决方案: ├─ LoginCoreService在哪个Module中提供? │ └─ 答:LoginCoreModule ├─ AuthGatewayModule是否导入了LoginCoreModule? │ └─ 否 → 需要添加到imports └─ 如果通过其他Module间接导入,该Module是否导出了LoginCoreModule? └─ 否 → 需要在中间Module的exports中添加 ``` ### 依赖注入最佳实践 ```typescript // ✅ 推荐:明确的依赖关系 @Module({ imports: [ // 业务层模块 AuthModule, // 直接需要的核心层模块(用于Guard等技术组件) LoginCoreModule, ], controllers: [LoginController], providers: [JwtAuthGuard], exports: [JwtAuthGuard], }) export class AuthGatewayModule {} // ✅ 推荐:完整的导出链 @Module({ imports: [LoginCoreModule, UsersModule], providers: [LoginService], exports: [ LoginService, // 导出自己的服务 LoginCoreModule, // 导出依赖的模块(如果上层需要) ], }) export class AuthModule {} ``` ## 🔍 检查执行步骤 1. **识别当前模块的层级** - 确定是Gateway层、Business层还是Core层 - 检查文件夹路径和命名 - 根据层级应用对应的检查规则 2. **Gateway层检查(如果是Gateway层)** - 检查是否只包含协议处理代码 - 检查是否使用DTO进行数据验证 - 检查是否只调用Business层服务 - 检查是否有统一的错误处理 - 检查文件类型是否符合Gateway层规范 3. **Business层检查(如果是Business层)** - 检查是否只包含业务逻辑 - 检查是否协调多个Core层服务 - 检查是否返回统一的业务响应 - 检查是否不包含HTTP协议处理 4. **Core层检查(如果是Core层)** - 检查Core层命名规范 - 业务支撑模块是否使用_core后缀 - 通用工具模块是否不使用后缀 - 根据模块职责判断命名正确性 - 检查是否只包含技术实现 5. **检查职责分离** - Gateway层是否只做协议转换 - Business层是否只包含业务逻辑 - Core层是否只包含技术实现 - 是否有跨层职责混乱 6. **🔥 检查依赖注入完整性(关键步骤)** - 扫描所有Injectable类的构造函数依赖 - 检查Module的imports是否包含所有依赖的Module - 验证中间Module是否正确导出了需要的服务 - 确认依赖链的完整性和可访问性 - 识别并修复常见的依赖注入错误 7. **检查依赖关系** - Gateway层是否只依赖Business层 - Business层是否只依赖Core层 - Core层是否不依赖业务层 - 依赖注入是否正确使用 7. **检查架构违规** - 识别常见的分层违规模式 - 检查技术实现和业务逻辑的边界 - 检查协议处理和业务逻辑的边界 - 确保架构清晰度 8. **游戏服务器特殊检查** - WebSocket Gateway的分层正确性 - 双模式服务的架构设计 - 实时通信组件的职责分离 ## 🔥 重要提醒 **如果在本步骤中执行了任何修改操作(调整分层结构、修正依赖关系、重构代码等),必须立即重新执行步骤4的完整检查!** - ✅ 执行修改 → 🔥 立即重新执行步骤4 → 提供验证报告 → 等待用户确认 - ❌ 执行修改 → 直接进入步骤5(错误做法) **🚨 重要强调:纯检查步骤不更新修改记录** **如果检查发现架构分层已经符合规范,无需任何修改,则:** - ❌ **禁止添加检查记录**:不要添加"AI代码检查步骤4:架构分层检查和优化" - ❌ **禁止更新时间戳**:不要修改@lastModified字段 - ❌ **禁止递增版本号**:不要修改@version字段 - ✅ **仅提供检查报告**:说明检查结果,确认符合规范 **不能跳过重新检查环节!**