Skip to content

代码质量标准与 Lint 规范

AI 生成的代码在风格上可能与团队现有代码库存在差异——变量命名不一致、函数过长、复杂度过高、格式混乱。制定并强制执行统一的 Lint 规范,是将 AI 生成代码纳入可维护代码库的关键步骤。

为什么需要专门针对 AI 代码制定质量规范

AI 模型生成代码时,会根据上下文推断风格,但不了解项目的具体约定。常见问题包括:

  • 风格漂移:生成的代码与文件其他部分缩进、引号风格不一致
  • 过度工程化:为简单功能生成多层抽象,增加认知负担
  • 命名模糊:使用 dataresulttemp 等无意义变量名
  • 注释冗余:大量解释"做了什么"的注释,而非解释"为什么"

ESLint 推荐配置

以下是适用于 TypeScript + React 项目的完整 ESLint 配置,针对 AI 生成代码的常见问题加入了额外规则:

javascript
// eslint.config.js (ESLint v9 flat config)
import js from '@eslint/js';
import typescript from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import react from 'eslint-plugin-react';
import reactHooks from 'eslint-plugin-react-hooks';
import sonarjs from 'eslint-plugin-sonarjs';
import unicorn from 'eslint-plugin-unicorn';

export default [
  js.configs.recommended,
  {
    files: ['**/*.{ts,tsx}'],
    languageOptions: {
      parser: tsParser,
      parserOptions: {
        project: './tsconfig.json',
      },
    },
    plugins: {
      '@typescript-eslint': typescript,
      react,
      'react-hooks': reactHooks,
      sonarjs,
      unicorn,
    },
    rules: {
      // --- TypeScript 严格规则 ---
      '@typescript-eslint/no-explicit-any': 'error',
      '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
      '@typescript-eslint/explicit-function-return-type': 'warn',
      '@typescript-eslint/no-floating-promises': 'error',
      '@typescript-eslint/await-thenable': 'error',

      // --- 复杂度控制(针对 AI 过度生成) ---
      'complexity': ['error', { max: 10 }],
      'max-lines-per-function': ['warn', { max: 50, skipComments: true }],
      'max-depth': ['error', 4],
      'max-params': ['warn', 4],

      // --- SonarJS 代码质量规则 ---
      'sonarjs/cognitive-complexity': ['error', 15],
      'sonarjs/no-duplicate-string': ['warn', { threshold: 3 }],
      'sonarjs/no-identical-functions': 'error',
      'sonarjs/no-redundant-boolean': 'error',

      // --- 命名规范 ---
      'unicorn/prevent-abbreviations': ['warn', {
        replacements: {
          res: { response: true },
          req: { request: true },
          err: { error: true },
          cb: { callback: true },
        },
      }],

      // --- React 规则 ---
      'react-hooks/rules-of-hooks': 'error',
      'react-hooks/exhaustive-deps': 'warn',
      'react/no-array-index-key': 'warn',
    },
  },
];

Prettier 配置

格式化应完全交给 Prettier,ESLint 只负责代码质量,不负责风格:

json
// .prettierrc
{
  "semi": true,
  "singleQuote": true,
  "trailingComma": "all",
  "printWidth": 100,
  "tabWidth": 2,
  "useTabs": false,
  "arrowParens": "always",
  "endOfLine": "lf"
}
json
// .prettierignore
dist/
build/
coverage/
*.min.js

将 Prettier 集成到 ESLint(避免规则冲突):

bash
npm install -D eslint-config-prettier
javascript
// eslint.config.js 末尾添加
import prettierConfig from 'eslint-config-prettier';
export default [
  // ...前面的配置
  prettierConfig,  // 必须放最后,禁用与 Prettier 冲突的规则
];

命名约定规范

类型规范示例
变量/函数camelCase,语义明确userProfile, fetchOrderList
常量UPPER_SNAKE_CASEMAX_RETRY_COUNT, API_BASE_URL
React 组件PascalCaseUserProfileCard, OrderListItem
接口/类型PascalCase,不加 I 前缀UserProfile, ApiResponse<T>
布尔变量is/has/can/should 前缀isLoading, hasPermission
事件处理函数handle 前缀handleSubmit, handleUserClick
文件名(组件)PascalCaseUserProfileCard.tsx
文件名(工具)kebab-caseformat-date.ts, api-client.ts

