arch-strangler-fig について
ファサード経由で新旧の実装へ処理を振り分け、機能単位で移行して旧コードを削除する手法を解説するスキルです。停止して一括書き換えできない重要システムを対象に、独立してリリースできる移行手順と完了計画を重視します。
主な機能
- 01ファサードで処理を受けて振り分け
- 02機能単位で段階的に置き換え
- 03トラフィックを移行し新旧の結果を比較
- 04腐敗防止層でモデルの違いを分離
- 05移行中の新旧データを管理
- 06完了後にレガシー経路を削除
活用シーン
- 01モノリスを段階的にマイクロサービスへ移行
- 02停止できないレガシーシステムを置き換え
- 03内部構造が不明なシステムを少しずつ把握
- 04一括書き換えを避けながら継続的にリリース
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ yonatankarp/ software-design-skills --skill arch-strangler-figインストール後、Claude Code で/arch-strangler-figを入力して読み込まれたか確認します。
詳細
1 行でまとめると
レガシーシステムをファサードで包みます。新機能と段階的に書き換えた既存機能を、そのファサードの背後にある新しいサービスへルーティングします。すべての機能を移行し終えると、レガシーシステムは「絞め殺され」、廃止できます。
このスキルを使う場合
- モノリスを数か月から数年かけてマイクロサービスへ移行する場合。
- 書き換えのために停止するには重要すぎるレガシーシステムを置き換える場合。
- 内部の仕組みがよくわかっていないシステムを分解する場合。一度に 1 つの振る舞いを移行しながら、理解を深めていきます。
- 誰かが「ビッグバン」方式の書き換えを提案した場合はいつでも。より安全な代替策です。
このスキルを使わない場合
- レガシーシステムが小さく、直接書き換えるほうが実際に短期間で、リスクも低い場合。
- 機能があまりに複雑に絡み合っていて、明確なファサードを設けられない場合。まず、境界を明らかにするリファクタリングに取り組みます。
- 無期限の移行を隠すために絞め殺しが使われており、誰も完了させるつもりがない場合。レガシーシステムがなくなることはありません。
主な内容
進め方:
- 境界を選びます。 明確な境界(HTTP エンドポイント、メッセージハンドラー、スケジュール済みジョブ)で仲介できる機能を特定します。
- ファサードを構築します。 プロキシ/ゲートウェイ/ディスパッチャーで、その機能に関するトラフィックをルーティングします。最初はすべてのトラフィックをレガシーシステムに送ります。
- 置き換え先を構築します。 新しいサービスで、その機能の外部契約を同じように実装します。
- 一部のトラフィックを切り替えます。 1%/10%/100% を新しいサービスにルーティングします。出力を比較します(シャドートラフィック、並行実行)。
- 廃止します。 その機能に関するすべてのトラフィックが新しいサービスに移行したら、レガシー側のコードパスを削除します。
- 繰り返します。 次の機能に進みます。
アンチコラプションレイヤー(ACL)と併用します。 レガシーシステムのモデルは、新しいサービスのモデルとほぼ必ず異なります。ACL で両者の間を変換することで、新しいサービスがレガシーのデータ形式や語彙を引き継がずに済みます。ACL のパターンについては、ddd-context-mapping を参照してください。
重要:各移行ステップは個別にリリースできなければなりません。 ある移行ステップに「6 か月かけて書き換えてから切り替える」必要があるなら、それはストラングラーパターンではなく、並行システムを構築したことになります。実際の絞め殺しでは、移行した小さな機能単位を毎週リリースします。
一般的なファサードの実装方法。
- API ゲートウェイ(Kong、Istio、カスタムプロキシ)でパス/ヘッダーに基づいてルーティングします。
- 読み取り元が旧ストアか新ストアかを抽象化するデータベースビュー。
- イベントベースのシステム向けのイベントブリッジ。新旧のサービスが同じイベントを消費し、フィーチャーフラグに基づいてルーティングします。
- 組み込み型のレガシーシステム向けに、コード内で実装するカスタムディスパッチャー(「旧経路か新経路か」を決定するコーディネータークラス)。
移行中のスキーマ。 通常、新しいサービスがデータを所有します。レガシーシステムは引き続き正規のストアを持ちます。次のような戦略があります。
- レガシーから読み取り、両方に書き込みます。 当面、新しいサービスはレガシーシステムから読み取ります。書き込みは両方のストアに行います。新しいストアが正規のストアになったら、読み取り方向を切り替えます。
- レガシーから新しいストアへレプリケーションします。 変更データキャプチャ(CDC)によって、レガシーの変更を新しいストアに反映します。新しいサービスは新しいストアだけから読み取ります。
判断の指針
- 常に、機能の中で最もシンプルな単位を選ぶことから始めます。最もリスクの高い部分に最初から取り組まずに、移行の仕組みが機能することを確認できます。
- 切り替える前に、一定期間、新旧を並行稼働させます。結果を比較し、差異を調査します。
- レガシーを廃止する日付とマイルストーン計画を文書化します。これがないと、移行はいつまでも続き、5 年間にわたって両方のシステムを保守することになります。
- 廃止作業も取り組みの一部であり、後回しにするものではありません。レガシーコードを削除するまでは、移行は完了していません。
アンチパターン
- ストラングラーを装った一括書き換え。 「ストラングラーパターンを使います」と言いながら、計画が「18か月間並行して書き換え、その後切り替える」というものなら、それは看板を付け替えただけの書き換えです。
- 終わりのないストラングラー。 新しいサービスが何年もトラフィックの30%を処理し、誰も移行を完了せず、両方のシステムを永久に保守し続けます。
- ACLなしのストラングラー。 新しいサービスがレガシーのデータ構造をそのまま引き継ぎます。レガシーの悪い設計が置き換え先にまで広がります。
- 技術レイヤーごとに分割する。 一貫した機能を移行せずに「データベース」や「API」を移行すると、中途半端な移行状態になります。
関連項目
ddd-context-mapping— 腐敗防止層は、代表的な組み合わせとなるパターンです。arch-microservices— ストラングラーは、モノリスからマイクロサービスへ移行する標準的な道筋です。arch-event-driven— 旧システムと新システムの橋渡しには、多くの場合イベントが使われます。arch-fitness-functions— 「レガシーコードの経路が実際に使われているか」を自動で確認します。
参考資料
- Martin Fowler、「StranglerFigApplication」(2004年のエッセイ)— 最初の提唱。
- Sam Newman、Monolith to Microservices(O'Reilly)— ストラングラーパターンによる移行についての詳しい章。
コメント
Markdown 対応