feat: 初始化考培练系统项目
- 从服务器拉取完整代码 - 按框架规范整理项目结构 - 配置 Drone CI 测试环境部署 - 包含后端(FastAPI)、前端(Vue3)、管理端 技术栈: Vue3 + TypeScript + FastAPI + MySQL
This commit is contained in:
380
docs/规划/后端开发拆分策略/开发规范文档.md
Normal file
380
docs/规划/后端开发拆分策略/开发规范文档.md
Normal file
@@ -0,0 +1,380 @@
|
||||
# 考培练系统后端开发规范
|
||||
|
||||
## 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查询问题
|
||||
- [ ] 大量数据处理使用了分页或流式处理
|
||||
|
||||
### 日志检查
|
||||
- [ ] 关键操作有日志记录
|
||||
- [ ] 错误信息包含完整的上下文
|
||||
- [ ] 日志级别使用恰当
|
||||
|
||||
Reference in New Issue
Block a user