- 统一文件命名为snake_case格式(kebab-case snake_case) - 重构zulip模块为zulip_core,明确Core层职责 - 重构user-mgmt模块为user_mgmt,统一命名规范 - 调整模块依赖关系,优化架构分层 - 删除过时的文件和目录结构 - 更新相关文档和配置文件 本次重构涉及大量文件重命名和模块重组, 旨在建立更清晰的项目架构和统一的命名规范。
639 lines
14 KiB
Markdown
639 lines
14 KiB
Markdown
# 命名规范
|
||
|
||
本文档定义了项目中所有代码的命名规范,确保代码风格统一,提高可读性和可维护性。
|
||
|
||
## 目录
|
||
|
||
- [文件和文件夹命名](#文件和文件夹命名)
|
||
- [变量和函数命名](#变量和函数命名)
|
||
- [类和构造函数命名](#类和构造函数命名)
|
||
- [常量命名](#常量命名)
|
||
- [接口路由命名](#接口路由命名)
|
||
- [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' })
|
||
```
|
||
|
||
## 注释命名规范
|
||
|
||
### 注释标签命名
|
||
|
||
**规则:使用标准JSDoc标签**
|
||
|
||
```typescript
|
||
✅ 正确示例:
|
||
@param userId 用户ID
|
||
@returns 用户信息
|
||
@throws NotFoundException 用户不存在时
|
||
@author moyin
|
||
@version 1.0.0
|
||
@since 2025-01-07
|
||
@lastModified 2025-01-07
|
||
|
||
❌ 错误示例:
|
||
@参数 userId 用户ID
|
||
@返回 用户信息
|
||
@异常 NotFoundException 用户不存在时
|
||
@作者 moyin
|
||
```
|
||
|
||
### 修改记录命名
|
||
|
||
**规则:使用标准化的修改类型**
|
||
|
||
```typescript
|
||
✅ 正确示例:
|
||
- 2025-01-07: 代码规范优化 - 清理未使用的导入
|
||
- 2025-01-07: 功能新增 - 添加用户验证功能
|
||
- 2025-01-07: Bug修复 - 修复登录验证逻辑
|
||
- 2025-01-07: 性能优化 - 优化数据库查询
|
||
- 2025-01-07: 重构 - 重构用户服务架构
|
||
|
||
❌ 错误示例:
|
||
- 2025-01-07: 修改 - 改了一些代码
|
||
- 2025-01-07: 更新 - 更新了功能
|
||
- 2025-01-07: 优化 - 优化了性能
|
||
- 2025-01-07: 调整 - 调整了结构
|
||
```
|
||
|
||
**📏 长度限制:修改记录只保留最近5次修改,保持文件头注释简洁。**
|
||
|
||
### 注释内容命名
|
||
|
||
**规则:使用清晰描述性的中文**
|
||
|
||
```typescript
|
||
✅ 正确示例:
|
||
/** 用户唯一标识符 */
|
||
userId: string;
|
||
|
||
/** 用户邮箱地址,用于登录和通知 */
|
||
email: string;
|
||
|
||
/** 用户状态:active-激活, inactive-未激活, banned-已封禁 */
|
||
status: UserStatus;
|
||
|
||
/**
|
||
* 验证用户登录凭据
|
||
*
|
||
* 业务逻辑:
|
||
* 1. 验证用户名或邮箱格式
|
||
* 2. 查找用户记录
|
||
* 3. 验证密码哈希值
|
||
* 4. 检查用户状态
|
||
*/
|
||
|
||
❌ 错误示例:
|
||
/** id */
|
||
userId: string;
|
||
|
||
/** 邮箱 */
|
||
email: string;
|
||
|
||
/** 状态 */
|
||
status: UserStatus;
|
||
|
||
/**
|
||
* 登录
|
||
*/
|
||
```
|
||
|
||
### 版本号命名规范
|
||
|
||
**规则:使用语义化版本号**
|
||
|
||
```typescript
|
||
✅ 正确示例:
|
||
@version 1.0.0 // 主版本.次版本.修订版本
|
||
@version 1.2.3 // 功能更新
|
||
@version 2.0.0 // 重大更新
|
||
|
||
修改时版本递增规则:
|
||
- 代码规范优化、Bug修复 → 修订版本 +1 (1.0.0 → 1.0.1)
|
||
- 功能新增、功能修改 → 次版本 +1 (1.0.1 → 1.1.0)
|
||
- 重构、架构变更 → 主版本 +1 (1.1.0 → 2.0.0)
|
||
|
||
❌ 错误示例:
|
||
@version v1 // 缺少详细版本号
|
||
@version 1 // 格式不规范
|
||
@version latest // 不明确的版本标识
|
||
```
|
||
|
||
## 命名示例
|
||
|
||
### 完整的模块示例
|
||
|
||
```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 前缀
|
||
- [ ] 避免使用无意义的缩写
|
||
- [ ] 注释使用标准JSDoc标签
|
||
- [ ] 修改记录使用标准化修改类型
|
||
- [ ] 版本号遵循语义化版本规范
|
||
- [ ] 修改现有文件时添加了修改记录和更新版本号
|
||
- [ ] 修改记录只保留最近5次,保持注释简洁
|
||
|
||
## 工具配置
|
||
|
||
### 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"]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
## 总结
|
||
|
||
遵循统一的命名规范能够:
|
||
|
||
- 提高代码可读性
|
||
- 减少团队沟通成本
|
||
- 降低代码维护难度
|
||
- 避免命名冲突
|
||
- 提升项目专业度
|
||
|
||
记住:**好的命名是自解释的,不需要额外的注释。**
|