forked from Gitlink/gitlink-cli
389 lines
8.8 KiB
Markdown
389 lines
8.8 KiB
Markdown
# 代码质量检查
|
||
|
||
本文档详细说明如何使用 AI 分析代码质量问题。
|
||
|
||
## 📋 概述
|
||
|
||
代码质量检查是智能代码审查的核心维度之一,通过分析代码的复杂度、命名规范、注释完整性等指标,评估代码的可读性和可维护性。
|
||
|
||
## 🎯 检查维度
|
||
|
||
### 1. 代码复杂度
|
||
|
||
**检查项**:
|
||
- **圈复杂度(Cyclomatic Complexity)**: 衡量代码的独立路径数量
|
||
- **函数长度**: 单个函数的代码行数
|
||
- **嵌套层级**: 代码的嵌套深度
|
||
- **参数数量**: 函数的参数个数
|
||
|
||
**标准**:
|
||
- 圈复杂度 < 10: 优秀 ✅
|
||
- 圈复杂度 10-20: 良好 ⚠️
|
||
- 圈复杂度 > 20: 需要重构 🔴
|
||
|
||
- 函数长度 < 50 行: 优秀 ✅
|
||
- 函数长度 50-100 行: 良好 ⚠️
|
||
- 函数长度 > 100 行: 需要拆分 🔴
|
||
|
||
- 嵌套层级 < 3: 优秀 ✅
|
||
- 嵌套层级 3-4: 良好 ⚠️
|
||
- 嵌套层级 > 4: 需要简化 🔴
|
||
|
||
**示例代码**:
|
||
```go
|
||
// 🔴 高复杂度示例(需要重构)
|
||
func processData(input1, input2, input3, input4, input5 string) error {
|
||
if input1 != "" {
|
||
for i := 0; i < 100; i++ {
|
||
if input2 != "" {
|
||
switch input3 {
|
||
case "a":
|
||
if input4 != "" {
|
||
// 嵌套层级过深
|
||
}
|
||
case "b":
|
||
// ...
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// ✅ 低复杂度示例(优秀)
|
||
func processData(input string) error {
|
||
if err := validateInput(input); err != nil {
|
||
return err
|
||
}
|
||
|
||
data, err := parseInput(input)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
return saveData(data)
|
||
}
|
||
```
|
||
|
||
### 2. 命名规范
|
||
|
||
**检查项**:
|
||
- **变量命名**: 是否使用清晰、描述性的名称
|
||
- **函数命名**: 是否使用动词开头,描述函数功能
|
||
- **类命名**: 是否使用名词,首字母大写
|
||
- **常量命名**: 是否使用全大写+下划线
|
||
|
||
**规则**:
|
||
- ✅ 使用有意义的名称(`userAge` 而非 `x`)
|
||
- ✅ 遵循语言约定(Go: 驼峰命名,Python: 下划线命名)
|
||
- ❌ 避免单字母变量(除循环变量 `i`, `j`)
|
||
- ❌ 避免缩写(`usr` 而非 `user`)
|
||
|
||
**示例**:
|
||
```javascript
|
||
// ❌ 不好的命名
|
||
const x = 10;
|
||
function calc(a, b) {
|
||
return a + b;
|
||
}
|
||
|
||
// ✅ 好的命名
|
||
const maxRetryCount = 10;
|
||
function calculateTotal(price, quantity) {
|
||
return price * quantity;
|
||
}
|
||
```
|
||
|
||
### 3. 注释完整性
|
||
|
||
**检查项**:
|
||
- **函数注释**: 复杂函数是否有注释说明
|
||
- **代码逻辑**: 复杂逻辑是否有解释
|
||
- **TODO 标记**: 是否有未完成的 TODO
|
||
|
||
**规则**:
|
||
- ✅ 公共 API 必须有注释
|
||
- ✅ 复杂算法必须有注释
|
||
- ✅ 非显而易见的逻辑必须有注释
|
||
- ❌ 避免注释显而易见的代码
|
||
|
||
**示例**:
|
||
```go
|
||
// ❌ 不好的注释(显而易见)
|
||
// 设置用户名为 "admin"
|
||
username := "admin"
|
||
|
||
// ✅ 好的注释(解释复杂逻辑)
|
||
// 使用二次探测法解决哈希冲突
|
||
index := (hash + i * i) % tableSize
|
||
```
|
||
|
||
### 4. 代码格式
|
||
|
||
**检查项**:
|
||
- **缩进**: 是否使用一致的缩进(2/4 空格或 Tab)
|
||
- **空行**: 函数/类之间是否有适当的空行
|
||
- **行长度**: 单行代码是否过长(建议 < 120 字符)
|
||
- **代码组织**: 导入、常量、变量、函数的顺序
|
||
|
||
**标准**:
|
||
- 使用统一的代码格式化工具(gofmt、prettier)
|
||
- 函数之间空 1-2 行
|
||
- 逻辑块之间空 1 行
|
||
|
||
## 🔧 分析流程
|
||
|
||
```
|
||
开始分析代码质量
|
||
↓
|
||
1. 解析代码结构
|
||
├─ 识别函数、类、变量
|
||
└─ 提取代码块
|
||
↓
|
||
2. 计算复杂度指标
|
||
├─ 圈复杂度
|
||
├─ 函数长度
|
||
├─ 嵌套层级
|
||
└─ 参数数量
|
||
↓
|
||
3. 检查命名规范
|
||
├─ 变量命名
|
||
├─ 函数命名
|
||
└─ 类命名
|
||
↓
|
||
4. 评估注释完整性
|
||
├─ 函数注释
|
||
├─ 逻辑注释
|
||
└─ TODO 标记
|
||
↓
|
||
5. 生成质量报告
|
||
├─ 评分
|
||
├─ 问题列表
|
||
└─ 改进建议
|
||
↓
|
||
完成
|
||
```
|
||
|
||
## 📊 输出格式
|
||
|
||
### JSON 格式
|
||
|
||
```json
|
||
{
|
||
"quality_analysis": {
|
||
"overall_score": 85,
|
||
"complexity": {
|
||
"score": 90,
|
||
"metrics": {
|
||
"avg_cyclomatic_complexity": 3.5,
|
||
"max_cyclomatic_complexity": 8,
|
||
"avg_function_length": 25,
|
||
"max_function_length": 60,
|
||
"max_nesting_level": 3
|
||
},
|
||
"issues": [
|
||
{
|
||
"file": "src/auth/login.go",
|
||
"function": "authenticate",
|
||
"line": 45,
|
||
"severity": "MEDIUM",
|
||
"metric": "function_length",
|
||
"value": 60,
|
||
"threshold": 50,
|
||
"suggestion": "建议将此函数拆分为更小的函数"
|
||
}
|
||
]
|
||
},
|
||
"naming": {
|
||
"score": 95,
|
||
"issues": [
|
||
{
|
||
"file": "src/auth/user.go",
|
||
"line": 78,
|
||
"severity": "LOW",
|
||
"type": "variable",
|
||
"name": "x",
|
||
"suggestion": "建议使用更具描述性的名称,如 'retryCount'"
|
||
}
|
||
]
|
||
},
|
||
"comments": {
|
||
"score": 75,
|
||
"coverage": 60,
|
||
"missing_comments": [
|
||
{
|
||
"file": "src/auth/login.go",
|
||
"function": "validateToken",
|
||
"line": 120,
|
||
"suggestion": "建议添加函数注释说明验证逻辑"
|
||
}
|
||
]
|
||
},
|
||
"format": {
|
||
"score": 90,
|
||
"issues": [
|
||
{
|
||
"file": "src/auth/login.go",
|
||
"line": 45,
|
||
"type": "line_length",
|
||
"value": 150,
|
||
"threshold": 120,
|
||
"suggestion": "建议将长行拆分为多行"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### Markdown 格式
|
||
|
||
```markdown
|
||
## 代码质量分析: 85/100 ⭐⭐⭐⭐
|
||
|
||
### 复杂度: 90/100 ✅
|
||
|
||
- 平均圈复杂度: 3.5 ✅
|
||
- 最大圈复杂度: 8 ✅
|
||
- 平均函数长度: 25 行 ✅
|
||
- 最大函数长度: 60 行 ⚠️
|
||
- 最大嵌套层级: 3 ✅
|
||
|
||
#### ⚠️ 需要改进
|
||
|
||
1. **函数过长** - `src/auth/login.go:45`
|
||
- 函数 `authenticate` 长度为 60 行
|
||
- 建议:将此函数拆分为更小的函数
|
||
|
||
### 命名规范: 95/100 ✅
|
||
|
||
#### 💡 改进建议
|
||
|
||
1. **变量命名** - `src/auth/user.go:78`
|
||
- 变量 `x` 命名不够清晰
|
||
- 建议:使用更具描述性的名称,如 'retryCount'
|
||
|
||
### 注释完整性: 75/100 ⚠️
|
||
|
||
- 注释覆盖率: 60%
|
||
|
||
#### ❌ 缺少注释
|
||
|
||
1. **函数注释** - `src/auth/login.go:120`
|
||
- 函数 `validateToken` 缺少注释
|
||
- 建议:添加函数注释说明验证逻辑
|
||
|
||
### 代码格式: 90/100 ✅
|
||
|
||
#### 💡 改进建议
|
||
|
||
1. **行长度** - `src/auth/login.go:45`
|
||
- 行长度为 150 字符
|
||
- 建议:将长行拆分为多行
|
||
```
|
||
|
||
## 💡 最佳实践
|
||
|
||
### 1. 保持函数简短
|
||
|
||
```go
|
||
// ✅ 好的实践
|
||
func handleRequest(req *Request) (*Response, error) {
|
||
if err := validateRequest(req); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
data, err := processRequest(req)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return buildResponse(data), nil
|
||
}
|
||
|
||
// ❌ 不好的实践
|
||
func handleRequest(req *Request) (*Response, error) {
|
||
// 100+ 行代码
|
||
// 验证、处理、响应都在一个函数中
|
||
}
|
||
```
|
||
|
||
### 2. 使用清晰的命名
|
||
|
||
```javascript
|
||
// ✅ 好的实践
|
||
const MAX_RETRY_ATTEMPTS = 3;
|
||
const API_TIMEOUT_MS = 5000;
|
||
|
||
function calculateDiscount(price, discountRate) {
|
||
return price * (1 - discountRate);
|
||
}
|
||
|
||
// ❌ 不好的实践
|
||
const max = 3;
|
||
const t = 5000;
|
||
|
||
function calc(p, d) {
|
||
return p * (1 - d);
|
||
}
|
||
```
|
||
|
||
### 3. 添加有意义的注释
|
||
|
||
```python
|
||
# ✅ 好的注释
|
||
# 实现二分查找算法,时间复杂度 O(log n)
|
||
def binary_search(arr, target):
|
||
left, right = 0, len(arr) - 1
|
||
while left <= right:
|
||
mid = (left + right) // 2
|
||
if arr[mid] == target:
|
||
return mid
|
||
elif arr[mid] < target:
|
||
left = mid + 1
|
||
else:
|
||
right = mid - 1
|
||
return -1
|
||
|
||
# ❌ 不好的注释
|
||
# 查找目标值
|
||
def binary_search(arr, target):
|
||
# ... 显而易见的代码 ...
|
||
```
|
||
|
||
## 🔍 常见问题
|
||
|
||
### Q: 如何平衡代码质量和开发效率?
|
||
|
||
**A**:
|
||
- 对于核心业务逻辑,严格要求代码质量
|
||
- 对于一次性脚本,可以适当放宽标准
|
||
- 使用代码格式化工具自动处理格式问题
|
||
- 定期进行代码重构,而非过度追求完美
|
||
|
||
### Q: 如何处理历史遗留的低质量代码?
|
||
|
||
**A**:
|
||
- 不要求立即重构所有历史代码
|
||
- 在修改相关代码时进行重构
|
||
- 优先重构最常用的核心模块
|
||
- 逐步改进,避免大规模重写
|
||
|
||
### Q: 代码质量工具与 AI 审查如何配合?
|
||
|
||
**A**:
|
||
- 代码质量工具(lint、static analysis)处理规则性检查
|
||
- AI 审查处理语义性、上下文相关的检查
|
||
- 工具提供定量指标,AI 提供定性分析
|
||
- 结合使用,获得全面的代码质量评估
|
||
|
||
## 📚 相关文档
|
||
|
||
- [安全性检查](code-review-security.md) - 安全性分析
|
||
- [性能检查](code-review-performance.md) - 性能分析
|
||
- [可维护性检查](code-review-maintainability.md) - 可维护性分析
|
||
|
||
---
|
||
|
||
*最后更新: 2026-06-12*
|