# 命名规范 本文档定义了项目中所有代码的命名规范,确保代码风格统一,提高可读性和可维护性。 ## 目录 - [文件和文件夹命名](#文件和文件夹命名) - [变量和函数命名](#变量和函数命名) - [类和构造函数命名](#类和构造函数命名) - [常量命名](#常量命名) - [接口路由命名](#接口路由命名) - [TypeScript 特定规范](#typescript-特定规范) - [命名示例](#命名示例) ## 文件和文件夹命名 **规则:使用下划线分隔(snake_case)** ### 文件命名 ``` ✅ 正确示例: - order_controller.ts - user_service.ts - game_gateway.ts - player_entity.ts - create_room_dto.ts - database_config.ts ❌ 错误示例: - OrderController.ts - userService.ts - game-gateway.ts - playerEntity.ts ``` ### 文件夹命名 ``` ✅ 正确示例: - src/api/ - src/service/ - src/model/dto/ - src/utils/ - src/config/ - test/unit_test/ - test/integration_test/ ❌ 错误示例: - src/API/ - src/Service/ - src/model-dto/ - src/Utils/ ``` ### 特殊说明 - 所有文件和文件夹名使用小写字母 - 多个单词之间使用下划线 `_` 连接 - 避免使用缩写,除非是广泛认可的缩写(如 dto、api) ## 变量和函数命名 **规则:使用小驼峰命名(camelCase)** ### 变量命名 ```typescript ✅ 正确示例: const userName = 'Alice'; let playerScore = 100; const roomId = '12345'; const isGameStarted = false; const maxPlayerCount = 4; ❌ 错误示例: const UserName = 'Alice'; const player_score = 100; const RoomId = '12345'; const is_game_started = false; ``` ### 函数命名 ```typescript ✅ 正确示例: function getUserInfo() { } async function queryUserInfo() { } function calculateDamage() { } function isPlayerAlive() { } function handlePlayerMove() { } ❌ 错误示例: function GetUserInfo() { } function query_user_info() { } function CalculateDamage() { } function IsPlayerAlive() { } ``` ### 命名建议 - 使用动词开头描述函数功能: - `get` - 获取数据(如 `getUserById`) - `set` - 设置数据(如 `setPlayerPosition`) - `create` - 创建实体(如 `createRoom`) - `update` - 更新数据(如 `updatePlayerScore`) - `delete` - 删除数据(如 `deleteRoom`) - `is/has` - 布尔判断(如 `isGameOver`、`hasPermission`) - `handle` - 事件处理(如 `handlePlayerAttack`) - `calculate` - 计算逻辑(如 `calculateDamage`) - `validate` - 验证逻辑(如 `validateInput`) - 布尔变量使用 `is`、`has`、`can` 等前缀: ```typescript const isActive = true; const hasPermission = false; const canMove = true; ``` ## 类和构造函数命名 **规则:使用大驼峰命名(PascalCase)** ### 类命名 ```typescript ✅ 正确示例: class UserModel { } class OrderService { } class GameController { } class PlayerEntity { } class RoomGateway { } class DatabaseConnection { } ❌ 错误示例: class userModel { } class order_service { } class gameController { } class player_entity { } ``` ### 接口命名 ```typescript ✅ 正确示例: interface User { } interface GameConfig { } interface PlayerData { } interface RoomOptions { } // 或使用 I 前缀(可选) interface IUser { } interface IGameConfig { } ❌ 错误示例: interface user { } interface game_config { } interface playerData { } ``` ### DTO 命名 ```typescript ✅ 正确示例: class CreateUserDto { } class UpdatePlayerDto { } class JoinRoomDto { } class GameStateDto { } ❌ 错误示例: class createUserDto { } class update_player_dto { } class joinRoomDTO { } ``` ### 装饰器命名 ```typescript ✅ 正确示例: @Controller('users') @Injectable() @Module() @Get() // 自定义装饰器 function CustomDecorator() { } ``` ## 常量命名 **规则:全大写 + 下划线分隔(SCREAMING_SNAKE_CASE)** ```typescript ✅ 正确示例: const PORT = 3000; const DB_HOST = 'localhost'; const MAX_PLAYERS = 10; const API_VERSION = 'v1'; const DEFAULT_TIMEOUT = 5000; const GAME_STATUS_WAITING = 'waiting'; const GAME_STATUS_PLAYING = 'playing'; ❌ 错误示例: const port = 3000; const dbHost = 'localhost'; const maxPlayers = 10; const ApiVersion = 'v1'; const default_timeout = 5000; ``` ### 枚举命名 ```typescript ✅ 正确示例: enum GameStatus { WAITING = 'waiting', PLAYING = 'playing', FINISHED = 'finished', } enum PlayerRole { ADMIN = 'admin', PLAYER = 'player', SPECTATOR = 'spectator', } ❌ 错误示例: enum gameStatus { waiting = 'waiting', playing = 'playing', } enum PlayerRole { admin = 'admin', player = 'player', } ``` ## 接口路由命名 **规则:全小写 + 短横线分隔(kebab-case)** ```typescript ✅ 正确示例: @Get('user/get-info') @Post('order/create-order') @Put('player/update-position') @Delete('room/delete-room') @Get('game/get-state') @Post('room/join-room') ❌ 错误示例: @Get('user/getInfo') @Post('order/createOrder') @Put('player/update_position') @Delete('room/DeleteRoom') @Get('game/GetState') ``` ### 路由结构建议 ```typescript // 资源型路由 @Controller('api/players') export class PlayerController { @Get() // GET /api/players @Get(':id') // GET /api/players/:id @Post() // POST /api/players @Put(':id') // PUT /api/players/:id @Delete(':id') // DELETE /api/players/:id } // 动作型路由 @Controller('api/game') export class GameController { @Post('start-game') // POST /api/game/start-game @Post('end-game') // POST /api/game/end-game @Get('get-state') // GET /api/game/get-state } // 嵌套资源路由 @Controller('api/rooms') export class RoomController { @Post(':id/join') // POST /api/rooms/:id/join @Post(':id/leave') // POST /api/rooms/:id/leave @Get(':id/players') // GET /api/rooms/:id/players } ``` ## TypeScript 特定规范 ### 类型别名 ```typescript ✅ 正确示例: type UserId = string; type PlayerPosition = { x: number; y: number }; type GameCallback = (state: GameState) => void; ❌ 错误示例: type userId = string; type player_position = { x: number; y: number }; ``` ### 泛型参数 ```typescript ✅ 正确示例: function findById(id: string): T { } class Repository { } interface Response { } // 使用有意义的名称 function mapArray(arr: TInput[]): TOutput[] { } ❌ 错误示例: function findById(id: string): t { } class Repository { } ``` ### 装饰器参数 ```typescript ✅ 正确示例: @Column({ name: 'user_name' }) @IsString({ message: 'Name must be a string' }) @ApiProperty({ description: 'User ID' }) ❌ 错误示例: @Column({ name: 'UserName' }) @IsString({ message: 'name_must_be_string' }) ``` ## 命名示例 ### 完整的模块示例 ```typescript // 文件:src/api/player_controller.ts import { Controller, Get, Post, Body, Param } from '@nestjs/common'; import { PlayerService } from '../service/player_service'; import { CreatePlayerDto } from '../model/dto/create_player_dto'; const MAX_PLAYERS = 100; @Controller('api/players') export class PlayerController { constructor(private readonly playerService: PlayerService) {} @Get() async getAllPlayers() { return this.playerService.findAll(); } @Get(':id') async getPlayerById(@Param('id') playerId: string) { return this.playerService.findById(playerId); } @Post() async createPlayer(@Body() createPlayerDto: CreatePlayerDto) { return this.playerService.create(createPlayerDto); } @Post(':id/update-position') async updatePlayerPosition( @Param('id') playerId: string, @Body() body: { x: number; y: number } ) { const { x, y } = body; return this.playerService.updatePosition(playerId, x, y); } } ``` ```typescript // 文件:src/service/player_service.ts import { Injectable, NotFoundException } from '@nestjs/common'; import { Player } from '../model/player_entity'; import { CreatePlayerDto } from '../model/dto/create_player_dto'; const DEFAULT_HEALTH = 100; const DEFAULT_SPEED = 5; @Injectable() export class PlayerService { private players: Map = new Map(); findAll(): Player[] { return Array.from(this.players.values()); } findById(playerId: string): Player { const player = this.players.get(playerId); if (!player) { throw new NotFoundException(`Player with ID ${playerId} not found`); } return player; } create(createPlayerDto: CreatePlayerDto): Player { const newPlayer: Player = { id: this.generatePlayerId(), name: createPlayerDto.name, health: DEFAULT_HEALTH, speed: DEFAULT_SPEED, position: { x: 0, y: 0 }, isAlive: true, createdAt: new Date(), }; this.players.set(newPlayer.id, newPlayer); return newPlayer; } updatePosition(playerId: string, x: number, y: number): Player { const player = this.findById(playerId); player.position = { x, y }; return player; } private generatePlayerId(): string { return `player_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } private calculateDamage(attackPower: number, defense: number): number { return Math.max(0, attackPower - defense); } isPlayerAlive(playerId: string): boolean { const player = this.findById(playerId); return player.isAlive && player.health > 0; } } ``` ```typescript // 文件:src/model/player_entity.ts export interface Player { id: string; name: string; health: number; speed: number; position: Position; isAlive: boolean; createdAt: Date; } export interface Position { x: number; y: number; } export enum PlayerStatus { IDLE = 'idle', MOVING = 'moving', ATTACKING = 'attacking', DEAD = 'dead', } ``` ```typescript // 文件:src/model/dto/create_player_dto.ts import { IsString, IsNotEmpty, MinLength, MaxLength } from 'class-validator'; export class CreatePlayerDto { @IsString() @IsNotEmpty() @MinLength(3) @MaxLength(20) name: string; } ``` ## 检查清单 在提交代码前,请确保: - [ ] 所有文件和文件夹使用下划线分隔命名 - [ ] 所有变量和函数使用小驼峰命名 - [ ] 所有类、接口、DTO 使用大驼峰命名 - [ ] 所有常量和枚举值使用全大写 + 下划线命名 - [ ] 所有路由使用全小写 + 短横线命名 - [ ] 函数名清晰表达其功能 - [ ] 布尔变量使用 is/has/can 前缀 - [ ] 避免使用无意义的缩写 ## 工具配置 ### ESLint 配置建议 ```json { "rules": { "@typescript-eslint/naming-convention": [ "error", { "selector": "variable", "format": ["camelCase", "UPPER_CASE"] }, { "selector": "function", "format": ["camelCase"] }, { "selector": "class", "format": ["PascalCase"] }, { "selector": "interface", "format": ["PascalCase"] } ] } } ``` ## 总结 遵循统一的命名规范能够: - 提高代码可读性 - 减少团队沟通成本 - 降低代码维护难度 - 避免命名冲突 - 提升项目专业度 记住:**好的命名是自解释的,不需要额外的注释。**