mcpField
C
clean-code

clean-code

github.com/claude-dev-suite开发4651 次安装4 天前更新
代码仓库

关于 clean-code

面向开发者的代码质量技能,提供编写可读、易维护代码的实用指导,涵盖命名、职责清晰的函数、核心原则、反模式和质量实践。

主要功能

  1. 01命名指导
  2. 02职责单一的函数
  3. 03提前返回
  4. 04避免魔法数字
  5. 05代码质量实践

适用场景

  1. 01重构嵌套过深的函数
  2. 02将含糊命名改为清晰命名
  3. 03减少重复代码

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/claude-dev-suite/claude-dev-suite --skill clean-code

安装后在 Claude Code 中输入/clean-code确认已加载。

附带文件quick-ref/principles.mdquick-ref/refactoring.md

详细介绍

Clean Code 核心原则

深入了解:使用技术为 clean-code 的 mcp__documentation__fetch_docs 获取全面文档。

命名

// ❌ Bad
const d = new Date();
const yyyymmdd = formatDate(d);
function calc(a, b) { return a + b; }
const list = users.filter(x => x.active);

// ✅ Good
const currentDate = new Date();
const formattedDate = formatDate(currentDate);
function calculateTotal(price, quantity) { return price * quantity; }
const activeUsers = users.filter(user => user.isActive);

函数

// ❌ Bad - Too many responsibilities
function processUser(user) {
  validateUser(user);
  saveToDatabase(user);
  sendWelcomeEmail(user);
  updateAnalytics(user);
}

// ✅ Good - Single responsibility
function createUser(userData: UserInput): User {
  const user = validateAndBuildUser(userData);
  return userRepository.save(user);
}

// Separately handle side effects
async function onUserCreated(user: User) {
  await sendWelcomeEmail(user);
  await analytics.trackSignup(user);
}

尽早返回

// ❌ Bad - Nested conditions
function getDiscount(user) {
  if (user) {
    if (user.isPremium) {
      if (user.yearsActive > 2) {
        return 0.2;
      } else {
        return 0.1;
      }
    } else {
      return 0;
    }
  }
  return 0;
}

// ✅ Good - Early returns
function getDiscount(user: User | null): number {
  if (!user) return 0;
  if (!user.isPremium) return 0;
  if (user.yearsActive > 2) return 0.2;
  return 0.1;
}

避免魔法数字

// ❌ Bad
if (user.age >= 18 && items.length <= 10) { ... }
setTimeout(callback, 86400000);

// ✅ Good
const MINIMUM_AGE = 18;
const MAX_CART_ITEMS = 10;
const ONE_DAY_MS = 24 * 60 * 60 * 1000;

if (user.age >= MINIMUM_AGE && items.length <= MAX_CART_ITEMS) { ... }
setTimeout(callback, ONE_DAY_MS);

原则总结

原则描述
DRY不要重复自己
KISS保持简单,傻瓜
YAGNI你不会需要它
SRP单一职责原则
组合优先使用组合,而非继承

不适用此技能的场景

此技能侧重于代码层面的质量。请勿用于:

  • SOLID 原则 - 使用 solid-principles 技能了解面向对象设计原则
  • Git 提交质量 - 使用 git-workflow 技能了解版本控制最佳实践
  • 性能优化 - 使用 performance 技能优化速度和内存
  • 安全漏洞 - 使用 OWASP 或专门的安全技能
  • 构建/工具配置 - 使用特定框架的技能(例如 biome、vite)

反模式

反模式不良之处Clean Code 解决方案
上帝对象类承担了过多职责拆分为职责明确的类(SRP)
魔法数字难以理解其上下文使用有名称的常量
深层嵌套难以理清逻辑尽早返回,提取函数
参数列表过长难以使用和维护使用参数对象或建造者模式
复制粘贴代码会重复引入错误,且难以维护提取共享函数(DRY)
含糊的名称data、temp、x使用能体现意图的名称
Getter 中的副作用行为出乎意料使用纯函数,将查询与命令分开
用注释代替代码注释会过时,代码也显得杂乱使用名称清晰、能自我说明的代码

快速故障排查

问题检查项解决方案
函数复杂圈复杂度 > 10提取更小的函数,尽早返回
代码难以阅读需要注释来解释重命名变量/函数,提取逻辑
逻辑重复多个文件中存在复制粘贴提取到共享工具/服务中
文件过长> 300 行按职责拆分,分离关注点
变量含义不清名称未能体现意图重命名,以说明其包含/表示的内容
出现魔法数字未解释的字面值定义带有描述性名称的 const

