288 lines
9.5 KiB
Plaintext
288 lines
9.5 KiB
Plaintext
电商订单管理系统 — 工程规范文档
|
||
团队:订单研发团队(后端6人 + 前端3人 + QA2人 + DevOps1人)
|
||
最后更新:2026-07-15
|
||
仓库:[email protected]:order-team/oms.git
|
||
|
||
================================================================================
|
||
项目背景
|
||
================================================================================
|
||
|
||
本项目是一个面向 B 端商家的电商订单管理系统,日均订单量约 50 万单。
|
||
系统采用微服务架构,包含订单服务、支付服务、库存服务和物流服务四个核心模块。
|
||
|
||
技术栈:
|
||
- 后端:Java 17 + Spring Boot 3.2 + MyBatis-Plus
|
||
- 前端:React 18 + TypeScript 5.3 + Vite
|
||
- 数据库:MySQL 8.0 + Redis 7
|
||
- 消息队列:RocketMQ 5.x
|
||
|
||
================================================================================
|
||
团队介绍
|
||
================================================================================
|
||
|
||
订单研发团队目前有 12 人:
|
||
- 后端 6 人(含 1 名 Tech Lead:张三)
|
||
- 前端 3 人(负责人:李四)
|
||
- QA 2 人
|
||
- DevOps 1 人
|
||
|
||
团队代码仓库:[email protected]:order-team/oms.git
|
||
内部 Wiki:https://wiki.internal/order-team
|
||
|
||
================================================================================
|
||
一、安全相关规范
|
||
================================================================================
|
||
|
||
在 2026 Q2 的安全审计中,我们发现线上代码中存在硬编码的数据库密码,
|
||
导致一次严重的安全事件。因此制定以下规范:
|
||
|
||
---- 规则 ----
|
||
名称:禁止硬编码凭证
|
||
严重级别:error
|
||
适用语言:javascript, typescript, java
|
||
描述:禁止在源码中硬编码密码、令牌、API Key 等敏感凭证
|
||
提示:检测到疑似硬编码凭证,请使用环境变量或密钥管理服务注入
|
||
|
||
以下是反面示例(请勿模仿):
|
||
|
||
// Java: 硬编码密码
|
||
public class DatabaseConfig {
|
||
private String password = "Admin@123456";
|
||
private String apiKey = "sk-abc123xyz";
|
||
}
|
||
|
||
// JavaScript: 硬编码 Token
|
||
const API_TOKEN = "ghp_abc123def456";
|
||
|
||
正确做法:
|
||
|
||
@Value("${db.password}")
|
||
private String password;
|
||
|
||
const apiToken = process.env.API_TOKEN;
|
||
|
||
---- 规则 ----
|
||
名称:禁止使用 eval()
|
||
严重级别:error
|
||
适用语言:javascript, typescript
|
||
描述:禁止使用 eval() 函数,存在代码注入风险
|
||
提示:eval() 存在安全风险,请使用 JSON.parse() 或 Function 构造器替代
|
||
|
||
上周代码审查中发现前端模块有 eval() 调用:
|
||
|
||
// 错误:使用 eval 解析用户输入
|
||
const data = eval(request.body);
|
||
|
||
// 正确:使用 JSON.parse
|
||
const data = JSON.parse(request.body);
|
||
|
||
---- 规则 ----
|
||
名称:禁止直接赋值 innerHTML
|
||
严重级别:warning
|
||
适用语言:所有语言
|
||
描述:禁止直接赋值 innerHTML,可能导致 XSS
|
||
提示:避免直接操作 innerHTML,请使用 textContent 或 DOMPurify 清洗
|
||
|
||
相关讨论参见内部 Wiki: XSS 防护指南
|
||
|
||
================================================================================
|
||
二、命名规范
|
||
================================================================================
|
||
|
||
以下命名规范参考了 Google Java Style Guide 和 Airbnb JavaScript Style Guide,
|
||
根据团队实际情况做了调整。
|
||
|
||
---- 规则 ----
|
||
名称:常量使用全大写命名
|
||
严重级别:warning
|
||
适用语言:javascript, typescript, java
|
||
描述:常量命名必须使用全大写加下划线(SCREAMING_SNAKE_CASE)
|
||
提示:常量应使用全大写命名,如 MAX_RETRY_COUNT
|
||
|
||
反面示例:
|
||
|
||
static final int maxRetry = 3;
|
||
static final String DbHost = "localhost";
|
||
|
||
正确做法:
|
||
|
||
static final int MAX_RETRY = 3;
|
||
static final String DB_HOST = "localhost";
|
||
|
||
---- 规则 ----
|
||
名称:布尔变量添加前缀
|
||
严重级别:info
|
||
适用语言:javascript, typescript
|
||
描述:布尔变量和方法名应以 is/has/can/should 开头
|
||
提示:布尔变量建议添加 is/has/can/should 前缀以提升可读性
|
||
|
||
// 错误
|
||
let active = true;
|
||
let user = { verified: true };
|
||
function check(): boolean { ... }
|
||
|
||
// 正确
|
||
let isActive = true;
|
||
let user = { isVerified: true };
|
||
function canCheck(): boolean { ... }
|
||
|
||
================================================================================
|
||
三、性能规范
|
||
================================================================================
|
||
|
||
架构说明:订单服务采用 CQRS 模式,写操作走主库,读操作走从库。
|
||
在高并发场景下,以下性能规范尤为重要。
|
||
|
||
---- 规则 ----
|
||
名称:禁止三层以上嵌套循环
|
||
严重级别:warning
|
||
适用语言:javascript, typescript, java
|
||
描述:禁止三层及以上嵌套循环,时间复杂度过高
|
||
提示:检测到深层嵌套循环(≥3层),建议重构为扁平结构或使用查找表优化
|
||
|
||
// 错误:O(n³) 的订单匹配逻辑
|
||
for (const order of orders) {
|
||
for (const item of order.items) {
|
||
for (const warehouse of warehouses) {
|
||
// 匹配逻辑...
|
||
}
|
||
}
|
||
}
|
||
|
||
// 正确:使用 Map 优化为 O(n)
|
||
const warehouseMap = new Map(warehouses.map(w => [w.id, w]));
|
||
for (const order of orders) {
|
||
for (const item of order.items) {
|
||
const wh = warehouseMap.get(item.warehouseId);
|
||
}
|
||
}
|
||
|
||
---- 规则 ----
|
||
名称:异步函数内禁止同步 API
|
||
严重级别:warning
|
||
适用语言:javascript, typescript
|
||
描述:异步函数内禁止调用同步阻塞 API
|
||
提示:在 async 函数中调用同步 API 会阻塞事件循环,请改用异步版本
|
||
|
||
--- 2026-07-15 会议纪要 ---
|
||
|
||
- 讨论了 Node.js 事件循环阻塞问题
|
||
- 决定在 async 函数中全面禁用 fs.readFileSync 等同步 API
|
||
- 下个 Sprint 开始 Code Review 时执行
|
||
- 张三负责更新 ESLint 配置
|
||
- 李四负责前端代码排查
|
||
|
||
================================================================================
|
||
四、代码风格
|
||
================================================================================
|
||
|
||
---- 规则 ----
|
||
名称:函数显式类型注解
|
||
严重级别:info
|
||
适用语言:typescript
|
||
描述:函数参数和返回值应显式标注 TypeScript 类型
|
||
提示:建议为函数添加显式类型注解,提升类型安全性
|
||
|
||
// 错误
|
||
function createOrder(data) {
|
||
return api.post('/orders', data);
|
||
}
|
||
|
||
// 正确
|
||
function createOrder(data: CreateOrderDTO): Promise<OrderResponse> {
|
||
return api.post('/orders', data);
|
||
}
|
||
|
||
---- 规则 ----
|
||
名称:禁止魔法数字
|
||
严重级别:info
|
||
适用语言:javascript, typescript
|
||
描述:禁止在代码中直接使用魔法数字,应提取为命名常量
|
||
提示:检测到魔法数字,建议提取为具名常量以提升可维护性
|
||
|
||
// 错误
|
||
if (order.status === 3) { ... }
|
||
setTimeout(retry, 5000);
|
||
|
||
// 正确
|
||
const ORDER_STATUS_SHIPPED = 3;
|
||
const RETRY_DELAY_MS = 5000;
|
||
if (order.status === ORDER_STATUS_SHIPPED) { ... }
|
||
setTimeout(retry, RETRY_DELAY_MS);
|
||
|
||
================================================================================
|
||
五、团队约定
|
||
================================================================================
|
||
|
||
部署流程说明:
|
||
每周二、四发布,发布窗口 14:00-16:00。
|
||
CI/CD Pipeline 详见 Jenkins 配置。
|
||
|
||
---- 规则 ----
|
||
名称:throw 语句携带上下文
|
||
严重级别:warning
|
||
适用语言:javascript, typescript, java
|
||
描述:throw 语句必须携带错误上下文信息
|
||
提示:throw 时应提供足够的上下文信息,便于问题定位
|
||
|
||
// 错误
|
||
throw new RuntimeException("失败");
|
||
throw new Error("error");
|
||
|
||
// 正确
|
||
throw new OrderNotFoundException("订单不存在, orderId=" + orderId);
|
||
throw new PaymentFailedException("支付失败", cause);
|
||
|
||
---- 规则 ----
|
||
名称:禁止遗留 TODO 注释
|
||
严重级别:info
|
||
排除语言:sql
|
||
描述:生产代码中不应遗留 TODO/FIXME/HACK 注释
|
||
提示:代码中发现 TODO/FIXME/HACK 注释,请在发布前处理
|
||
|
||
注:SQL 脚本中允许临时性的 TODO 标记,因为数据库迁移脚本的生命周期与代码不同。
|
||
|
||
---- 规则 ----
|
||
名称:公共函数文档注释
|
||
严重级别:info
|
||
适用语言:javascript, typescript, java
|
||
描述:公共函数应添加文档注释(JSDoc / Javadoc)
|
||
提示:公共函数缺少文档注释,建议补充说明用途、参数和返回值
|
||
|
||
/**
|
||
* 创建订单
|
||
* @param request 订单创建请求
|
||
* @return 订单创建结果
|
||
* @throws InsufficientStockException 库存不足时抛出
|
||
*/
|
||
public OrderResult createOrder(CreateOrderRequest request) { ... }
|
||
|
||
/**
|
||
* 获取用户订单列表
|
||
* @param userId 用户ID
|
||
* @param page 分页参数
|
||
* @returns 订单列表
|
||
*/
|
||
function getUserOrders(userId: string, page: Pagination): Promise<Order[]> { ... }
|
||
|
||
================================================================================
|
||
附录
|
||
================================================================================
|
||
|
||
A. 代码审查 Checklist
|
||
[ ] 安全规范是否遵守
|
||
[ ] 命名规范是否一致
|
||
[ ] 性能是否有明显瓶颈
|
||
[ ] 代码风格是否统一
|
||
[ ] 团队约定是否遵循
|
||
|
||
B. 相关链接
|
||
- Google Java Style Guide: https://google.github.io/styleguide/javaguide.html
|
||
- Airbnb JavaScript Style Guide: https://github.com/airbnb/javascript
|
||
- TypeScript ESLint Rules: https://typescript-eslint.io/rules/
|
||
|
||
C. 版本历史
|
||
v1.0 2026-06-01 张三 初版
|
||
v1.1 2026-07-15 李四 新增性能规范
|
||
v1.2 2026-08-01 王五 补充代码示例
|