code-simplification

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Code Simplification

代码简化

Inspired by the Claude Code Simplifier plugin. Adapted here as a model-agnostic, process-driven skill for any AI coding agent.
灵感来源于 Claude Code Simplifier plugin,此处适配为可用于任意AI编码Agent的模型无关、流程驱动的技能。

Overview

概述

Simplify code by reducing complexity while preserving exact behavior. The goal is not fewer lines — it's code that is easier to read, understand, modify, and debug. Every simplification must pass a simple test: "Would a new team member understand this faster than the original?"
在完全保留代码行为的前提下通过降低复杂度来简化代码。我们的目标不是减少代码行数,而是让代码更易读、易懂、易修改、易调试。每一处简化都需要通过一个简单的测试:"新的团队成员能比读原版代码更快理解这段代码吗?"

When to Use

适用场景

  • After a feature is working and tests pass, but the implementation feels heavier than it needs to be
  • During code review when readability or complexity issues are flagged
  • When you encounter deeply nested logic, long functions, or unclear names
  • When refactoring code written under time pressure
  • When consolidating related logic scattered across files
  • After merging changes that introduced duplication or inconsistency
When NOT to use:
  • Code is already clean and readable — don't simplify for the sake of it
  • You don't understand what the code does yet — comprehend before you simplify
  • The code is performance-critical and the "simpler" version would be measurably slower
  • You're about to rewrite the module entirely — simplifying throwaway code wastes effort
  • 功能已开发完成且测试通过,但实现逻辑比必要的更繁重
  • 代码评审过程中发现了可读性或复杂度问题
  • 遇到深度嵌套的逻辑、过长的函数或者表意不明的命名
  • 重构赶工完成的代码
  • 整合散落在多个文件中的相关逻辑
  • 合并了引入重复代码或不一致性的变更之后
不适用场景:
  • 代码已经足够整洁可读——不要为了简化而简化
  • 你还没理解代码的功能——先搞懂再简化
  • 代码是性能关键型的,所谓的"更简单"版本运行速度会明显更慢
  • 你正打算完全重写这个模块——简化即将废弃的代码是浪费精力

The Five Principles

五大原则

1. Preserve Behavior Exactly

1. 完全保留代码行为

Don't change what the code does — only how it expresses it. All inputs, outputs, side effects, error behavior, and edge cases must remain identical. If you're not sure a simplification preserves behavior, don't make it.
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?
不要改变代码的功能——只改变代码的表达形式。所有输入、输出、副作用、错误行为、边界 case 都必须保持完全一致。如果你不确定某一处简化是否会改变代码行为,就不要做这个改动。
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. Follow Project Conventions

2. 遵循项目规范

Simplification means making code more consistent with the codebase, not imposing external preferences. Before simplifying:
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
Simplification that breaks project consistency is not simplification — it's churn.
简化意味着让代码和代码库的其余部分更一致,而不是强加外部的偏好。简化前:
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. Prefer Clarity Over Cleverness

3. 清晰优先于巧妙

Explicit code is better than compact code when the compact version requires a mental pause to parse.
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);
}
如果简洁版本的代码需要停顿思考才能读懂,那么显式代码优于简洁代码。
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. Maintain Balance

4. 保持平衡

Simplification has a failure mode: over-simplification. Watch for these traps:
  • Inlining too aggressively — removing a helper that gave a concept a name makes the call site harder to read
  • Combining unrelated logic — two simple functions merged into one complex function is not simpler
  • Removing "unnecessary" abstraction — some abstractions exist for extensibility or testability, not complexity
  • Optimizing for line count — fewer lines is not the goal; easier comprehension is
简化有一个失败模式:过度简化。注意避免以下陷阱:
  • 过度激进的内联——移除了用来给概念命名的辅助函数会让调用位置更难读
  • 合并无关逻辑——把两个简单函数合并成一个复杂函数并不会更简单
  • 移除"不必要"的抽象——有些抽象是为了扩展性或可测试性存在的,不是为了增加复杂度
  • 追求代码行数最少——更少的行数不是目标,更容易理解才是

5. Scope to What Changed

5. 限定改动范围

Default to simplifying recently modified code. Avoid drive-by refactors of unrelated code unless explicitly asked to broaden scope. Unscoped simplification creates noise in diffs and risks unintended regressions.
默认只简化最近修改过的代码。除非明确要求扩大范围,否则不要随意重构无关代码。无范围限制的简化会在diff中产生噪音,还会带来意外回归的风险。

The Simplification Process

简化流程

