61 lines
1.9 KiB
Markdown
61 lines
1.9 KiB
Markdown
---
|
||
title: "PrematureAbstraction"
|
||
type: concept
|
||
tags: [engineering, code-quality, design]
|
||
last_updated: 2026-05-02
|
||
---
|
||
|
||
## Definition
|
||
|
||
过早抽象(PrematureAbstraction)指在实际需要提取抽象之前(通常指第三次出现之前)就引入辅助函数、类或接口的代码设计反模式。这导致引入短期内无法偿还的隐性债务。
|
||
|
||
## Core Rule
|
||
|
||
**等待第四次出现再提取。** 前三次重复出现时,保持重复代码而非提取抽象。提取的时机应基于实际的调用次数,而非"直觉上看起来应该提取"。
|
||
|
||
## Why Wait for the Fourth Time
|
||
|
||
- **第一次**:孤例,可能是一次性的特殊处理
|
||
- **第二次**:可能是巧合,模式尚不清晰
|
||
- **第三次**:确认存在模式,但抽象接口(参数、返回值、边界情况)尚未完全明确
|
||
- **第四次**:抽象接口足够清晰,且维护收益开始超过抽象本身的成本
|
||
|
||
## Examples
|
||
|
||
### ❌ 过早抽象(第二次就提取)
|
||
|
||
```typescript
|
||
// 第二次出现就开始提取
|
||
const dryRun = args.includes('--dry-run');
|
||
if (dryRun) logDryRun(records);
|
||
|
||
// 马上为第三次出现提取
|
||
export function runWithMode(mode: RunMode, records: Record[]) {
|
||
// strategy pattern introduced too early
|
||
}
|
||
```
|
||
|
||
### ✅ 延迟抽象(第四次才提取)
|
||
|
||
```typescript
|
||
// 保持三次重复
|
||
if (dryRun) logDryRun(records);
|
||
if (dryRun) logDryRun(items);
|
||
if (dryRun) logDryRun(entries);
|
||
|
||
// 第四次出现——抽象接口完全清晰了
|
||
export function runDry(records: Record[]) {
|
||
return { dry: true, count: records.length };
|
||
}
|
||
```
|
||
|
||
## Connections
|
||
|
||
- [[engineering-minimal-change-engineer]]:最小变更工程师的核心原则之一
|
||
- [[ScopeCreep]]:过早抽象通常是范围蔓延的表现形式
|
||
- [[MinimalChangePrinciple]]:最小变更原则的延伸——保持重复代码直到收益明确
|
||
|
||
## Sources
|
||
|
||
- [[engineering-minimal-change-engineer]]
|