# 架构重构文档 ## 重构目标 将现有的混合架构重构为清晰的4层架构,实现更好的关注点分离和代码组织。 ## 架构对比 ### 重构前 ``` src/ ├── business/auth/ # 混合了Gateway和Business职责 │ ├── login.controller.ts # HTTP协议处理 │ ├── login.service.ts # 业务逻辑 │ ├── jwt_auth.guard.ts # 认证守卫 │ └── dto/ # 数据传输对象 └── core/login_core/ # 核心层 └── login_core.service.ts # 数据访问和基础设施 ``` ### 重构后 ``` src/ ├── gateway/auth/ # 网关层(新增) │ ├── login.controller.ts # HTTP协议处理 │ ├── register.controller.ts # HTTP协议处理 │ ├── jwt_auth.guard.ts # 认证守卫 │ ├── dto/ # 数据传输对象 │ └── auth.gateway.module.ts # 网关模块 ├── business/auth/ # 业务层(精简) │ ├── login.service.ts # 登录业务逻辑 │ ├── register.service.ts # 注册业务逻辑 │ └── auth.module.ts # 业务模块 └── core/login_core/ # 核心层(不变) └── login_core.service.ts # 数据访问和基础设施 ``` ## 4层架构说明 ### 1. Transport Layer(传输层)- 可选 **位置**:`src/transport/` **职责**: - 底层网络通信和连接管理 - WebSocket服务器、TCP/UDP服务器 - 原生Socket连接池管理 **说明**:对于HTTP应用,NestJS已经提供了传输层,无需额外实现。对于WebSocket等特殊协议,可以在此层实现。 ### 2. Gateway Layer(网关层) **位置**:`src/gateway/` **职责**: - HTTP协议处理和请求响应 - 数据验证(DTO) - 路由管理 - 认证守卫 - 错误转换(业务错误 → HTTP状态码) - API文档 **原则**: - ✅ 只做协议转换,不做业务逻辑 - ✅ 使用DTO进行数据验证 - ✅ 统一的错误处理 - ❌ 不直接访问数据库 - ❌ 不包含业务规则 **示例**: ```typescript @Controller('auth') export class LoginController { constructor(private readonly loginService: LoginService) {} @Post('login') async login(@Body() loginDto: LoginDto, @Res() res: Response): Promise { // 只做协议转换 const result = await this.loginService.login({ identifier: loginDto.identifier, password: loginDto.password }); // 转换为HTTP响应 this.handleResponse(result, res); } } ``` ### 3. Business Layer(业务层) **位置**:`src/business/` **职责**: - 业务逻辑实现 - 业务流程控制 - 服务协调 - 业务规则验证 - 事务管理 **原则**: - ✅ 实现所有业务逻辑 - ✅ 协调多个Core层服务 - ✅ 返回统一的业务响应 - ❌ 不处理HTTP协议 - ❌ 不直接访问数据库 **示例**: ```typescript @Injectable() export class LoginService { async login(loginRequest: LoginRequest): Promise> { try { // 1. 调用核心服务进行认证 const authResult = await this.loginCoreService.login(loginRequest); // 2. 业务逻辑:验证Zulip账号 await this.validateAndUpdateZulipApiKey(authResult.user); // 3. 生成JWT令牌 const tokenPair = await this.loginCoreService.generateTokenPair(authResult.user); // 4. 返回业务响应 return { success: true, data: { user: this.formatUserInfo(authResult.user), ...tokenPair }, message: '登录成功' }; } catch (error) { return { success: false, message: error.message, error_code: 'LOGIN_FAILED' }; } } } ``` ### 4. Core Layer(核心层) **位置**:`src/core/` **职责**: - 数据访问(数据库、缓存) - 基础设施(Redis、消息队列) - 外部系统集成 - 技术实现细节 **原则**: - ✅ 提供技术基础设施 - ✅ 数据持久化和缓存 - ✅ 外部API集成 - ❌ 不包含业务逻辑 - ❌ 不处理HTTP协议 ## 数据流向 ``` 客户端请求 ↓ Gateway Layer (Controller) ↓ 调用 Business Layer (Service) ↓ 调用 Core Layer (Data Access) ↓ 数据库/缓存/外部API ``` ## 依赖关系 ``` Gateway → Business → Core ``` - Gateway层依赖Business层 - Business层依赖Core层 - Core层不依赖任何业务层 - 依赖方向单向,不允许反向依赖 ## 重构步骤 ### 第一阶段:登录注册模块(已完成) 1. ✅ 创建`src/gateway/auth/`目录 2. ✅ 移动Controller到Gateway层 3. ✅ 移动DTO到Gateway层 4. ✅ 移动Guard到Gateway层 5. ✅ 创建`AuthGatewayModule` 6. ✅ 更新Business层模块,移除Controller 7. ✅ 更新`app.module.ts`使用新的Gateway模块 8. ✅ 创建架构文档 ### 第二阶段:其他业务模块(待进行) - [ ] 重构`location_broadcast`模块 - [ ] 重构`user_mgmt`模块 - [ ] 重构`admin`模块 - [ ] 重构`zulip`模块 - [ ] 重构`notice`模块 ### 第三阶段:WebSocket模块(待进行) - [ ] 创建`src/transport/websocket/` - [ ] 实现原生WebSocket服务器 - [ ] 创建`src/gateway/location-broadcast/` - [ ] 移动WebSocket Gateway到Gateway层 ## 迁移指南 ### 如何判断代码应该放在哪一层? **Gateway层**: - 包含`@Controller()`装饰器 - 包含`@Get()`, `@Post()`等HTTP方法装饰器 - 包含`@Body()`, `@Param()`, `@Query()`等参数装饰器 - 包含DTO类(`class LoginDto`) - 包含Guard类(`class JwtAuthGuard`) **Business层**: - 包含`@Injectable()`装饰器 - 包含业务逻辑方法 - 协调多个服务 - 返回`ApiResponse`格式的响应 **Core层**: - 包含数据库访问代码 - 包含Redis操作代码 - 包含外部API调用 - 包含技术实现细节 ### 重构Checklist 对于每个模块: 1. [ ] 识别Controller文件 2. [ ] 创建对应的Gateway目录 3. [ ] 移动Controller到Gateway层 4. [ ] 移动DTO到Gateway层的`dto/`目录 5. [ ] 移动Guard到Gateway层 6. [ ] 创建Gateway Module 7. [ ] 更新Business Module,移除Controller 8. [ ] 更新imports,修正路径 9. [ ] 更新app.module.ts 10. [ ] 运行测试确保功能正常 ## 最佳实践 ### 1. 保持层级职责清晰 每一层只做自己职责范围内的事情,不要越界。 ### 2. 使用统一的响应格式 Business层返回统一的`ApiResponse`格式: ```typescript interface ApiResponse { success: boolean; data?: T; message: string; error_code?: string; } ``` ### 3. 错误处理分层 - Gateway层:将业务错误转换为HTTP状态码 - Business层:捕获异常并转换为业务错误 - Core层:抛出技术异常 ### 4. 依赖注入 使用NestJS的依赖注入系统,通过Module配置依赖关系。 ### 5. 文档完善 每个层级都应该有README文档说明职责和使用方法。 ## 注意事项 1. **渐进式重构**:不要一次性重构所有模块,逐个模块进行 2. **保持测试**:重构后运行测试确保功能正常 3. **向后兼容**:重构过程中保持API接口不变 4. **代码审查**:重构代码需要经过代码审查 5. **文档更新**:及时更新相关文档 ## 参考资料 - [NestJS官方文档](https://docs.nestjs.com/) - [Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) - [Hexagonal Architecture](https://alistair.cockburn.us/hexagonal-architecture/)