Step 1: Understand Before Touching (Chesterton's Fence)

步骤1:改动前先理解(切斯特顿围栏原则)

Before changing or removing anything, understand why it exists. This is Chesterton's Fence: if you see a fence across a road and don't understand why it's there, don't tear it down. First understand the reason, then decide if the reason still applies.
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?
If you can't answer these, you're not ready to simplify. Read more context first.
在修改或删除任何内容之前,先理解它为什么存在。这就是切斯特顿围栏原则:如果你看到路中间有一道围栏,却不知道它为什么存在,不要直接把它拆掉。先搞懂存在的原因,再判断这个原因是否还成立。
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?
如果你回答不了这些问题,说明你还没做好简化的准备,先去了解更多上下文。

Step 2: Identify Simplification Opportunities

步骤2:识别简化机会

Scan for these patterns — each one is a concrete signal, not a vague smell:
Structural complexity:
PatternSignalSimplification
Deep nesting (3+ levels)Hard to follow control flowExtract conditions into guard clauses or helper functions
Long functions (50+ lines)Multiple responsibilitiesSplit into focused functions with descriptive names
Nested ternariesRequires mental stack to parseReplace with if/else chains, switch, or lookup objects
Boolean parameter flags
doThing(true, false, true)
Replace with options objects or separate functions
Repeated conditionalsSame
if
check in multiple places
Extract to a well-named predicate function
Naming and readability:
PatternSignalSimplification
Generic names
data
,
result
,
temp
,
val
,
item
Rename to describe the content:
userProfile
,
validationErrors
Abbreviated names
usr
,
cfg
,
btn
,
evt
Use full words unless the abbreviation is universal (
id
,
url
,
api
)
Misleading namesFunction named
get
that also mutates state
Rename to reflect actual behavior
Comments explaining "what"
// increment counter
above
count++
Delete the comment — the code is clear enough
Comments explaining "why"
// Retry because the API is flaky under load
Keep these — they carry intent the code can't express
Redundancy:
PatternSignalSimplification
Duplicated logicSame 5+ lines in multiple placesExtract to a shared function
Dead codeUnreachable branches, unused variables, commented-out blocksRemove (after confirming it's truly dead)
Unnecessary abstractionsWrapper that adds no valueInline the wrapper, call the underlying function directly
Over-engineered patternsFactory-for-a-factory, strategy-with-one-strategyReplace with the simple direct approach
Redundant type assertionsCasting to a type that's already inferredRemove the assertion
扫描以下模式——每一个都是具体的信号,不是模糊的坏味道:
结构复杂度:
模式信号简化方案
深度嵌套(3层及以上)控制流难以跟踪将条件提取为守卫子句或辅助函数
过长函数(超过50行)承担了多个职责拆分为多个命名清晰的单一职责函数
嵌套三元表达式需要在脑中维护调用栈才能读懂替换为if/else链、switch或查找对象
布尔参数标志
doThing(true, false, true)
替换为配置对象或独立的函数
重复条件判断多个位置出现相同的
if
检查
提取为命名清晰的谓词函数
命名和可读性:
模式信号简化方案
通用命名
data
result
temp
val
item
重命名为描述内容的名字:
userProfile
validationErrors
缩写命名
usr
cfg
btn
evt
使用完整单词,除非是通用缩写(
id
url
api
误导性命名名为
get
的函数同时会修改状态
重命名以反映实际行为
解释"做了什么"的注释
// increment counter
above
count++
删除注释——代码本身已经足够清晰
解释"为什么这么做"的注释
// Retry because the API is flaky under load
保留这些注释——它们承载了代码无法表达的意图
冗余:
模式信号简化方案
重复逻辑多个位置出现相同的5行以上代码提取为公共函数
死代码不可达分支、未使用变量、被注释的代码块确认确实无用后删除
不必要的抽象没有提供任何价值的包装层内联包装层,直接调用底层函数
过度设计的模式为工厂再建工厂、只有一个实现的策略模式替换为简单直接的实现方式
冗余类型断言转换为已经被推断出的类型移除类型断言

Step 3: Apply Changes Incrementally

步骤3:增量应用改动

Make one simplification at a time. Run tests after each change. Submit refactoring changes separately from feature or bug fix changes. A PR that refactors and adds a feature is two PRs — split them.
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
Avoid batching multiple simplifications into a single untested change. If something breaks, you need to know which simplification caused it.
The Rule of 500: If a refactoring would touch more than 500 lines, invest in automation (codemods, sed scripts, AST transforms) rather than making the changes by hand. Manual edits at that scale are error-prone and exhausting to review.
一次只做一处简化。每次改动后都运行测试。重构改动要和功能或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行代码,优先使用自动化工具(codemods、sed脚本、AST转换),不要手动修改。这种规模的手动修改容易出错,评审也非常消耗精力。

Step 4: Verify the Result

步骤4:验证结果

After all simplifications, step back and evaluate the whole:
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?
If the "simplified" version is harder to understand or review, revert. Not every simplification attempt succeeds.
所有简化完成后,退一步整体评估:
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?
如果"简化"后的版本更难理解或评审,就回滚。不是每一次简化尝试都会成功。

Language-Specific Guidance

语言特定指导

TypeScript / JavaScript

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;
}
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

python
undefined
python
undefined

SIMPLIFY: Verbose dictionary building

SIMPLIFY: Verbose dictionary building

Before

Before

result = {} for item in items: result[item.id] = item.name
result = {} for item in items: result[item.id] = item.name

After

After

result = {item.id: item.name for item in items}
result = {item.id: item.name for item in items}

SIMPLIFY: Nested conditionals with early return

SIMPLIFY: Nested conditionals with early return

Before

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")
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

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)
undefined
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)
undefined

