ワンクリックで
code-simplification
为清晰性而简化代码。在重构代码以提高可读性而不改变行为时使用。当代码可以正常工作但比应有的更难阅读、维护或扩展时使用。在审查已积累不必要复杂性的代码时使用。当组件过度设计、过于炫技而难以维护时使用。当需要清理越来越难读懂的代码时使用。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
为清晰性而简化代码。在重构代码以提高可读性而不改变行为时使用。当代码可以正常工作但比应有的更难阅读、维护或扩展时使用。在审查已积累不必要复杂性的代码时使用。当组件过度设计、过于炫技而难以维护时使用。当需要清理越来越难读懂的代码时使用。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
| name | code-simplification |
| description | 为清晰性而简化代码。在重构代码以提高可读性而不改变行为时使用。当代码可以正常工作但比应有的更难阅读、维护或扩展时使用。在审查已积累不必要复杂性的代码时使用。当组件过度设计、过于炫技而难以维护时使用。当需要清理越来越难读懂的代码时使用。 |
灵感来源于 Claude Code Simplifier 插件。此处改编为一个模型无关的、面向任何 AI 编码智能体的流程驱动型技能。
通过降低复杂度同时保持精确行为来简化代码。目标不是更少的行数——而是更易于阅读、理解、修改和调试的代码。每个简化都必须通过一个简单的测试:"新团队成员会比原始代码更快地理解它吗?"
何时不使用:
不要改变代码做什么——只改变它如何表达。所有输入、输出、副作用、错误行为和边界情况必须保持完全相同。如果你不确定一个简化是否保持行为,就不要做。
每次变更前自问:
→ 这对每个输入都产生相同的输出吗?
→ 这保持了相同的错误行为吗?
→ 这保持了相同的副作用和顺序吗?
→ 所有现有测试是否仍在无修改的情况下通过?
简化意味着使代码与代码库更一致,而非强加外部偏好。在简化之前:
1. 阅读 CLAUDE.md / 项目约定
2. 研究相邻代码如何处理类似模式
3. 在以下方面匹配项目风格:
- Import 排序和模块系统
- 函数声明风格
- 命名约定
- 错误处理模式
- 类型注解深度
破坏项目一致性的简化不是简化——它是无谓的改动。
显式代码优于紧凑代码——当紧凑版本需要大脑停顿来解析时。
// 不清晰:密集的条件链
label := choose(isNew, "New", choose(isUpdated, "Updated", choose(isArchived, "Archived", "Active")))
// 清晰:可读的 switch
func statusLabel(item *Item) string {
switch {
case item.IsNew:
return "New"
case item.IsUpdated:
return "Updated"
case item.IsArchived:
return "Archived"
}
return "Active"
}
// 不清晰:硬套函数式风格的一行聚合
result := lo.Reduce(items, func(acc map[string]int, it Item, _ int) map[string]int {
acc[it.ID]++
return acc
}, map[string]int{})
// 清晰:命名的中间步骤
countByID := make(map[string]int)
for _, item := range items {
countByID[item.ID]++
}
简化有一个失败模式:过度简化。注意这些陷阱:
默认只简化最近修改的代码。避免对不相关代码的顺手重构,除非被明确要求扩大范围。无范围的简化会在 diff 中制造噪音,并有意外回归的风险。
在改变或移除任何东西之前,理解它为什么存在。这就是切斯特顿之栅栏:如果你看到路中间有一道栅栏且不明白它为什么在那里,不要拆除它。先理解原因,然后决定这个原因是否仍然适用。
简化之前,回答:
- 这段代码的职责是什么?
- 谁调用它?它调用什么?
- 边界情况和错误路径是什么?
- 是否有定义预期行为的测试?
- 它为什么可能以这种方式编写?(性能?平台限制?历史原因?)
- 检查 git blame:这段代码的原始上下文是什么?
如果你不能回答这些问题,你就没有准备好进行简化。先阅读更多上下文。
扫描以下模式——每一个都是一个具体的信号,而非模糊的异味:
结构性复杂度:
| 模式 | 信号 | 简化方法 |
|---|---|---|
| 深层嵌套(3+ 层) | 难以跟踪控制流 | 将条件提取为卫语句或辅助函数 |
| 过长函数(50+ 行) | 多重职责 | 拆分为具有描述性名称的专注函数 |
| 嵌套三元表达式 | 需要脑内栈来解析 | 替换为 if/else 链、switch 或查找对象 |
| 布尔参数标志 | doThing(true, false, true) | 替换为选项对象或独立函数 |
| 重复的条件判断 | 多处出现相同的 if 检查 | 提取为命名良好的谓词函数 |
命名和可读性:
| 模式 | 信号 | 简化方法 |
|---|---|---|
| 通用名称 | data、result、temp、val、item | 重命名以描述内容:userProfile、validationErrors |
| 缩写名称 | usr、cfg、hdlr、stat | 使用完整单词,除非缩写是通用的(id、url、api) |
| 误导性名称 | 名为 get 的函数也会改变状态 | 重命名以反映实际行为 |
| 解释"what"的注释 | count++ 上面的 // increment counter | 删除注释——代码已经足够清晰 |
| 解释"why"的注释 | // Retry because the API is flaky under load | 保留这些——它们传达了代码无法表达的意图 |
冗余:
| 模式 | 信号 | 简化方法 |
|---|---|---|
| 重复逻辑 | 多处出现相同的 5+ 行代码 | 提取为共享函数 |
| 死代码 | 不可达的分支、未使用的变量、被注释掉的代码块 | 移除(在确认确实死代码之后) |
| 不必要的抽象 | 不增加价值的包装器 | 内联包装器,直接调用底层函数 |
| 过度工程化模式 | 为工厂创建的工厂、只有一个策略的策略模式 | 替换为简单直接的方法 |
| 冗余的类型断言 | 强转为已经推断出的类型 | 移除断言 |
一次做一个简化。每次变更后运行测试。将重构变更与功能或缺陷修复变更分开提交。 一个既重构又添加功能的 PR 是两个 PR——拆分它们。
对于每个简化:
1. 进行变更
2. 运行测试套件
3. 如果测试通过 → 提交(或继续下一个简化)
4. 如果测试失败 → 撤销并重新考虑
避免将多个简化批处理为一个未测试的变更。如果出现问题,你需要知道是哪个简化导致的。
500 行规则: 如果重构将触及超过 500 行,投资于自动化(codemod、sed 脚本、AST 转换)而非手动改动。该规模的手动编辑容易出错且令人筋疲力尽地审查。
所有简化之后,退后一步评估整体:
比较前后:
- 简化后的版本是否确实更容易理解?
- 你是否引入了任何与代码库不一致的新模式?
- Diff 是否干净且可审查?
- 同事会批准这个变更吗?
如果"简化后"的版本更难理解或审查,就撤销。不是每次简化尝试都会成功。
// 简化:不必要的包装函数
// 之前
func GetNode(id string) (*Node, error) {
n, err := nodeService.FindByID(id)
if err != nil {
return nil, err
}
return n, nil
}
// 之后
func GetNode(id string) (*Node, error) {
return nodeService.FindByID(id)
}
// 简化:冗长的条件赋值
// 之前
var displayName string
if node.Alias != "" {
displayName = node.Alias
} else {
displayName = node.Hostname
}
// 之后
displayName := cmp.Or(node.Alias, node.Hostname)
// 简化:字符串比较错误
// 之前
if err != nil && err.Error() == "node not found" {
return nil
}
// 之后
if errors.Is(err, ErrNodeNotFound) {
return nil
}
// 简化:冗余的布尔返回
// 之前
func isValid(input string) bool {
if len(input) > 0 && len(input) < 100 {
return true
}
return false
}
// 之后
func isValid(input string) bool {
return len(input) > 0 && len(input) < 100
}
# 简化:冗长的字典构建
# 之前
result = {}
for item in items:
result[item.id] = item.name
# 之后
result = {item.id: item.name for item in items}
# 简化:嵌套条件加提前返回
# 之前
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 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)
// 简化:冗余的 match 布尔
// 之前
let state = match node.is_leader() {
true => State::Leader,
false => State::Follower,
};
// 之后
let state = if node.is_leader() { State::Leader } else { State::Follower };
// 简化:手动传播错误
// 之前
let entry = match log.get(index) {
Ok(e) => e,
Err(err) => return Err(err),
};
// 之后
let entry = log.get(index)?;
// 简化:冗长的 Option 处理
// 之前
let name = match replica.alias {
Some(alias) => alias,
None => replica.hostname.clone(),
};
// 之后
let name = replica.alias.unwrap_or_else(|| replica.hostname.clone());
| 合理化借口 | 现实 |
|---|---|
| "它能用,不用动它" | 能用但难以阅读的代码,在出问题时将难以修复。现在简化能为每一次未来的变更节省时间。 |
| "更少的行总是更简单" | 一行嵌套三元表达式不比五行 if/else 更简单。简单性关乎理解速度,而非行数。 |
| "我顺便快速简化一下这段不相关的代码" | 无范围的简化会制造噪音 diff,并在你不打算修改的代码中带来回归风险。保持专注。 |
| "类型让它自文档化" | 类型文档化的是结构,而非意图。一个命名良好的函数解释为什么,比类型签名解释是什么更好。 |
| "这个抽象以后可能有用" | 不要保留推测性抽象。如果现在不使用它,它就是没有价值的复杂度。移除它,需要时再加回来。 |
| "原作者一定有原因" | 也许。检查 git blame——应用切斯特顿之栅栏。但累积的复杂性往往没有原因;它只是压力下迭代的残留物。 |
| "我在添加这个功能的同时重构" | 将重构与功能工作分开。混合的变更更难审查、更难回滚,在历史中也更难理解。 |
完成简化之后:
指导稳定的 RPC、存储协议和接口设计。在设计节点间 RPC、存储协议语义、模块边界或任何公共接口时使用。在定义 gRPC service、对象存储或文件系统语义、节点间的类型契约,或确立组件边界时使用。
自动化 CI/CD 流水线设置。在设置或修改构建和部署流水线时使用。当需要自动化质量门禁、在 CI 中配置测试运行器,或建立部署策略时使用。当需要处理 CI 上不稳定(flaky)的测试时使用。
进行多维度代码审查。在合并任何变更之前使用。在审查由你自己、另一个智能体或人类编写的代码时使用。当需要在代码进入主分支之前评估其跨多个维度的质量时使用。当需要评估变更的正确性、可读性、架构与性能,或审查 PR/diff 时使用。
验证系统的一致性与持久性承诺。在设计或修改复制协议、写路径、崩溃恢复逻辑时使用。当需要证明已确认的写入不丢失、副本间不发散、崩溃后能恢复到一致状态,或评审 fsync/校验和/事务语义时使用。
优化智能体上下文设置。在开始新会话、智能体输出质量下降、在不同任务之间切换,或需要为项目配置规则文件和上下文时使用。
指导系统化的根因调试。当测试失败、构建中断、行为不符合预期,或遇到任何意外错误时使用。当需要系统化地找到并修复根本原因而非猜测时使用。当服务崩溃(panic)、空指针异常、或之前通过的测试突然挂掉时使用。当生产环境间歇性报错、需要定位根因时使用。当测试或构建昨天还通过、今天就挂了时使用。