# 代码质量检查

本文档详细说明如何使用 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*
