# Deprecation And Migration

> Use when removing an old API, feature, or distribution channel, when renaming a public function with downstream users, when deciding whether dead or shim code can be deleted, or when migrating users from one implementation to another.

- Skill: `just-silver/deprecation-and-migration` (Agent Skill)
- Install (CLI): `npx skillmds@latest add just-silver/deprecation-and-migration`
- Raw SKILL.md: https://api.skillmd.com/api/skills/just-silver/deprecation-and-migration/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: Just-Silver (https://skillmd.com/u/just-silver)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/just-silver/deprecation-and-migration

---


# Deprecation and Migration（废弃与迁移）

## Overview

代码是负债不是资产。每行代码都有持有成本：修 bug、跟依赖、打补丁、新人理解。废弃是主动清偿负债的纪律，迁移是把用户安全送到新实现的过程。组织擅长建造，不擅长拆除——本技能补这一块。

## When to Use

- 删除旧 API、旧功能、旧分发渠道前
- 公开函数改名/改签名且有下游用户时
- 判断僵尸代码、注释代码、兼容 shim 能否删时
- 做选型替换（旧实现 → 新实现）需迁移用户时
- 新系统设计时（废弃计划从设计时开始：3 年后怎么拆掉它）

**When NOT to use:**

- 内部未公开、无下游的函数重构（直接改，跑测试即可）
- 一次性脚本、实验分支（删了就是，无需流程）
- 废弃流程已在走，只是执行迁移步骤

## 决策五问（删之前先回答）

```
1. 还有独特价值吗？有 → 留着维护；无 → 继续
2. 多少用户/调用方依赖？量化迁移范围（全局搜调用点）
3. 替代品存在吗？无 → 先造替代品，不许裸废弃
4. 每个调用方迁移成本多高？可自动化 → 直接迁；手工高成本 → 权衡持有成本
5. 不删的持有成本是什么？安全风险、人力、复杂度机会成本
```

## Advisory vs Compulsory（两级废弃）

| 类型 | 何时用 | 机制 |
|------|--------|------|
| Advisory（建议） | 迁移可选，旧系统稳定 | 警告 + 文档 + 引导，用户按自己节奏迁，无硬 deadline |
| Compulsory（强制） | 有安全问题、阻塞进展、持有成本不可持续 | 硬 deadline（某版本移除），必须配迁移工具 + 文档 + 支持 |

**默认 Advisory。** Compulsory 必须同时给出：替代品可用、迁移指南、到期版本，三缺一即不许强制。

## 迁移四步

```
替代品就绪 → 公告 + 文档 → 逐个迁移 → 确认零使用后删除
```

1. **替代品先行**：覆盖旧系统关键用例、有文档、有迁移指南、已在生产验证（不是"理论上更好"）。
2. **公告**：CHANGELOG 开 Deprecated 小节 + 迁移指南（旧→新对照、验证命令）；旧入口保留但打印废弃警告（含新用法 + 移除版本）。
3. **逐个迁移**：一次迁一个调用方，每迁完验证行为一致（测试 + 集成检查），不批量闪迁。
4. **删除**：确认零活跃使用（搜索零引用、日志零触发、测试零覆盖）后删代码 + 删测试 + 删文档 + 删公告。删代码是成就，不是损失。

**Churn Rule：** 谁拥有被废弃的基础设施，谁负责迁用户——或提供无需迁移的向后兼容。不许只发公告让用户自己想办法。

## 删除标准（四条同时满足才删）

- **无引用**：全局搜索零调用（含反射、动态导入、配置/路由字符串），测试零覆盖
- **无契约**：不是公开 API / 插件点 / 外部依赖接口。对外暴露的即使内部无人调也不算僵尸
- **有替代**：调用方已有替代品可用，或已过废弃 deadline 且公告充分
- **可回滚**：git 历史可找回，删除 commit 写清原因，删完全量测试 + 构建通过，一次只删一批不混功能改动

**特殊项：**

- 注释掉的代码块 → 见光就删，git 历史就是它的坟墓
- 兼容 shim → 按版本契约删：有明确下线条件（最低支持版本/调用方全迁）才删；否则留但必须加 `TODO + 下线版本 + 原因`，无下线计划的兼容代码即永久僵尸
- 拿不准的 → 先标 `deprecated` + 运行时警告跑一个版本，看触发再删，不永久保留

## 破坏性变更规则

- 默认不 break 下游：旧名保留做别名转发到新实现，逻辑只留一份
- 旧入口加 `@deprecated` + 运行时警告一次（新名字 + 移除版本）
- 测试同时覆盖新旧两个入口
- 本次 minor 只废弃不删除，下一个 major 才删旧别名

## Quick Reference

| 场景 | 动作 |
|------|------|
| 删旧功能 | 五问 → Advisory/Compulsory 定级 → 替代品 → 公告 → 逐迁 → 零使用后删 |
| 公开改名 | 别名转发 + deprecated 警告 + 双入口测试，major 才删旧名 |
| 注释代码 | 直接删 |
| 无引用内部代码 | 四标准验证后删，一批一次 |
| 兼容 shim | 按版本契约，无下线计划即僵尸，加 TODO 限期 |
| 拿不准 | 标 deprecated 跑一个版本观察，不永久保留 |

## Common Rationalizations

| Excuse | Reality |
|--------|---------|
| "没人用了，直接删" | Hyrum's Law：用户够多时连 bug 都有人依赖；先量化调用方，无替代品不许裸删 |
| "先删了，有问题再加回来" | 删除易恢复难（下游已改）；流程是公告→迁移→零使用→删，删是最后一步不是第一步 |
| "留着又不占地方" | 每行都是负债：测试、补丁、理解成本；留必须有下线计划，否则即僵尸 |
| "兼容 shim 才几行" | 几行的 shim 乘以 30 年就是永久税；无 TODO + 下线版本即违规 |
| "breaking 一次改完省事" | 省的是你，成本全转嫁下游；别名 + 迁移期是拥有者的责任（Churn Rule） |
| "注释代码万一有用" | git 即坟墓；注释代码无测试无维护，留着只污染阅读 |

## Red Flags — STOP

- 无替代品即宣布废弃
- Compulsory 无 deadline、无迁移工具、无文档三缺一
- 公开改名直接改无别名、无迁移期
- 注释代码/零引用代码以"万一有用"为由保留
- 兼容 shim 无 TODO + 下线版本
- 批量闪迁多调用方（一次迁多个，出事无法定位）
- 删代码与功能改动混同一提交

**以上任一出现 → 停手，回迁移四步/删除标准修正后再删。**

## Verification

- [ ] 决策五问已回答，迁移范围已量化
- [ ] Advisory/Compulsory 已定级；Compulsory 有 deadline + 工具 + 文档
- [ ] 替代品覆盖关键用例且已验证
- [ ] 公告已发（CHANGELOG Deprecated 小节 + 迁移指南），旧入口有废弃警告
- [ ] 删除前确认零使用（搜索/日志/覆盖三证据）
- [ ] 删除 commit 独立、可回滚，全量测试 + 构建通过

