# Code Simplification

> 为清晰性简化代码。适用于在不改变行为的前提下重构代码、让其更容易阅读、维护和扩展时，也适用于评审那些已经积累了不必要复杂度的代码。

- Skill: `233i/code-simplification` (Agent Skill)
- Install (CLI): `npx skillmds@latest add 233i/code-simplification`
- Raw SKILL.md: https://api.skillmd.com/api/skills/233i/code-simplification/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: 233i (https://skillmd.com/u/233i)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/233i/code-simplification

---


# 代码简化

> Inspired by the [Claude Code Simplifier plugin](https://github.com/anthropics/claude-plugins-official/blob/main/plugins/code-simplifier/agents/code-simplifier.md). Adapted here as a model-agnostic, process-driven skill for any AI coding agent.

## 概览

通过降低复杂度来简化代码，同时保持行为完全不变。目标不是让代码行数更少，而是让它更容易读、容易理解、容易修改、也更容易调试。每一次简化都应该通过一个简单测试：“一个新加入团队的人，会不会比看原始版本更快看懂它？”

## 何时使用

- 功能已经能跑、测试也通过了，但实现比它应该有的样子更重
- Code review 中指出了可读性或复杂度问题
- 你碰到深层嵌套逻辑、超长函数或命名不清的代码
- 你在整理那些赶工写出来的代码
- 你要把散落在多个文件中的相关逻辑收拢起来
- 合并一些引入重复或不一致的改动之后

**不适用的场景：**

- 代码已经足够干净清晰，不要为了“简化而简化”
- 你还没真正理解代码在干什么，先看懂再简化
- 这段代码是性能热点，而“更简单”的写法会带来可测量的性能损失
- 你马上就要彻底重写这个模块，对废弃代码做简化是在浪费精力

## 五个原则

### 1. 精确保留行为

不要改变代码做的事情，只改变它的表达方式。所有输入、输出、副作用、错误行为和边界情况都必须保持一致。如果你不确定某次“简化”是否保留行为，就不要做。

```
ASK BEFORE EVERY CHANGE:
→ Does this produce the same output for every input?
→ Does this maintain the same error behavior?
→ Does this preserve the same side effects and ordering?
→ Do all existing tests still pass without modification?
```

### 2. 遵守项目约定

简化代码，意味着让它更贴近当前代码库，而不是把你自己的偏好强行带进来。开始简化前：

```
1. Read CLAUDE.md / project conventions
2. Study how neighboring code handles similar patterns
3. Match the project's style for:
   - Import ordering and module system
   - Function declaration style
   - Naming conventions
   - Error handling patterns
   - Type annotation depth
```

如果所谓“简化”打破了代码库一致性，那它不是简化，而是无意义扰动。

### 3. 清晰优先于聪明

当紧凑写法需要人停下来想一下时，显式代码通常更好。

```typescript
// UNCLEAR: Dense ternary chain
const label = isNew ? 'New' : isUpdated ? 'Updated' : isArchived ? 'Archived' : 'Active';

// CLEAR: Readable mapping
function getStatusLabel(item: Item): string {
  if (item.isNew) return 'New';
  if (item.isUpdated) return 'Updated';
  if (item.isArchived) return 'Archived';
  return 'Active';
}
```

```typescript
// UNCLEAR: Chained reduces with inline logic
const result = items.reduce((acc, item) => ({
  ...acc,
  [item.id]: { ...acc[item.id], count: (acc[item.id]?.count ?? 0) + 1 }
}), {});

// CLEAR: Named intermediate step
const countById = new Map<string, number>();
for (const item of items) {
  countById.set(item.id, (countById.get(item.id) ?? 0) + 1);
}
```

### 4. 保持平衡

简化也有失败模式，就是过度简化。要警惕这些陷阱：

- **过度内联**，把本来有清晰概念名的 helper 拆掉，反而让调用处更难懂
- **合并无关逻辑**，两个简单函数合成一个复杂函数，并不叫更简单
- **删掉“看似没必要”的抽象**，有些抽象是为了扩展性或可测性存在，而不是为了炫技
- **只盯行数**，目标不是更短，而是更快理解

### 5. 聚焦在当前范围

默认只简化最近被修改到的代码。除非明确要求扩展范围，否则不要顺手改无关代码。无范围的简化只会让 diff 变噪音，还会带来无谓回归风险。

## 简化流程

### 步骤 1：先理解，再动手（Chesterton's Fence）

在修改或删除任何东西之前，先弄清楚它为什么存在。这就是 Chesterton's Fence：如果你看到路中央有一道篱笆，而你不知道它为什么在那，就不要先拆。先理解原因，再决定这个原因是否还成立。

```
BEFORE SIMPLIFYING, ANSWER:
- What is this code's responsibility?
- What calls it? What does it call?
- What are the edge cases and error paths?
- Are there tests that define the expected behavior?
- Why might it have been written this way? (Performance? Platform constraint? Historical reason?)
- Check git blame: what was the original context for this code?
```

如果这些问题你答不上来，那你还没准备好去简化它。

### 步骤 2：识别简化机会

寻找这些具体模式，它们不是模糊“味道”，而是很实在的信号：

**结构复杂度：**

| 模式 | 信号 | 简化方式 |
|---------|--------|----------------|
| 深层嵌套（3 层以上） | 控制流难以跟踪 | 提前返回、guard clause，或抽 helper |
| 长函数（50+ 行） | 职责过多 | 拆成小而有清晰名字的函数 |
| 嵌套三元表达式 | 阅读时需要额外脑内堆栈 | 改成 if/else、switch 或查表 |
| 布尔参数标志位 | 出现 `doThing(true, false, true)` | 改成 options object 或拆函数 |
| 重复条件判断 | 相同 `if` 在多处出现 | 抽成有语义名字的谓词函数 |

**命名与可读性：**

| 模式 | 信号 | 简化方式 |
|---------|--------|----------------|
| 泛泛命名 | `data`、`result`、`temp`、`val`、`item` | 改成能说明内容的名字，如 `userProfile` |
| 过度缩写 | `usr`、`cfg`、`btn`、`evt` | 除通用缩写外，尽量用完整单词 |
| 误导性命名 | 叫 `get` 的函数实际上会修改状态 | 名字要反映真实行为 |
| 注释解释 “what” | `// increment counter` 写在 `count++` 上方 | 这种注释删掉 |
| 注释解释 “why” | `// Retry because the API is flaky under load` | 这种注释要保留 |

**冗余：**

| 模式 | 信号 | 简化方式 |
|---------|--------|----------------|
| 重复逻辑 | 同样的 5 行以上代码出现在多处 | 抽公共函数 |
| 死代码 | 不可达分支、未使用变量、注释掉的旧块 | 确认真死后删除 |
| 无价值抽象 | 包了一层但没有真正带来意义 | 内联 wrapper，直接调用底层函数 |
| 过度设计模式 | factory-for-a-factory，单策略的 strategy | 换回直接简单方案 |
| 冗余类型断言 | 明明可推导还强转一次 | 删除断言 |

### 步骤 3：增量应用改动

一次做一个简化，做完就跑测试。**重构改动要和功能 / bug 修复改动分开提交。** 一个 PR 同时做重构和功能，本质上是两个 PR。

```
FOR EACH SIMPLIFICATION:
1. Make the change
2. Run the test suite
3. If tests pass → commit (or continue to next simplification)
4. If tests fail → revert and reconsider
```

不要把多个简化打包成一个未经验证的大改动。要是出了问题，你需要知道是哪一次简化导致的。

**500 规则：** 如果某次重构要改超过 500 行，就应考虑自动化工具，例如 codemod、sed 脚本、AST transform，而不是手工一点点改。那种规模的手工修改既容易出错，也很难 review。

### 步骤 4：验证结果

所有简化做完后，退一步整体看：

```
COMPARE BEFORE AND AFTER:
- Is the simplified version genuinely easier to understand?
- Did you introduce any new patterns inconsistent with the codebase?
- Is the diff clean and reviewable?
- Would a teammate approve this change?
```

如果所谓“简化”版本实际上更难懂、更难审，那就撤回。不是每一次简化尝试都会成功。

## 语言特定建议

### TypeScript / JavaScript

```typescript
// SIMPLIFY: Unnecessary async wrapper
// Before
async function getUser(id: string): Promise<User> {
  return await userService.findById(id);
}
// After
function getUser(id: string): Promise<User> {
  return userService.findById(id);
}

// SIMPLIFY: Verbose conditional assignment
// Before
let displayName: string;
if (user.nickname) {
  displayName = user.nickname;
} else {
  displayName = user.fullName;
}
// After
const displayName = user.nickname || user.fullName;

// SIMPLIFY: Manual array building
// Before
const activeUsers: User[] = [];
for (const user of users) {
  if (user.isActive) {
    activeUsers.push(user);
  }
}
// After
const activeUsers = users.filter((user) => user.isActive);

// SIMPLIFY: Redundant boolean return
// Before
function isValid(input: string): boolean {
  if (input.length > 0 && input.length < 100) {
    return true;
  }
  return false;
}
// After
function isValid(input: string): boolean {
  return input.length > 0 && input.length < 100;
}
```

### Python

```python
# SIMPLIFY: Verbose dictionary building
# Before
result = {}
for item in items:
    result[item.id] = item.name
# After
result = {item.id: item.name for item in items}

# SIMPLIFY: Nested conditionals with early return
# Before
def process(data):
    if data is not None:
        if data.is_valid():
            if data.has_permission():
                return do_work(data)
            else:
                raise PermissionError("No permission")
        else:
            raise ValueError("Invalid data")
    else:
        raise TypeError("Data is None")
# After
def process(data):
    if data is None:
        raise TypeError("Data is None")
    if not data.is_valid():
        raise ValueError("Invalid data")
    if not data.has_permission():
        raise PermissionError("No permission")
    return do_work(data)
```

### React / JSX

```tsx
// SIMPLIFY: Verbose conditional rendering
// Before
function UserBadge({ user }: Props) {
  if (user.isAdmin) {
    return <Badge variant="admin">Admin</Badge>;
  } else {
    return <Badge variant="default">User</Badge>;
  }
}
// After
function UserBadge({ user }: Props) {
  const variant = user.isAdmin ? 'admin' : 'default';
  const label = user.isAdmin ? 'Admin' : 'User';
  return <Badge variant={variant}>{label}</Badge>;
}

// SIMPLIFY: Prop drilling through intermediate components
// Before — consider whether context or composition solves this better.
// This is a judgment call — flag it, don't auto-refactor.
```

## 常见自我安慰

| 自我安慰 | 现实 |
|---|---|
| “它现在能跑，没必要动” | 能跑但难懂的代码，出问题时也会更难修。现在简化，能为未来每次改动省时间。 |
| “行数越少就越简单” | 一行嵌套三元表达式，通常不如五行 if/else 简单。简单是看理解速度，不是看行数。 |
| “顺手把这段无关代码也简化一下” | 无范围简化只会制造噪音 diff，还会引入你本来不打算承担的风险。 |
| “类型已经足够自解释了” | 类型只能说明结构，说明不了意图。一个命名好的函数，比一个类型签名更能解释 why。 |
| “这个抽象以后可能会有用” | 不要为假想中的未来保留抽象。现在没用，就是没有价值的复杂度。 |
| “原作者肯定有他的理由” | 也许有。先看 `git blame`，遵守 Chesterton's Fence。但很多复杂度只是历史压力下堆积出来的残留。 |
| “我加功能的时候顺手重构一下” | 重构和功能要分开。混合改动更难 review、更难回滚、历史也更难读。 |

## 危险信号

- 为了让简化通过而去修改测试，这通常意味着你改了行为
- “简化后”的代码反而更长、更难理解
- 按你自己的偏好重命名，而不是按项目约定
- 因为“这样更清爽”就删掉错误处理
- 在还没真正理解代码前就开始简化
- 把很多简化揉进一个很大、很难审的提交
- 未经要求就去重构当前任务范围外的代码

## 验证

完成一轮简化后，确认：

- [ ] 所有现有测试都无需修改即可通过
- [ ] 构建成功，没有新增 warning
- [ ] Linter / formatter 通过，没有样式回退
- [ ] 每次简化都是可 review 的增量改动
- [ ] Diff 很干净，没有混入无关改动
- [ ] 简化后的代码遵守项目约定，已对照 CLAUDE.md 或等价规则
- [ ] 没有移除或削弱错误处理
- [ ] 没有留下死代码，例如未使用 import、不可达分支
- [ ] 同事或 review agent 会认为这是一项净改进

