docs: 重构文档结构和组织
- 重新组织docs目录结构,按功能模块分类 - 新增deployment和development目录 - 更新API文档结构 - 添加客户端README文档 - 移除过时的文档文件
This commit is contained in:
527
docs/development/naming_convention.md
Normal file
527
docs/development/naming_convention.md
Normal file
@@ -0,0 +1,527 @@
|
||||
# 命名规范
|
||||
|
||||
本文档定义了项目中所有代码的命名规范,确保代码风格统一,提高可读性和可维护性。
|
||||
|
||||
## 目录
|
||||
|
||||
- [文件和文件夹命名](#文件和文件夹命名)
|
||||
- [变量和函数命名](#变量和函数命名)
|
||||
- [类和构造函数命名](#类和构造函数命名)
|
||||
- [常量命名](#常量命名)
|
||||
- [接口路由命名](#接口路由命名)
|
||||
- [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<T>(id: string): T { }
|
||||
class Repository<T, K> { }
|
||||
interface Response<T> { }
|
||||
|
||||
// 使用有意义的名称
|
||||
function mapArray<TInput, TOutput>(arr: TInput[]): TOutput[] { }
|
||||
|
||||
❌ 错误示例:
|
||||
function findById<t>(id: string): t { }
|
||||
class Repository<type, key> { }
|
||||
```
|
||||
|
||||
### 装饰器参数
|
||||
|
||||
```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<string, Player> = 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"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 总结
|
||||
|
||||
遵循统一的命名规范能够:
|
||||
|
||||
- 提高代码可读性
|
||||
- 减少团队沟通成本
|
||||
- 降低代码维护难度
|
||||
- 避免命名冲突
|
||||
- 提升项目专业度
|
||||
|
||||
记住:**好的命名是自解释的,不需要额外的注释。**
|
||||
Reference in New Issue
Block a user