关于 clean-code
面向开发者的代码质量技能,提供编写可读、易维护代码的实用指导,涵盖命名、职责清晰的函数、核心原则、反模式和质量实践。
主要功能
- 01命名指导
- 02职责单一的函数
- 03提前返回
- 04避免魔法数字
- 05代码质量实践
适用场景
- 01重构嵌套过深的函数
- 02将含糊命名改为清晰命名
- 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 |
权威资料
- Clean Code,作者 Robert C. Martin - https://www.oreilly.com/library/view/clean-code-a/9780136083238/
- Martin Fowler 的 重构目录 - https://refactoring.com/catalog/
生产就绪
代码质量门禁
// 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