React / JSX

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.
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.

Common Rationalizations

常见借口

RationalizationReality
"It's working, no need to touch it"Working code that's hard to read will be hard to fix when it breaks. Simplifying now saves time on every future change.
"Fewer lines is always simpler"A 1-line nested ternary is not simpler than a 5-line if/else. Simplicity is about comprehension speed, not line count.
"I'll just quickly simplify this unrelated code too"Unscoped simplification creates noisy diffs and risks regressions in code you didn't intend to change. Stay focused.
"The types make it self-documenting"Types document structure, not intent. A well-named function explains why better than a type signature explains what.
"This abstraction might be useful later"Don't preserve speculative abstractions. If it's not used now, it's complexity without value. Remove it and re-add when needed.
"The original author must have had a reason"Maybe. Check git blame — apply Chesterton's Fence. But accumulated complexity often has no reason; it's just the residue of iteration under pressure.
"I'll refactor while adding this feature"Separate refactoring from feature work. Mixed changes are harder to review, revert, and understand in history.
借口现实
"它能正常运行,没必要动"难读的可运行代码出问题时也很难修。现在简化可以节省未来每次改动的时间。
"代码行数越少越简单"一行嵌套三元表达式并不比5行if/else更简单。简单性取决于理解速度,不是代码行数。
"我顺便快速简化下这段无关代码"无范围的简化会产生嘈杂的diff,还会给你没打算改动的代码带来回归风险。保持专注。
"类型已经让代码自文档化了"类型只能记录结构,不能记录意图。命名良好的函数解释"为什么"的能力远胜解释"是什么"的类型签名。
"这个抽象以后可能有用"不要保留推测性的抽象。如果现在没用,它就是没有价值的复杂度。删掉它,等需要的时候再加回来。
"原作者肯定有这么写的理由"也许吧。查看git blame——应用切斯特顿围栏原则。但累积的复杂度往往没有理由,只是赶工迭代留下的残渣。
"我加功能的时候顺便重构"把重构和功能开发分开。混合改动更难评审、更难回滚、也更难在历史记录中理解。

Red Flags

危险信号

  • Simplification that requires modifying tests to pass (you likely changed behavior)
  • "Simplified" code that is longer and harder to follow than the original
  • Renaming things to match your preferences rather than project conventions
  • Removing error handling because "it makes the code cleaner"
  • Simplifying code you don't fully understand
  • Batching many simplifications into one large, hard-to-review commit
  • Refactoring code outside the scope of the current task without being asked
  • 简化需要修改测试才能通过(你很可能改了代码行为)
  • "简化"后的代码比原版更长、更难理解
  • 按照个人偏好而非项目规范重命名
  • 以"让代码更整洁"为由移除错误处理
  • 简化你没有完全理解的代码
  • 把多个简化合并成一个难以评审的大提交
  • 没有被要求就重构当前任务范围外的代码

Verification

验证项

After completing a simplification pass:
  • All existing tests pass without modification
  • Build succeeds with no new warnings
  • Linter/formatter passes (no style regressions)
  • Each simplification is a reviewable, incremental change
  • The diff is clean — no unrelated changes mixed in
  • Simplified code follows project conventions (checked against CLAUDE.md or equivalent)
  • No error handling was removed or weakened
  • No dead code was left behind (unused imports, unreachable branches)
  • A teammate or review agent would approve the change as a net improvement
完成一次简化流程后:
  • 所有现有测试无需修改即可通过
  • 构建成功,没有新的警告
  • Linter/格式化工具校验通过(没有样式回归)
  • 每一处简化都是可评审的增量改动
  • Diff干净——没有混入无关改动
  • 简化后的代码遵循项目规范(对照CLAUDE.md或等效文档检查)
  • 没有移除或削弱错误处理
  • 没有遗留死代码(未使用的导入、不可达分支)
  • 同事或评审Agent会认可这是一次净收益的改动