--- name: backward-compat-governance description: >- 後方互換性がゴミコードを量産する構造を検出し、互換性を「契約と撤去計画」として管理する ガバナンスを支援するスキル。公開API境界の明確化、非推奨化サイクル(deprecation cycle)の 制度化、互換層の局所化(Adapter/Strangler Fig)、契約テスト(CDC)による互換性検証、 AI生成コードの互換性ゲート設計を含む。コードレビュー、API設計、リファクタリング、 レガシー移行時に互換性起因の技術的負債を防ぐために使用。 対象言語: 言語非依存(Java, TypeScript, Go, Python, Rust等すべて)。 トリガー:「後方互換性を保ちたい」「非推奨APIをどうする」「互換層が増えてきた」 「レガシー移行の戦略」「API設計レビュー」「互換性のためのコードが多い」 「deprecation policyを作りたい」「破壊的変更の管理」といった互換性管理関連リクエストで起動。 --- # 後方互換性ガバナンス 互換性を「残すコード」ではなく「契約と撤去計画」として管理する。 ## 核心原則 **後方互換性それ自体が悪ではない。互換性を支える「仕様・テスト・撤去計画・計測」が欠けたとき、互換要求が実装へ流れ込みゴミコード化する。** | 状態 | 互換性の扱い | 結果 | |------|-------------|------| | 管理あり | 契約(仕様)+ テスト + 撤去SLO + 計測 | 安定性の基盤(資産) | | 管理なし | 実装でのその場しのぎ | 互換層の肥大化(負債) | ## 負債化のフィードバックループ ``` 既存クライアント → 「壊すな」の要求 → 公開APIの固定・増殖 → 非推奨APIの温存 + 互換アダプタ/分岐追加 → 複雑性増大・テスト範囲拡大 → 保守コスト増・変更速度低下 → 期限圧力で近道実装 → さらにAPI固定... (ループ) ``` ## 判断フロー ``` 互換性に関わる変更を検出 ↓ 公開API境界は明確か? ├─ NO → 境界を仕様化してから進む └─ YES ↓ 非推奨化ポリシーはあるか? ├─ NO → ポリシーを策定(撤去SLO含む) └─ YES ↓ 互換処理はどこにあるか? ├─ コードベース全体に散在 → 互換層を局所化(Adapter/Strangler Fig) └─ 局所化済み ↓ 撤去計画はあるか? ├─ NO → 撤去タイムライン + 計測を設定 └─ YES → 計画に従って進行 ``` ## アンチパターン検出 以下のパターンを見つけたら互換性負債の兆候: ``` ❌ if (version < X) { /* 旧挙動 */ } else { /* 新挙動 */ } // バージョン分岐の散在 ❌ @Deprecated が付いたまま何年も残るAPI ❌ LegacyXxxAdapter, OldXxxWrapper が増殖 ❌ "互換性のため" というコメントが散在 ❌ 同じ機能の新旧2つのエンドポイントが併存 ❌ テストに "backward compat" 系のスキップ/無視がある ❌ 破壊的変更がドキュメント化されていない ``` ## 対策パターン ### 1. 公開API境界の明確化 互換対象を限定し、不要な互換コードを防ぐ。 ``` ✅ 公開APIを仕様として宣言する(SemVer, OpenAPI等) ✅ 内部APIと公開APIを構造的に分離する ✅ 「何を壊さないか」のスコープを文書化する ❌ すべてのAPIを暗黙的に互換対象にする ❌ 内部実装の変更が外部に漏れる構造 ``` **境界の隔離例**(Linux kernelの戦略): - ユーザ空間ABI: 極力壊さない(安定境界) - カーネル内部API: 自由に変更可能(進化可能) ### 2. 非推奨化サイクル(Deprecation Cycle) 撤去を制度化し、コード墓場を減らす。 ``` 非推奨宣言 → 移行期間(猶予SLO) → 利用率計測 → 削除 ``` | フェーズ | アクション | 成果物 | |---------|-----------|--------| | 宣言 | 非推奨マーク + 代替案の提示 | 非推奨注釈、移行ガイド | | 猶予 | 移行支援 + 利用率追跡 | テレメトリ、移行状況ダッシュボード | | 削除 | 利用ゼロ確認後に除去 | 削除PR、リリースノート | **猶予期間の目安**(プロジェクト規模に応じて調整): - 内部API: 1-2リリースサイクル - 公開ライブラリ: 最低1メジャーバージョン - プラットフォームAPI: 2年以上(大規模エコシステム) ### 3. 互換層の局所化 互換処理を「コードベース全体に散らさない」ことが主戦場。 **Adapterパターン**: 非互換なI/F同士の差分を一点に集約 ```typescript // ❌ 散在: あちこちでバージョン分岐 function processOrder(order: Order) { if (order.apiVersion < 2) { // v1の処理... } else { // v2の処理... } } // ✅ 局所化: アダプタで吸収 interface OrderProcessor { process(order: Order): Result } class OrderV1Adapter implements OrderProcessor { constructor(private inner: OrderProcessorV2) {} process(order: OrderV1): Result { const converted = convertV1toV2(order) return this.inner.process(converted) } } ``` **Strangler Figパターン**: レガシーを段階的に置換 ``` 旧システム ←→ [ルーティング層] ←→ 新システム ↑ 段階的に新へ転送を増やし、最終的に旧を除去 ``` ### 4. 契約テスト(Consumer-Driven Contract) 利用者の「使い方」に基づいて互換性を検証する。 ``` ✅ 消費者が使う部分だけを契約として固定 ✅ 使われない挙動は自由に変更可能 ✅ CIで互換性の回帰を自動検出 ❌ "全部テストする" で範囲が爆発 ❌ 互換テストがないまま「互換性を守る」と宣言 ``` ### 5. AI生成コードの互換性ゲート AI出力を「未信頼入力」として扱い、互換性・依存性・安全性をゲートで縛る。 ``` 互換ポリシー/公開API定義 → 参照ドキュメント/RAG → AI生成 → 静的解析/セキュリティ検査 + 互換テスト/契約テスト → PR作成 → 人間レビュー(互換・依存・撤去計画) → マージ → 互換メトリクス/非推奨利用率の監視 ``` **AI特有のリスク**: - 非推奨APIの「それらしい」再生産 - 存在しない依存パッケージ名の生成(package hallucination) - 互換層の無秩序な増殖(レビュー漏れ) ## 適用指針 ### 推奨 - `@Deprecated` / `#[deprecated]` が付いたまま長期間残るAPI - バージョン分岐がコードベース全体に散在 - 「互換性のため」コメントが増殖 - 破壊的変更のドキュメント化が不十分 - レガシーシステムからの段階移行 ### 過剰適用を避ける - 内部のみで使われるプライベートAPI - プロトタイプ段階で互換性が不要な場合 - 互換対象のクライアントが存在しない新規API ## レビューチェックリスト ### API境界 - [ ] 公開APIの境界が仕様として明確に定義されているか - [ ] 内部APIと公開APIが構造的に分離されているか - [ ] 互換性のスコープ(何を壊さないか)が文書化されているか ### 非推奨化管理 - [ ] 非推奨APIに代替案が明示されているか - [ ] 撤去タイムライン(猶予SLO)が設定されているか - [ ] 利用率の計測手段があるか(テレメトリ等) - [ ] 非推奨APIの削除がリリース計画に含まれているか ### 互換層の設計 - [ ] 互換処理が局所化されているか(Adapter等に集約) - [ ] バージョン分岐がコード全体に散在していないか - [ ] Strangler Fig等の段階移行戦略が検討されているか - [ ] Feature Flagを使う場合、撤去計画が設定されているか ### テスト - [ ] 互換性の対象ごとに回帰テストがあるか - [ ] 契約テスト(CDC)が導入されているか(外部API/マイクロサービス) - [ ] 破壊的変更を検出する静的解析がCIに組み込まれているか ### AI関与時の追加確認 - [ ] AI生成コードが非推奨APIを使用していないか - [ ] 依存パッケージが実在するか検証されているか - [ ] 互換性テストがAI生成コードにも適用されているか ## 関連スキル(併読推奨) このスキルを使用する際は、以下のスキルも併せて参照すること: - `clean-architecture`: 互換層を配置するアダプタ層の設計 - `repository-design`: 公開API境界としてのリポジトリの互換性管理 - `intent-based-dedup`: 旧API・新APIの意図的な重複を共通化しない判断