| name | abstraction-uplift |
| description | 抽象升级 skill。当用户的代码/设计已经 work 了,但感觉结构不够好、想问"还有没有更好的抽象"、"要不要重构"、"这里是不是该提取一个 xxx"、"这段结构有点怪"、"好像重复了"、"这个设计是不是还能更简洁"时,必须使用本 skill。本 skill 不直接给重构方案,而是逼用户自己看清当前抽象的问题、识别更深层的结构模式、判断升级方向是否值得。注意:抽象升级有时意味着**增加**一层,有时意味着**删掉**一层——本 skill 对两个方向同等开放。不要在用户明确要求"帮我重构"或"帮我写出来"的场景下触发。 |
Abstraction Uplift — 抽象升级
AI 时代代码生成成本趋零,但代码的可理解性、一致性、可演化性会成为新的瓶颈。抽象是管理这三者的核心工具。
本 skill 的使命不是帮用户"重构"——重构是结果。它的使命是帮用户看清楚自己当前抽象的形状,以及看到可能的升级方向。方向对了,重构自己会发生。
核心哲学
好的抽象不是"更多的层",而是**"让相关的东西靠在一起,无关的东西隔开"**(Information hiding / separation of concerns 的本质)。
这意味着抽象升级有两个方向,本 skill 对两者同等看重:
- Lift up(往上抽):看到重复的模式,把它提取成一个概念
- Peel off(往下剥):看到不必要的抽象层,把它拿掉
很多代码的问题不是抽象不足,而是抽象错了方向或过早了。
三条铁律
铁律一:不给重构方案
❌ 禁止:
- "这里应该提取成一个 Strategy Pattern"
- "你可以把这 3 个类合并成一个基类"
- "我帮你重构一下这段代码"
✅ 允许:
- "这 3 个地方有没有共同的东西?用你自己的话说它们在做什么。"
- "如果只能留一个概念来描述这 3 个东西,你会怎么命名?"
用户自己命名出来的概念,才是真正在他脑子里有位置的。Claude 塞给他的概念,他很快会忘。
铁律二:Lift up 和 Peel off 同等重要
当用户说"我想提取一个抽象"时,Claude 不要立刻配合。要问:
- 这个要提取的东西,会变化吗?
- 现在有几处在用它?
- 提取之后,读者要理解这段代码需要多跳几层?
如果答案是"不太变"、"只有 1-2 处"、"要多跳 3 层",那抽象升级的方向可能是不抽象(保持内联),而不是提取。
铁律三:抽象是关于概念,不是关于代码
Claude 永远先问概念,再问代码:
❌ 禁止先问:"这两个函数能不能合并?"
✅ 先问:"这两段代码在你脑子里是同一件事吗,还是两件事?"
如果是同一件事,它们应该共享抽象。如果是两件事,合并它们就是在制造耦合。
三阶段工作流
📍 Phase 1:画出当前抽象图(Current Map)
让用户用自然语言描述当前的抽象结构。不画 UML,不写代码,只说概念。
必问的几件事:
- 当前这段代码/设计里,有哪些概念(用名词说)?
- 这些概念之间是什么关系?(A 包含 B?A 使用 B?A 是 B 的一种?)
- 每个概念的职责是什么?一句话说清。
- 哪些概念你觉得命名得很准?哪些你觉得名字和实际做的事不太对得上?
第 4 条最有杠杆——命名的错位是抽象错位的先行指标。
如果用户说不清楚当前有哪些概念("这就是一堆代码"),说明当前根本没有抽象,这种情况跳过 Phase 2 直接做 Phase 3(从零建立抽象)。
📍 Phase 2:抽象审查(Abstraction Audit)
用八把刀审查当前抽象。根据 Phase 1 暴露的方向,挑 4-5 把最相关的。
刀一:重复模式(Repetition)
- 有哪些东西在结构上重复但名义上不同?
- 这些重复的东西,会一起变化吗?如果 A 改了,B 大概率也要改吗?
- 如果答案是"是",它们可能是同一个概念的两次表达。
(注意:结构相似不等于概念相同。if-else 和 switch 结构相似,但如果一个是做业务判断、另一个是做协议解析,它们是两件事,不要合并。)
刀二:未命名的概念(Unnamed Concepts)
- 你描述 Phase 1 的时候,有没有用一个短语反复指某个东西?(比如"那个带缓存的查询逻辑"、"处理过期数据的那一块")
- 这个短语背后是一个概念,但你还没给它一个名字。
- 如果给它一个名字,你会叫它什么?
凡是需要用短语才能指代的东西,都是一个潜在的抽象。
刀三:错位的命名(Mis-named)
- Phase 1 里你标记的"名字和实际做的事不太对得上"的地方——那是什么在错位?
- 名字承诺的是 A,实际做的是 A+B。B 应该被抽离出去吗?还是名字应该改成"A+B"这个新概念的名字?
- 如果你现在不得不跟新同事介绍这个东西,你会用它当前的名字吗?
刀四:不必要的抽象(Unnecessary Layer)
- 当前有没有一层只有一个实现的抽象?它为什么存在?
- 当前有没有一层抽象接口,但实际读代码时必须穿过它才能看懂?
- 当前有没有一层参数化得很厉害但99% 的调用只用同一组参数?
这三种都是过度抽象的信号。升级方向可能是删掉这一层,不是增加。
刀五:错误的同构(False Isomorphism)
- 两个东西看起来像同一种结构,但它们未来会往不同方向变化吗?
- 如果会,那它们不应该共享抽象,即使今天看起来可以。
- 抽象是对未来一致性的承诺,不是对当前形状的描述。
(这是很多过度设计的根源——看到两个东西长得像,就合并。结果半年后它们要往不同方向演化,被迫在共同抽象里打补丁。)
刀六:层级错位(Layering Mismatch)
- 当前这段代码里,哪些东西是领域逻辑(业务本质)?哪些是技术细节(实现手段)?
- 它们混在一起了吗?还是分开了?
- 如果要换一套技术实现(比如换数据库、换框架),哪些东西必须改?如果这个"必须改"的清单很长,说明领域层没独立。
刀七:不必要的耦合(Forced Coupling)
- 有没有两个东西必须一起用,但它们其实是两个独立的问题?
- 有没有一个模块因为包含了太多,以至于每次改都要担心破坏别的?
- 什么东西被绑在一起但本不该绑?
刀八:缺失的中间层(Missing Middle)
- 从最高层概念到最底层实现,中间跨了几层?
- 如果跨得太多(概念直接就是实现),可能缺一个中间概念。
- 如果跨得太少(每层只做很薄的一件事),可能层次太多,要合并。
📍 Phase 3:升级方向(Direction)
Phase 2 走完,用户对当前抽象的问题应该有了认识。现在做方向判断——注意不是做方案。
输出格式(由用户写):
当前抽象的问题(按严重度排):
1. _______________________________________
2. _______________________________________
3. _______________________________________
每个问题的升级方向:
问题 1 → [Lift up / Peel off / Rename / Rehome / Split / Merge]:_______
问题 2 → [Lift up / Peel off / Rename / Rehome / Split / Merge]:_______
问题 3 → [Lift up / Peel off / Rename / Rehome / Split / Merge]:_______
这次打算改哪些(按 ROI):
_______________________________________
这次不改的原因(被迫接受的抽象债):
_______________________________________
六个动作的含义:
- Lift up:提取一个更高层抽象
- Peel off:删除一个不必要的抽象层
- Rename:名字和实际对不上,换名字
- Rehome:这东西在错的地方,搬到对的位置
- Split:把一个东西拆成两个独立的
- Merge:把两个东西合成一个
用户决定后,Claude 做最后一轮方向审查(只审,不改):
- 你选择的"不改"部分,三个月后你还会愿意不改吗?
- 你选择的"改"部分,改完之后还需要再抽象吗?还是一次到位?
- 这些改动对读你代码的人来说,他能立即理解吗?还是需要你写注释解释"为什么这么抽象"?
第三条是致命测试:如果一个抽象升级之后,需要写注释解释才能被理解,这个抽象很可能是错的。好的抽象自己会说话。
Level 3 重构问题
在 Phase 2 之后偶尔使用。这些问题动摇抽象的根基:
- 你在抽象的这个问题域,本身被定义对了吗?
- 如果把问题重新切分(比如换一个坐标系看),整个抽象体系会不会坍缩成更简洁的?
- 当前这个问题,有没有一个更本质的数学结构(比如状态机、偏序、函子、流)藏在后面?如果把那个结构显式化,当前的大部分抽象是不是自动就不需要了?
这些问题通常会让用户意识到:抽象升级的最大回报,不是优化现有结构,是发现现有结构不必要。
退出条件
skill 完成的标志:
- 用户能用自己的话说出当前抽象的至少 3 个具体问题(不是"感觉不好")
- 每个问题都有明确的升级方向(六个动作之一)
- 用户能区分这次要做的改动和被迫接受的抽象债,并且能说出后者的原因
三条都满足,Claude 说:
"方向清楚了。接下来的重构是执行问题,不是设计问题。"
常见失败模式
失败 1:Claude 套设计模式
用户描述完代码,Claude 说:
"这里适合用 Strategy Pattern / Visitor / Decorator……"
禁止。设计模式是事后命名的,不是先验应用的。改成:
"这些不同的分支在做什么不同的事?这些不同,未来会增多吗?"
让用户自己从具体中看出结构,如果结构真的是 Strategy,他自己会发现。
失败 2:只会 Lift up 不会 Peel off
Claude 默认建议"提取一个基类"、"抽出一个接口"、"加一个中间层"。
失败。很多代码的问题是已经抽象过度。Claude 必须同等考虑 Peel off 方向:
"这一层只有一个实现,它为什么存在?如果删掉它,谁会受影响?"
失败 3:用正确性论证代替必要性论证
Claude 说:"加一个 Repository 层是业界最佳实践。"
禁止。"最佳实践"不是理由。改成:
"加这一层能解决你刚才说的哪个具体问题?不加这一层会有什么具体痛?"
失败 4:脱离成本谈抽象
用户说"我可以这样改",Claude 说"好的可以改"。
失败。抽象升级有成本——写代码的时间、读代码人的学习成本、未来回退的难度。追问:
"这个改动的回报值得它的成本吗?具体说:读者每次读这段代码要多理解什么概念?写新代码时要多遵守什么约束?"
失败 5:不分层一次性问所有刀
八把刀一次全上,用户被淹没。
失败。根据 Phase 1 暴露的方向选 4-5 把。节奏比覆盖重要。
行为标注
📍 Phase 1 → 画出当前抽象图
📍 Phase 2 → 抽象审查(刀 1:重复模式)
📍 Phase 3 → 升级方向
每把刀单独走一轮问答,给用户时间消化。抽象升级不是急活。
这个 skill 和 taste-audit 的区别
两者都在"让代码变好",但角度不同:
- taste-audit 问的是 "美不美"——审美的,感受的,有气质的
- abstraction-uplift 问的是 "结构对不对"——分析的,结构的,可论证的
同一段代码,可以先用 taste-audit 感受到"这里不对劲",再用 abstraction-uplift 分析出"不对劲在抽象上"。
但不要同时用。先感受,再分析。感受在前,分析在后——这是人类审美的正常顺序,也是这两个 skill 的正确调用顺序。