# 考培练系统后端开发规范

## 1. 代码规范

### 1.1 Python代码规范
- **格式化工具**：使用 Black 进行代码格式化，配置行长度为 88
- **导入排序**：使用 isort 进行导入排序
- **类型检查**：使用 mypy 进行静态类型检查
- **代码检查**：使用 flake8 进行代码质量检查

### 1.2 命名规范
```python
# 文件名：使用小写字母和下划线
user_service.py

# 类名：使用大驼峰命名法
class UserService:
    pass

# 函数和变量：使用小写字母和下划线
def get_user_by_id(user_id: int) -> User:
    pass

# 常量：使用大写字母和下划线
MAX_RETRY_COUNT = 3

# 私有成员：使用单下划线前缀
def _validate_input(data: dict) -> bool:
    pass
```

### 1.3 文档字符串规范
```python
def create_user(
    username: str,
    email: str,
    password: str,
    role: UserRole = UserRole.TRAINEE
) -> User:
    """
    创建新用户
    
    Args:
        username: 用户名，长度3-20个字符
        email: 用户邮箱，必须是有效的邮箱格式
        password: 密码，最少8个字符
        role: 用户角色，默认为学员
    
    Returns:
        User: 创建成功的用户对象
    
    Raises:
        ValidationError: 输入参数验证失败
        DuplicateError: 用户名或邮箱已存在
    """
    pass
```

## 2. API开发规范

### 2.1 RESTful API设计原则
- 使用名词而非动词
- 使用复数形式
- 使用标准HTTP方法
- 合理使用HTTP状态码

```python
# 好的例子
GET    /api/v1/users          # 获取用户列表
GET    /api/v1/users/{id}     # 获取单个用户
POST   /api/v1/users          # 创建用户
PUT    /api/v1/users/{id}     # 更新用户
DELETE /api/v1/users/{id}     # 删除用户

# 错误的例子
GET    /api/v1/getUsers       # 不要使用动词
POST   /api/v1/user/create    # 不要在URL中包含动作
```

### 2.2 统一响应格式
```python
from typing import Optional, Any
from pydantic import BaseModel

class ResponseModel(BaseModel):
    """统一API响应模型"""
    code: int = 200
    message: str = "success"
    data: Optional[Any] = None
    
class ErrorResponse(BaseModel):
    """错误响应模型"""
    code: int
    message: str
    details: Optional[str] = None
    trace_id: Optional[str] = None

# 成功响应示例
{
    "code": 200,
    "message": "success",
    "data": {
        "id": 1,
        "username": "张三",
        "email": "zhangsan@example.com"
    }
}

# 错误响应示例
{
    "code": 400,
    "message": "参数验证失败",
    "details": "用户名长度必须在3-20个字符之间",
    "trace_id": "abc123def456"
}
```

### 2.3 API版本控制
- 使用URL路径进行版本控制：`/api/v1/`, `/api/v2/`
- 保持向后兼容，避免破坏性更改
- 废弃的API需要提前通知并设置过渡期

## 3. 数据库规范

### 3.1 表命名规范
- 使用复数形式：`users`, `courses`, `exams`
- 关联表使用下划线连接：`user_courses`, `exam_questions`
- 避免使用MySQL保留字

### 3.2 字段命名规范
- 使用蛇形命名法：`user_name`, `created_at`
- 主键统一使用 `id`
- 外键使用 `表名_id` 格式：`user_id`, `course_id`

### 3.3 必需字段
每个表必须包含以下字段：
```sql
id         BIGINT       PRIMARY KEY AUTO_INCREMENT  -- 主键
created_at TIMESTAMP    DEFAULT CURRENT_TIMESTAMP   -- 创建时间
updated_at TIMESTAMP    DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP  -- 更新时间
created_by BIGINT       -- 创建人ID（可选）
updated_by BIGINT       -- 更新人ID（可选）
is_deleted BOOLEAN      DEFAULT FALSE  -- 软删除标记（如需要）
```

### 3.4 索引规范
- 为外键字段创建索引
- 为经常查询的字段创建索引
- 避免创建过多索引影响写入性能
- 索引命名：`idx_表名_字段名`

## 4. 异常处理规范

### 4.1 自定义异常类
```python
# app/core/exceptions.py
class BaseAPIException(Exception):
    """API异常基类"""
    def __init__(
        self,
        code: int,
        message: str,
        details: str = None
    ):
        self.code = code
        self.message = message
        self.details = details
        super().__init__(message)

class ValidationError(BaseAPIException):
    """参数验证异常"""
    def __init__(self, message: str, details: str = None):
        super().__init__(400, message, details)

class NotFoundError(BaseAPIException):
    """资源不存在异常"""
    def __init__(self, resource: str):
        super().__init__(404, f"{resource}不存在")

class PermissionError(BaseAPIException):
    """权限不足异常"""
    def __init__(self, message: str = "权限不足"):
        super().__init__(403, message)
```