AI 生成代码中的常见命名问题:

typescript
// 不良:含糊的参数和变量名
async function processData(data: any, config: any) {
  const result = await fetch(config.url, { body: data });
  const temp = await result.json();
  return temp;
}

// 改进:明确表达意图
async function submitOrderForm(
  orderPayload: CreateOrderRequest,
  apiConfig: ApiClientConfig,
): Promise<OrderResponse> {
  const response = await fetch(apiConfig.baseUrl + '/orders', {
    method: 'POST',
    body: JSON.stringify(orderPayload),
  });
  return response.json() as Promise<OrderResponse>;
}

圈复杂度(Cyclomatic Complexity)控制

圈复杂度衡量代码中独立路径的数量。AI 可能生成嵌套层级深、分支多的函数:

typescript
// 圈复杂度 = 9(超标,难以测试)
function calculateDiscount(user: User, order: Order): number {
  let discount = 0;
  if (user.isPremium) {
    if (order.total > 1000) {
      if (order.items.length > 5) {
        discount = 0.2;
      } else {
        discount = 0.15;
      }
    } else {
      if (user.loyaltyYears > 3) {
        discount = 0.1;
      }
    }
  } else {
    if (order.total > 500) {
      discount = 0.05;
    }
  }
  return discount;
}

// 重构后:圈复杂度 = 3,可读性提升
function calculateDiscount(user: User, order: Order): number {
  if (!user.isPremium) return order.total > 500 ? 0.05 : 0;
  if (order.total > 1000) return order.items.length > 5 ? 0.2 : 0.15;
  return user.loyaltyYears > 3 ? 0.1 : 0;
}

复杂度参考标准:

圈复杂度评估建议
1–5简单,易测试保持
6–10尚可接受考虑拆分
11–15较复杂必须重构
> 15高风险阻塞合并

技术债务管理

使用注释标记技术债务,并在 CI 中统计:

typescript
// TODO(#123): AI 生成了暴力搜索,待优化为二分查找
// FIXME: 此处逻辑与 UserService.findById 重复,待合并
// HACK: 临时绕过第三方 SDK bug,待 v2.3.0 发布后移除
// DEBT: 缺少错误处理,影响用户体验

在 CI 中统计并限制 TODO 数量:

yaml
# .github/workflows/quality.yml
- name: 统计技术债务
  run: |
    count=$(grep -rE "(TODO|FIXME|HACK|DEBT):" src/ | wc -l)
    echo "技术债务条目: $count"
    if [ "$count" -gt 20 ]; then
      echo "技术债务过多,请优先消化后再引入新的 AI 生成代码"
      exit 1
    fi

代码审查中的质量检查要点

在 Review AI 生成代码时,重点关注以下问题:

  • 重复代码:AI 有时会生成与现有工具函数功能相同的新函数,应引导复用
  • 过度抽象:评估抽象层是否真的有必要,而非为了"看起来像设计模式"
  • 错误处理缺失:AI 在示例代码中常省略 try/catch 和边界条件处理
  • 类型断言滥用as anyas unknown as T 是类型安全的漏洞
typescript
// 危险:类型断言绕过了 TypeScript 保护
const user = JSON.parse(response) as User;

// 安全:运行时验证
import { z } from 'zod';
const UserSchema = z.object({ id: z.number(), name: z.string() });
const user = UserSchema.parse(JSON.parse(response));

推荐工具链

bash
# 安装完整工具链
npm install -D \
  eslint \
  @eslint/js \
  @typescript-eslint/parser \
  @typescript-eslint/eslint-plugin \
  eslint-plugin-react \
  eslint-plugin-react-hooks \
  eslint-plugin-sonarjs \
  eslint-plugin-unicorn \
  eslint-config-prettier \
  prettier \
  lint-staged \
  husky
json
// package.json — 提交前自动 lint
{
  "lint-staged": {
    "*.{ts,tsx}": ["eslint --fix", "prettier --write"],
    "*.{json,md,yml}": ["prettier --write"]
  }
}
bash
# 初始化 husky(在 git 提交前自动执行 lint-staged)
npx husky init
echo "npx lint-staged" > .husky/pre-commit

通过将上述配置提交到代码仓库,可以确保无论是人工编写还是 AI 生成的代码,在进入代码库之前都经过统一的质量过滤。