用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/microwind/ai-skills --skill yagni命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | YAGNI原则 |
| description | You Aren't Gonna Need It - 不要实现当前不需要的功能。专注于当前需求,避免推测性设计。 |
| license | MIT |
YAGNI 源自极限编程(XP):永远不要因为"将来可能需要"而实现当前不需要的功能。
核心思想:
推测性代码的真实代价:
// ❌ YAGNI 违反:当前只需要支持 MySQL
public interface DatabaseDriver {
void connect(String url);
void disconnect();
ResultSet query(String sql);
}
public class MySQLDriver implements DatabaseDriver { /* ... */ }
public class PostgreSQLDriver implements DatabaseDriver { /* ... */ } // 不需要
public class MongoDBDriver implements DatabaseDriver { /* ... */ } // 不需要
public class OracleDriver implements DatabaseDriver { /* ... */ } // 不需要
public class DatabaseDriverFactory {
public static DatabaseDriver create(String type) { /* ... */ }
}
// ✅ YAGNI:只实现需要的
public class MySQLDatabase {
public void connect(String url) { /* ... */ }
public ResultSet query(String sql) { /* ... */ }
}
// 当真正需要支持 PostgreSQL 时再抽象接口
# ❌ 过度设计:配置系统支持多种格式
class ConfigLoader:
def load(self, path: str) -> dict:
if path.endswith('.json'):
return self._load_json(path)
elif path.endswith('.yaml'):
return self._load_yaml(path)
elif path.endswith('.toml'):
return self._load_toml(path)
elif path.endswith('.xml'):
return self._load_xml(path)
elif path.endswith('.ini'):
return self._load_ini(path)
# 实际项目只用了 JSON...
# ✅ YAGNI
import json
def load_config(path: str) -> dict:
with open(path) as f:
return json.load(f)
// ❌ 过度设计:为了"灵活性"的过度抽象
interface EventBus {
subscribe(event: string, handler: EventHandler): void;
publish(event: string, data: any): void;
unsubscribe(event: string, handler: EventHandler): void;
}
interface EventHandler {
handle(data: any): void;
priority(): number;
filter(data: any): boolean;
}
interface EventMiddleware {
before(event: string, data: any): any;
after(event: string, result: any): void;
}
// 实际只需要:用户注册后发邮件
// ✅ YAGNI
class UserService {
constructor(private : ) {}
() {
user = .(data);
..(user.);
user;
}
}
YAGNI ≠ 不做设计。以下情况需要提前考虑:
✅ 需要提前设计的:
- 数据库 schema(后期迁移代价大)
- 公开 API 接口(发布后难以修改)
- 安全机制(事后补救代价大)
- 核心架构决策(推倒重来代价大)
❌ 不需要提前实现的:
- "可能需要"的功能
- "将来可能"的数据库切换
- "也许会用到"的导出格式
- "以防万一"的配置选项
问自己:
1. 有明确的需求文档/用户故事要求这个功能吗?
→ 没有 = YAGNI
2. 如果不做这个,当前迭代的功能完整吗?
→ 完整 = YAGNI
3. 这个"提前设计"的成本是多少?不做的话将来补上的成本是多少?
→ 提前成本 > 将来成本 × 发生概率 = YAGNI
4. 团队成员都理解为什么需要这个吗?
→ 只有你觉得需要 = 很可能 YAGNI
Sprint 1: 用户只能用邮箱密码登录
Sprint 2: 需求确认后,添加 OAuth 登录
Sprint 3: 需求确认后,添加 SSO 登录
而不是:
Sprint 1: 设计支持 N 种登录方式的通用认证框架
(过度设计,3 种中可能只用到 1 种)
"最后责任时刻"= 再不决定就会失去重要选项的时刻
示例:
- 数据库选型:在了解实际数据模式后决定
- 缓存策略:在性能测试暴露瓶颈后添加
- 微服务拆分:在单体遇到实际扩展问题后拆分
| 类型 | 示例 | 态度 |
|---|---|---|
| 必要复杂性 | 业务本身复杂 | 接受 |
| 偶然复杂性 | 技术选型引入 | 最小化 |
| 推测复杂性 | "将来可能需要" | 消除 |
| 原则 | 关系 |
|---|---|
| KISS | KISS 关注怎么做简单,YAGNI 关注做不做 |
| OCP | OCP 提倡可扩展设计,YAGNI 提醒不要过度扩展 |
| DRY | 不要为了 DRY 而提前创建"将来可能用到"的抽象 |
YAGNI 核心:不要实现当前不需要的功能。
实践要点: