deprecation-and-migration
addyosmani/agent-skills
古いシステム、API、または機能の廃止プロセスや、ユーザーを代替システムへ移行するプロセスを指針として示すもので、意思決定の枠組み、移行パターン、および廃止戦略などが含まれる。
...すべて拡張します非推奨と移行
概要
コードは資産ではなく、負債です。コードの1行ごとに、バグの修正、依存関係の更新、セキュリティパッチの適用、そして新しいエンジニアの育成といった、継続的なメンテナンスコストが発生します。非推奨化とは、もはやその価値に見合う成果をもたらさないコードを削除する手法であり、移行とは、ユーザーを安全に旧システムから新システムへ移行させるプロセスです。
多くのエンジニアリング組織は、ものを構築することには長けています。しかし、それを撤去することに長けている組織はほとんどありません。このスキルは、そのギャップを埋めるものです。
使用すべき場面
- 古いシステム、API、またはライブラリを新しいものに置き換える場合
- 不要になった機能を段階的に廃止する場合
- 重複する実装を統合する場合
- 所有者はいないが、誰もが依存しているデッドコードの削除
- 新しいシステムのライフサイクルを計画する場合(非推奨化の計画は設計段階から始まる)
- レガシーシステムを維持するか、移行に投資するかを決定する
基本原則
コードは負債である
コードの1行1行には継続的なコストが伴います。テスト、ドキュメント、セキュリティパッチ、依存関係の更新、そしてそのコードの近くで作業するすべての人の精神的負担が必要です。コードの価値は、コードそのものではなく、それが提供する機能にあります。同じ機能を、より少ないコード、より低い複雑さ、あるいはより優れた抽象化によって提供できる場合、古いコードは削除すべきです。
ハイラムの法則が削除を困難にする
十分な数のユーザーが存在すると、バグ、タイミングの癖、文書化されていない副作用を含め、あらゆる観察可能な挙動に依存が生じます。これが、非推奨化には単なる告知だけでなく、積極的な移行が必要とされる理由です。ユーザーが、代替システムでは再現されない挙動に依存している場合、単に「切り替える」ことはできません。
非推奨化の計画は設計段階から始まる
新しいものを構築する際は、「3年後にこれをどのように削除するか?」と自問してください。クリーンなインターフェース、機能フラグ、最小限の表面積を備えて設計されたシステムは、実装の詳細が至る所に漏れ出ているシステムよりも、非推奨化が容易です。
非推奨化の決定
何かを非推奨にする前に、以下の質問に答えてください:
1. このシステムは依然として独自の価値を提供しているか?
→ 「はい」の場合は維持し、「いいえ」の場合は廃止を進める。
2. これに依存しているユーザー/利用者は何人いるか?
→ 移行の範囲を定量化する。
3. 代替手段は存在するか?
→ 存在しない場合は、まず代替手段を構築する。代替手段がないまま非推奨にしてはならない。
4. 利用者1人あたりの移行コストはいくらか?
→ 簡単に自動化できる場合は実施する。手作業で多大な労力を要する場合は、維持コストと天秤にかける。
5. 非推奨にしない場合の継続的な維持コストはどれくらいか?
→ セキュリティリスク、エンジニアの工数、複雑さによる機会コスト。
強制的な非推奨と勧告的な非推奨
| 種類 | 使用すべき場合 | 仕組み |
|---|---|---|
| 推奨 | 移行は任意で、旧システムは安定している | 警告、ドキュメント、促し。ユーザーは各自のスケジュールに合わせて移行する。 |
| 必須 | 旧システムにセキュリティ上の問題がある、業務の進展を妨げている、または保守コストが維持不可能な場合 | 厳格な期限。X日までに旧システムは廃止されます。移行ツールを提供してください。 |
原則として「推奨」とする。維持コストやリスクの観点から移行を強制することが正当化される場合にのみ「強制」を採用する。「強制」による廃止には、移行ツール、ドキュメント、およびサポートの提供が必須である。単に期限を告知するだけでは不十分である。
移行プロセス
ステップ1:代替システムの構築
動作する代替システムがない状態で廃止してはならない。代替システムは以下を満たす必要がある:
- 旧システムのすべての重要なユースケースを網羅していること
- ドキュメントと移行ガイドを備えていること
- 本番環境で実証済みであること(単に「理論上優れている」だけでは不十分)
ステップ 2: 告知と文書化
## 非推奨のお知らせ:OldService
**ステータス:** 2025年3月1日をもって非推奨
**代替サービス:** NewService(以下の移行ガイドを参照)
**廃止予定日:** 勧告 — 現時点では厳格な期限は設定されていません
**理由:** OldServiceは手動でのスケーリングが必要であり、可観測性に欠けています。
NewServiceはこれら両方を自動的に処理します。
### 移行ガイド
1. `import { client } from 'old-service'` を `import { client } from 'new-service'` に置き換える
2. 設定を更新する(以下の例を参照)
3. 移行検証スクリプトを実行する:`npx migrate-check`
ステップ3:段階的に移行する
コンシューマーは一度にすべてではなく、1つずつ移行してください。各コンシューマーについて:
1. 非推奨システムとのすべての接点を特定する
2. 代替システムを使用するように更新する
3. 動作が一致することを検証する(テスト、統合チェック)
4. 旧システムへの参照を削除する
5. 回帰がないことを確認する
「チャーン・ルール」:廃止対象となるインフラストラクチャを管理している場合は、ユーザーの移行を行うか、移行を必要としない下位互換性のある更新を提供する責任があります。廃止を発表して、ユーザーに自分で解決させるようなことはしないでください。
ステップ4:旧システムの削除
すべての利用者が移行を完了してから:
1. アクティブな利用がゼロであることを確認する(メトリクス、ログ、依存関係分析)
2. コードを削除する
3. 関連するテスト、ドキュメント、設定を削除する
4. 非推奨の通知を削除する
5. 祝う — コードの削除は成果である
移行パターン
ストラングラー・パターン
旧システムと新システムを並行して稼働させる。トラフィックを段階的に旧システムから新システムへ切り替える。旧システムが処理するトラフィックが0%になったら、旧システムを削除する。
フェーズ1:新システムが0%、旧システムが100%を処理
フェーズ2:新システムが10%を処理(カナリア)
フェーズ3:新システムが50%を処理
フェーズ4:新システムが100%を処理、旧システムはアイドル状態
フェーズ5:旧システムを削除
アダプターパターン
古いインターフェースからの呼び出しを新しい実装に変換するアダプタを作成します。バックエンドの移行中は、利用者は引き続き古いインターフェースを使い続けます。
// アダプター:旧インターフェース、新実装
class LegacyTaskService implements OldTaskAPI {
constructor(private newService: NewTaskService) {}
// 旧メソッドのシグネチャ。新しい実装に委譲する
getTask(id: number): OldTask {
const task = this.newService.findById(String(id));
return this.toOldFormat(task);
}
}
機能フラグによる移行
フィーチャーフラグを使用して、コンシューマーを1つずつ古いシステムから新しいシステムに切り替えます:
function getTaskService(userId: string): TaskService {
if (featureFlags.isEnabled('new-task-service', { userId })) {
return new NewTaskService();
}
return new LegacyTaskService();
}
ゾンビコード
ゾンビコードとは、誰も所有していないが、誰もが依存しているコードのことです。積極的にメンテナンスされておらず、明確な所有者もおらず、セキュリティ上の脆弱性や互換性の問題が蓄積されています。兆候:
- 6ヶ月以上コミットがないにもかかわらず、アクティブな利用者が存在する
- 割り当てられたメンテナーやチームが存在しない
- 修正されないテストの失敗
- 既知の脆弱性がある依存関係があり、誰も更新していない
- もはや存在しないシステムを参照しているドキュメント
対応策:責任者を割り当てて適切にメンテナンスするか、具体的な移行計画を立てて非推奨とするか、のいずれかを行うこと。ゾンビコードを宙ぶらりんのままにしておくことはできない。投資を行うか、削除するか、のいずれかである。
よくある言い訳
| 言い訳 | 現実 |
|---|---|
| 「まだ動いているのに、なぜ削除する必要があるのか?」 | 誰もメンテナンスしていない動作中のコードは、セキュリティ債務と複雑さを蓄積する。メンテナンスコストは知らぬ間に膨れ上がる。 |
| 「後で誰かが必要とするかもしれない」 | 後で必要になれば、再構築すればよい。「万が一に備えて」使われていないコードを残しておくことは、再構築するよりもコストがかかる。 |
| 「移行にかかるコストが高すぎる」 | 移行コストを、今後2~3年間にわたる継続的なメンテナンスコストと比較してみてください。長期的に見れば、移行の方が通常は安上がりです。 |
| 「新しいシステムが完成したら、これを非推奨にする」 | 非推奨化の計画は設計段階から始まります。新システムが完成する頃には、新たな優先事項が生まれているでしょう。今から計画を立ててください。 |
| 「ユーザーは自発的に移行してくれるだろう」 | そうはなりません。ツールやドキュメント、インセンティブを提供するか、あるいは自力で移行を行ってください(チャーン・ルール)。 |
| 「両方のシステムを無期限に維持できる」 | 同じ機能を持つシステムが2つあるということは、保守、テスト、ドキュメント作成、および導入にかかるコストが2倍になるということです。 |
危険信号
- 代替手段がない廃止予定のシステム
- 移行ツールやドキュメントがないままの非推奨化の発表
- 何年も前から「推奨中止」とされているものの、進展が見られない「ソフト」な廃止
- 所有者もいないが、実際に利用されている「ゾンビコード」
- 非推奨システムに新機能が追加されている(代わりに代替システムへの投資を行うべき)
- 現在の実利用状況を測定せずに非推奨化
- アクティブな利用者がゼロであることを確認せずにコードを削除すること
検証
非推奨化完了後:
- 代替システムは本番環境での実績があり、すべての重要なユースケースを網羅している
- 具体的な手順や例を記載した移行ガイドが存在する
- すべてのアクティブな利用者が移行済みであること(メトリクスやログにより確認済み)
- 古いコード、テスト、ドキュメント、および設定が完全に削除されている
- コードベース内に非推奨システムへの参照が残っていない
- 非推奨通知は削除されました(その役割は果たしました)
---
name: deprecation-and-migration
description: Guides the process of deprecating old systems, APIs, or features and migrating users to replacements, including decision frameworks, migration patterns, and removal strategies.
---
# Deprecation and Migration
## Overview
Code is a liability, not an asset. Every line of code has ongoing maintenance cost — bugs to fix, dependencies to update, security patches to apply, and new engineers to onboard. Deprecation is the discipline of removing code that no longer earns its keep, and migration is the process of moving users safely from the old to the new.
Most engineering organizations are good at building things. Few are good at removing them. This skill addresses that gap.
## When to Use
- Replacing an old system, API, or library with a new one
- Sunsetting a feature that's no longer needed
- Consolidating duplicate implementations
- Removing dead code that nobody owns but everybody depends on
- Planning the lifecycle of a new system (deprecation planning starts at design time)
- Deciding whether to maintain a legacy system or invest in migration
## Core Principles
### Code Is a Liability
Every line of code has ongoing cost: it needs tests, documentation, security patches, dependency updates, and mental overhead for anyone working nearby. The value of code is the functionality it provides, not the code itself. When the same functionality can be provided with less code, less complexity, or better abstractions — the old code should go.
### Hyrum's Law Makes Removal Hard
With enough users, every observable behavior becomes depended on — including bugs, timing quirks, and undocumented side effects. This is why deprecation requires active migration, not just announcement. Users can't "just switch" when they depend on behaviors the replacement doesn't replicate.
### Deprecation Planning Starts at Design Time
When building something new, ask: "How would we remove this in 3 years?" Systems designed with clean interfaces, feature flags, and minimal surface area are easier to deprecate than systems that leak implementation details everywhere.
## The Deprecation Decision
Before deprecating anything, answer these questions:
```
1. Does this system still provide unique value?
→ If yes, maintain it. If no, proceed.
2. How many users/consumers depend on it?
→ Quantify the migration scope.
3. Does a replacement exist?
→ If no, build the replacement first. Don't deprecate without an alternative.
4. What's the migration cost for each consumer?
→ If trivially automated, do it. If manual and high-effort, weigh against maintenance cost.
5. What's the ongoing maintenance cost of NOT deprecating?
→ Security risk, engineer time, opportunity cost of complexity.
```
## Compulsory vs Advisory Deprecation
| Type | When to Use | Mechanism |
|------|-------------|-----------|
| **Advisory** | Migration is optional, old system is stable | Warnings, documentation, nudges. Users migrate on their own timeline. |
| **Compulsory** | Old system has security issues, blocks progress, or maintenance cost is unsustainable | Hard deadline. Old system will be removed by date X. Provide migration tooling. |
**Default to advisory.** Use compulsory only when the maintenance cost or risk justifies forcing migration. Compulsory deprecation requires providing migration tooling, documentation, and support — you can't just announce a deadline.
## The Migration Process
### Step 1: Build the Replacement
Don't deprecate without a working alternative. The replacement must:
- Cover all critical use cases of the old system
- Have documentation and migration guides
- Be proven in production (not just "theoretically better")
### Step 2: Announce and Document
```markdown
## Deprecation Notice: OldService
**Status:** Deprecated as of 2025-03-01
**Replacement:** NewService (see migration guide below)
**Removal date:** Advisory — no hard deadline yet
**Reason:** OldService requires manual scaling and lacks observability.
NewService handles both automatically.
### Migration Guide
1. Replace `import { client } from 'old-service'` with `import { client } from 'new-service'`
2. Update configuration (see examples below)
3. Run the migration verification script: `npx migrate-check`
```
### Step 3: Migrate Incrementally
Migrate consumers one at a time, not all at once. For each consumer:
```
1. Identify all touchpoints with the deprecated system
2. Update to use the replacement
3. Verify behavior matches (tests, integration checks)
4. Remove references to the old system
5. Confirm no regressions
```
**The Churn Rule:** If you own the infrastructure being deprecated, you are responsible for migrating your users — or providing backward-compatible updates that require no migration. Don't announce deprecation and leave users to figure it out.
### Step 4: Remove the Old System
Only after all consumers have migrated:
```
1. Verify zero active usage (metrics, logs, dependency analysis)
2. Remove the code
3. Remove associated tests, documentation, and configuration
4. Remove the deprecation notices
5. Celebrate — removing code is an achievement
```
## Migration Patterns
### Strangler Pattern
Run old and new systems in parallel. Route traffic incrementally from old to new. When the old system handles 0% of traffic, remove it.
```
Phase 1: New system handles 0%, old handles 100%
Phase 2: New system handles 10% (canary)
Phase 3: New system handles 50%
Phase 4: New system handles 100%, old system idle
Phase 5: Remove old system
```
### Adapter Pattern
Create an adapter that translates calls from the old interface to the new implementation. Consumers keep using the old interface while you migrate the backend.
```typescript
// Adapter: old interface, new implementation
class LegacyTaskService implements OldTaskAPI {
constructor(private newService: NewTaskService) {}
// Old method signature, delegates to new implementation
getTask(id: number): OldTask {
const task = this.newService.findById(String(id));
return this.toOldFormat(task);
}
}
```
### Feature Flag Migration
Use feature flags to switch consumers from old to new system one at a time:
```typescript
function getTaskService(userId: string): TaskService {
if (featureFlags.isEnabled('new-task-service', { userId })) {
return new NewTaskService();
}
return new LegacyTaskService();
}
```
## Zombie Code
Zombie code is code that nobody owns but everybody depends on. It's not actively maintained, has no clear owner, and accumulates security vulnerabilities and compatibility issues. Signs:
- No commits in 6+ months but active consumers exist
- No assigned maintainer or team
- Failing tests that nobody fixes
- Dependencies with known vulnerabilities that nobody updates
- Documentation that references systems that no longer exist
**Response:** Either assign an owner and maintain it properly, or deprecate it with a concrete migration plan. Zombie code cannot stay in limbo — it either gets investment or removal.
## Common Rationalizations
| Rationalization | Reality |
|---|---|
| "It still works, why remove it?" | Working code that nobody maintains accumulates security debt and complexity. Maintenance cost grows silently. |
| "Someone might need it later" | If it's needed later, it can be rebuilt. Keeping unused code "just in case" costs more than rebuilding. |
| "The migration is too expensive" | Compare migration cost to ongoing maintenance cost over 2-3 years. Migration is usually cheaper long-term. |
| "We'll deprecate it after we finish the new system" | Deprecation planning starts at design time. By the time the new system is done, you'll have new priorities. Plan now. |
| "Users will migrate on their own" | They won't. Provide tooling, documentation, and incentives — or do the migration yourself (the Churn Rule). |
| "We can maintain both systems indefinitely" | Two systems doing the same thing is double the maintenance, testing, documentation, and onboarding cost. |
## Red Flags
- Deprecated systems with no replacement available
- Deprecation announcements with no migration tooling or documentation
- "Soft" deprecation that's been advisory for years with no progress
- Zombie code with no owner and active consumers
- New features added to a deprecated system (invest in the replacement instead)
- Deprecation without measuring current usage
- Removing code without verifying zero active consumers
## Verification
After completing a deprecation:
- [ ] Replacement is production-proven and covers all critical use cases
- [ ] Migration guide exists with concrete steps and examples
- [ ] All active consumers have been migrated (verified by metrics/logs)
- [ ] Old code, tests, documentation, and configuration are fully removed
- [ ] No references to the deprecated system remain in the codebase
- [ ] Deprecation notices are removed (they served their purpose)
すべてのファイル
0件のファイルdeprecation-and-migrationをインストール
スキルファイルをダウンロードし、.claude/skills/ ディレクトリに解凍してください。
ZIPをダウンロードリポジトリをクローンし、スキルファイルをプロジェクトにコピーしてください。
git clone https://github.com/addyosmani/agent-skills/tree/main/skills/deprecation-and-migration # Copy SKILL.md to your .claude/skills/ directory
コピー





家