权威资料

生产就绪

代码质量门禁
// eslint.config.js
export default [
  {
    rules: {
      // Complexity limits
      complexity: ['error', { max: 10 }],
      'max-depth': ['error', 4],
      'max-lines-per-function': ['warn', { max: 50 }],
      'max-params': ['warn', { max: 4 }],

      // Maintainability
      'no-duplicate-imports': 'error',
      'no-else-return': 'error',
      'prefer-const': 'error',
      'no-var': 'error',
    },
  },
];

// biome.json
{
  "linter": {
    "rules": {
      "complexity": {
        "noExcessiveCognitiveComplexity": {
          "level": "error",
          "options": { "maxAllowedComplexity": 15 }
        }
      }
    }
  }
}
错误处理模式
// Custom error hierarchy
class AppError extends Error {
  constructor(
    message: string,
    public code: string,
    public statusCode: number = 500,
    public isOperational: boolean = true
  ) {
    super(message);
    this.name = this.constructor.name;
    Error.captureStackTrace(this, this.constructor);
  }
}

class ValidationError extends AppError {
  constructor(message: string) {
    super(message, 'VALIDATION_ERROR', 400);
  }
}

class NotFoundError extends AppError {
  constructor(resource: string, id: string) {
    super(`${resource} not found: ${id}`, 'NOT_FOUND', 404);
  }
}

// Error boundary pattern
async function handleRequest<T>(operation: () => Promise<T>): Promise<Result<T>> {
  try {
    const data = await operation();
    return { success: true, data };
  } catch (error) {
    if (error instanceof AppError && error.isOperational) {
      return { success: false, error };
    }
    // Log unexpected errors
    logger.error('Unexpected error', { error });
    throw error; // Re-throw for crash recovery
  }
}
代码审查自动化
# .github/workflows/code-quality.yml
name: Code Quality

on: [push, pull_request]

jobs:
  quality:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: SonarCloud Scan
        uses: SonarSource/sonarcloud-github-action@master
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

      - name: Check cognitive complexity
        run: npx @biomejs/biome check --diagnostic-level=error .

      - name: Detect code duplication
        run: npx jscpd src/ --threshold 5
测试标准
// Test naming convention
describe('UserService', () => {
  describe('createUser', () => {
    it('should create user with valid data', async () => {
      // Arrange
      const userData = { name: 'John', email: '[email protected]' };

      // Act
      const user = await userService.createUser(userData);

      // Assert
      expect(user.id).toBeDefined();
      expect(user.name).toBe('John');
    });

    it('should throw ValidationError for invalid email', async () => {
      // Arrange
      const invalidData = { name: 'John', email: 'invalid' };

      // Act & Assert
      await expect(userService.createUser(invalidData))
        .rejects.toThrow(ValidationError);
    });
  });
});

// Test coverage thresholds
// vitest.config.ts
{
  test: {
    coverage: {
      provider: 'v8',
      thresholds: {
        branches: 80,
        functions: 80,
        lines: 80,
        statements: 80,
      },
    },
  },
}
文档标准
/**
 * Creates a new user in the system.
 *
 * @param data - User creation data
 * @returns The created user with generated ID
 * @throws {ValidationError} If the data is invalid
 * @throws {ConflictError} If email already exists
 *
 * @example
 * ```ts
 * const user = await createUser({
 *   name: 'John Doe',
 *   email: '[email protected]'
 * });
 * ```
 */
async function createUser(data: CreateUserData): Promise<User> {
  // Implementation
}

// README template for modules
/**
 * # User Module
 *
 * ## Overview
 * Handles user management including CRUD operations.
 *
 * ## Usage
 * ```ts
 * import { UserService } from './user';
 * const service = new UserService(repository);
 * ```
 *
 * ## API
 * - `createUser(data)` - Creates a new user
 * - `getUser(id)` - Retrieves user by ID
 * - `updateUser(id, data)` - Updates user data
 */
监控指标
指标目标
认知复杂度< 15
圈复杂度< 10
代码重复率< 5%
测试覆盖率> 80%
技术债务比率< 5%
检查清单
  • 变量/函数名称有意义
  • 函数职责单一
  • 尽早返回以减少嵌套
  • 使用常量替代魔法数字
  • 错误处理一致
  • 在 linter 中设置复杂度限制
  • 测试覆盖率阈值
  • 为公共 API 编写 JSDoc
  • 检测代码重复
  • SonarQube 质量门禁

参考文档

评论

支持 Markdown