### 4.2 全局异常处理
```python
# app/core/middleware.py
from fastapi import Request
from fastapi.responses import JSONResponse

async def global_exception_handler(request: Request, exc: Exception):
    """全局异常处理器"""
    if isinstance(exc, BaseAPIException):
        return JSONResponse(
            status_code=exc.code,
            content={
                "code": exc.code,
                "message": exc.message,
                "details": exc.details,
                "trace_id": request.state.trace_id
            }
        )
    
    # 记录未预期的异常
    logger.error(f"未处理的异常: {exc}", exc_info=True)
    return JSONResponse(
        status_code=500,
        content={
            "code": 500,
            "message": "服务器内部错误",
            "trace_id": request.state.trace_id
        }
    )
```

## 5. 日志规范

### 5.1 日志级别使用
- **DEBUG**: 调试信息，仅在开发环境使用
- **INFO**: 一般信息，如API请求、重要业务操作
- **WARNING**: 警告信息，如已废弃的API调用
- **ERROR**: 错误信息，需要关注但不影响系统运行
- **CRITICAL**: 严重错误，可能导致系统无法正常运行

### 5.2 结构化日志
```python
import structlog

logger = structlog.get_logger()

# 使用结构化日志
logger.info(
    "用户登录成功",
    user_id=user.id,
    username=user.username,
    ip_address=request.client.host,
    user_agent=request.headers.get("user-agent")
)

# 记录错误信息
logger.error(
    "数据库连接失败",
    error=str(e),
    database_url=settings.DATABASE_URL,
    retry_count=retry_count,
    exc_info=True  # 包含完整堆栈信息
)
```

### 5.3 日志格式配置
```python
# app/core/logger.py
import structlog

def configure_logging():
    structlog.configure(
        processors=[
            structlog.stdlib.filter_by_level,
            structlog.stdlib.add_logger_name,
            structlog.stdlib.add_log_level,
            structlog.stdlib.PositionalArgumentsFormatter(),
            structlog.processors.TimeStamper(fmt="iso"),
            structlog.processors.StackInfoRenderer(),
            structlog.processors.format_exc_info,
            structlog.processors.UnicodeDecoder(),
            structlog.processors.JSONRenderer()
        ],
        context_class=dict,
        logger_factory=structlog.stdlib.LoggerFactory(),
        cache_logger_on_first_use=True,
    )
```

## 6. 测试规范

### 6.1 测试文件组织
```
tests/
├── unit/                  # 单元测试
│   ├── test_services/
│   └── test_utils/
├── integration/          # 集成测试
│   ├── test_api/
│   └── test_database/
└── e2e/                  # 端到端测试
    └── test_workflows/
```

### 6.2 测试命名规范
```python
# 测试文件名：test_模块名.py
test_user_service.py

# 测试类名：Test + 被测试类名
class TestUserService:
    pass

# 测试方法名：test_应该_做什么_当什么条件
def test_should_create_user_when_valid_data(self):
    pass

def test_should_raise_error_when_duplicate_username(self):
    pass
```

### 6.3 测试覆盖率要求
- 核心业务逻辑：≥ 90%
- API接口：≥ 80%
- 工具函数：≥ 70%
- 总体覆盖率：≥ 80%

## 7. Git提交规范

### 7.1 提交信息格式
```
<type>(<scope>): <subject>

<body>

<footer>
```

### 7.2 Type类型
- **feat**: 新功能
- **fix**: 修复bug
- **docs**: 文档更新
- **style**: 代码格式调整
- **refactor**: 代码重构
- **test**: 测试相关
- **chore**: 构建过程或辅助工具的变动

### 7.3 示例
```
feat(user): 添加用户批量导入功能

- 支持Excel文件导入
- 支持CSV文件导入  
- 添加导入进度显示
- 添加错误信息导出

Closes #123
```

## 8. 代码审查清单

提交代码前，请确保：

### 基础检查
- [ ] 代码通过 Black 格式化
- [ ] 代码通过 isort 导入排序
- [ ] 代码通过 mypy 类型检查
- [ ] 代码通过 flake8 质量检查

### 功能检查
- [ ] 所有函数都有完整的文档字符串
- [ ] 所有函数都有类型注解
- [ ] API响应格式符合统一标准
- [ ] 错误处理使用统一的异常类

### 测试检查
- [ ] 编写了相应的单元测试
- [ ] 测试覆盖率符合要求
- [ ] 所有测试通过

### 安全检查
- [ ] 没有硬编码的密钥或密码
- [ ] SQL查询使用参数化查询
- [ ] 敏感操作有权限检查

### 性能检查
- [ ] 数据库查询使用了适当的索引
- [ ] 避免了N+1查询问题
- [ ] 大量数据处理使用了分页或流式处理

### 日志检查
- [ ] 关键操作有日志记录
- [ ] 错误信息包含完整的上下文
- [ ] 日志级别使用恰当

