bookworm-smart-assistant/skills/project-audit-expert/references/code-review-patterns.md
Bookworm Admin b7a8e29d21 release: v6.7.0 - OTA E2E test release
- VERSION file as authoritative version source
- export.mjs reads VERSION with package.json fallback
- bw-ota.ps1 DryRun mode for safe testing
- auto-setup.ps1 bumped to v3.2.0 (Phase 8 OTA)
2026-04-27 17:59:44 +08:00

185 lines
5.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 深度代码审查模式库
基于多个生产项目Next.js/FastAPI/Go 全栈)实战总结的常见问题与修复方案。
## TypeScript/JavaScript 专项
### 类型安全 (来自实际项目教训)
```typescript
// ============================================
// 问题 1: useState<any> 泛滥
// 来源: ai-stats/page.tsx 中发现 6 处 useState<any>
// ============================================
// ❌ 实际项目中的坏代码
const [data, setData] = useState<any>(null);
const [report, setReport] = useState<any>({});
// eslint-disable @typescript-eslint/no-explicit-any // 更糟: 直接禁用规则
// ✅ 修复: 定义完整接口类型
interface AiStatsData {
totalReplies: number;
avgQualityScore: number;
channels: ChannelStatusData[];
}
const [data, setData] = useState<AiStatsData | null>(null);
// ============================================
// 问题 2: JSON.parse 无类型验证
// 来源: auth-store.ts 中 atob(token) 后直接 parse
// ============================================
// ❌ 危险: 解析后未验证结构
const payload = JSON.parse(atob(parts[1]));
return payload.role; // 可能 undefined
// ✅ 使用 Zod 进行运行时验证
import { z } from 'zod';
const TokenPayload = z.object({
sub: z.string(),
role: z.enum(['admin', 'user']),
exp: z.number(),
});
const result = TokenPayload.safeParse(JSON.parse(atob(parts[1])));
if (!result.success) throw new Error('Invalid token payload');
```
### 重复代码消除 (DRY)
```typescript
// ============================================
// 问题 3: 工具函数在多处重复定义
// 来源: golden/page.tsx 和 customer/[id]/page.tsx 各自定义 formatRelativeTime
// ============================================
// ❌ 多个文件各自实现相同逻辑
// golden/page.tsx: function formatRelativeTime(date) { ... }
// customer/page.tsx: function formatRelativeTime(date) { ... }
// ✅ 提取到共享模块
// lib/format.ts
export function formatRelativeTime(date: string | Date | null): string {
if (!date) return '-';
const d = new Date(date);
if (isNaN(d.getTime())) return '-';
// ... 统一实现
}
```
### 错误处理
```typescript
// ============================================
// 问题 4: fetch 后未检查 response.ok
// 来源: mybioweb 项目 lib/api.ts
// ============================================
// ❌ 缺少响应状态检查
const data = await fetch(url);
// ✅ 完整错误处理链
async function request<T>(url: string, options?: RequestInit): Promise<T> {
try {
const response = await fetch(url, options);
if (!response.ok) {
const error = await response.json().catch(() => ({}));
throw new ApiError(response.status, error.code, error.message);
}
return response.json();
} catch (error) {
if (error instanceof ApiError) throw error;
throw new ApiError(0, 'NETWORK_ERROR', '网络错误');
}
}
```
## Python/FastAPI 专项
### 异常处理收窄
```python
# ============================================
# 问题 5: except Exception 吞掉所有错误
# 来源: auto_delivery_service.py:184
# ============================================
# ❌ 过宽的异常捕获
try:
result = process_delivery(data)
except Exception:
return None # 数据库错误也被静默吞掉
# ✅ 分类处理异常
from sqlalchemy.exc import SQLAlchemyError
try:
result = process_delivery(data)
except (ValueError, KeyError) as e:
logger.warning(f"数据格式异常: {e}")
return None
except SQLAlchemyError as e:
logger.error(f"数据库错误: {e}", exc_info=True)
raise # DB 错误必须向上传播
```
### 数据库字段持久化
```python
# ============================================
# 问题 6: 内存中修改字段但从未持久化到 DB
# 来源: example_selector.py:337 设置 last_used_at 但 batch update 只更新 times_used
# ============================================
# ❌ 字段赋值但未包含在 batch update 中
golden.last_used_at = now_cst() # 内存中修改
# batch update 只更新 times_used, last_used_at 被遗漏
# ✅ batch update 必须包含所有修改字段
stmt = (
sa_update(GoldenExample)
.where(GoldenExample.id == golden.id)
.values(
times_used=golden.times_used + 1,
last_used_at=now_cst(), # 同步持久化
)
)
await session.execute(stmt)
```
### 数据库约束完整性
```python
# ============================================
# 问题 7: 缺少唯一约束,依赖应用层去重
# 来源: models/example_usage.py
# ============================================
# ❌ 无数据库层面约束
class ExampleUsage(Base):
conversation_id = Column(Integer)
golden_example_id = Column(Integer)
# ✅ 添加唯一约束 + 复合索引
class ExampleUsage(Base):
conversation_id = Column(Integer, nullable=False)
golden_example_id = Column(Integer, nullable=False)
__table_args__ = (
UniqueConstraint('conversation_id', 'golden_example_id',
name='uq_conv_golden'),
Index('ix_conv_golden', 'conversation_id', 'golden_example_id'),
)
```
## Go/Gin 专项
```go
// 检查清单:
// - [ ] error 是否全部处理(不允许 _ 忽略 error
// - [ ] goroutine 是否有 recover 保护
// - [ ] 数据库连接是否使用连接池
// - [ ] GORM 查询是否避免了 N+1
// - [ ] context 是否正确传递和取消
```