このパターンは、「レガシーの置き換えパターン」の一部です。
イベントインターセプション
システムの状態へのあらゆる更新をインターセプトし、それらの一部を新しいコンポーネントにルーティングする
2024年3月5日
レガシーシステムを段階的に置き換えることを検討する際、アプリケーションの機能を特定、抽出、および置換することを検討します。これを行うには、レガシーシステムとその代替システムの両方が相互作用する必要があるケースを導入します。それは、状態変更、コマンド処理、クエリ、またはユーザーインタラクションを処理するためです。多くの場合、レガシーシステムは変更が困難またはコストがかかります(この課題に対処することが、そもそも置き換えプログラムの主な理由である可能性があります)。そのため、レガシーシステムへの影響を最小限に抑えながら、新しいシステムによって提供される新しい機能を統合できるメカニズムが必要です。
イベントインターセプションでは、レガシーコンポーネント間の既存の統合ポイントを特定し、可能であれば、それらを新しい機能を導入するために使用できる継ぎ目として利用します。
仕組み

レガシーシステムには、メッセージコンシューマー、HTTP API、SQL接続、バッチジョブなど、イベントインターセプションの対象が多数、通常は多数あります。
レガシーコンポーネント間の既存の統合ポイント(上記の「技術的な継ぎ目」)を利用して、新しいアプリケーションコンポーネントを分解、抽出、または統合できるようにします。イベントインターセプションは、これらの技術的な継ぎ目を使用するテクニックであり、あるコンポーネントから別のコンポーネントに渡されるイベントをインターセプトし、新しいコンポーネント/サービスにルーティングできるようにすることでこれを行います。これを行うことで、以下を期待しています。
- イベントを作成または消費するレガシーコンポーネントへの変更を最小限に抑える
- イベントを新しいシステムにルーティングできるようにする - 複製ありまたはなし
メッセージングインフラ
メッセージングインフラがすでに使用されている場合は、幸運です。その主な利点の1つは、メッセージのプロデューサーをコンシューマーから分離することです。

ワイヤータップ、メッセージルーター、コンテンツベースルーターなどのパターンを使用して、新しいシステムまたは既存のレガシーシステムが処理するためにルーティングおよび処理できるイベントをインターセプトまたは作成できます。メッセージングインフラストラクチャでは通常、メッセージヘッダーを使用してメッセージをフィルター処理し、特定のメッセージをコンシューマーが利用できるようにします。たとえば、JMS実装ではメッセージセレクターを使用して、メッセージプロバイダーがメッセージをフィルター処理できるようにします。このようにして、単純なインターセプションとルーティングを実現できます。

上の図では、レガシーコンシューマーは、メッセージセレクターを含めるように(事実上フィルターを追加するように)プロデューサーを構成する必要があります。
より複雑なルーティングでは、メッセージの本文を検査する必要がある場合があります。この場合(コンテンツベースルーティング)、ルーティングコンポーネントがメッセージを消費し、メッセージペイロードを検査し、メッセージの内容に基づいて必要に応じて新しい宛先キューにメッセージを再エンキューする必要があります。

同様に、レガシーコンシューマーは、新しい宛先から消費するように再構成する必要があります
リバースプロキシ - URL、クエリパラメーター、またはフォームデータに基づくルーティング
リバースプロキシは、イベントを作成またはインターセプトするための非常に効果的な別の方法になる可能性があり、HTTP(S)リクエストを別のリソースにリダイレクトできます。メッセージングインフラストラクチャと同様に、リバースプロキシは通常、ホストとポートの部分、パス、クエリパラメーター、およびヘッダーを簡単に検査した後、リクエストをルーティングできます。

たとえば、フォームデータの内容に応じてリクエストをルーティングするにはカスタム実装が必要になる場合がありますが、非常に柔軟に対応できます。
APIゲートウェイ
APIゲートウェイは、サービスが公開するエンドポイントとその実装の間にある程度の間接性を提供します。大まかなレベルでは、APIゲートウェイは抽象化による分岐パターンを適用する機会を提供し、ゲートウェイがすべてのリクエストを選択した実装にルーティングできるようにします。より細かい粒度では、リクエストまたはペイロードの内容に応じて、必要に応じてサービスリクエストをルーティングすることも可能です。
Webアプリ内 - プログレッシブエンハンスメント
ここでの考え方は、レガシーWebアプリケーションに小さな変更を加えて、近代化の取り組みのリリースサイクルをレガシーアプリケーションへのさらなる変更から分離することです。これを行うには、テンプレート(またはスコープ内のすべてのページ)にスクリプト要素を追加できます。そのスクリプトは時間とともに開発(および独立してリリース)でき、プログレッシブエンハンスメントを使用してユーザーアクションをインターセプトし、必要に応じて動作を変更できます。たとえば、このアプローチを使用して、フォームが送信されるURLを変更するためにイベントハンドラーをアタッチまたは上書きできます。プログレッシブエンハンスメントを追加する前

そしてその後

これをうまく使用した例として、Webストアフロント内のレガシー製品画像ソリューションを置き換えたときがありました。ユーザーが製品の複数の画像を送信でき、専門のユーザーが品質を保証できる新しいシステムを構築しました。レガシーのストアフロントのグローバルテンプレートにスクリプトタグを追加するために簡単な変更を加えることができました。そのスクリプトタグのJavaScriptコンテンツは独立してリリースできました。スクリプトはストアフロント内でプログレッシブエンハンスメントを使用し、新しいシステムに製品の画像があるかどうかを確認し、ある場合は、それらの画像のカルーセルを作成しました。複数の詳細な画像を含む高度なカルーセルを表示することで、販売価格を上げることができました。
データベース層 - トリガー
変更がレガシーデータベースに到達した時点では、イベントインターセプションには遅すぎる可能性があります。とはいえ、「コミット前」トリガーを使用して、データベース書き込みイベントをインターセプトし、さまざまなアクションを実行できます。たとえば、新しいコンポーネントが読み取り/処理するために、別のイベントテーブルに 行を挿入できます。同時に、(または中止して)以前と同様に書き込みを続行します。既存の書き込み動作を変更する場合は、重要な暗黙的なコントラクトを破る可能性があるため、十分な注意が必要です。
事例研究:段階的なドメイン抽出
私たちのチームの1つは、安定性の問題があり、保守が困難になり、更新が遅くなったレガシーシステムを持つクライアントのために働いていました。
組織はこれを改善しようとしており、彼らにとって最も適切な方法は、レガシーシステムをサービスベースアーキテクチャによって実現される機能に置き換えることであると判断されました。
チームが採用した戦略は、ストラングラーフィグパターンを使用し、元のアプリケーションがほとんど残らなくなるまで、一度に1つずつドメインを抽出することでした。考慮された他の考慮事項は次のとおりです。
- 中断することなくレガシーシステムを継続して使用する必要性
- レガシーシステムの保守と機能強化を継続する必要性(ただし、抽出されるドメインへの変更を最小限に抑えることは許可されました)
- レガシーアプリケーションへの変更は最小限に抑える必要がありました。レガシーシステムの保持された知識が不足していました。
レガシー状態
以下の図は、レガシーアーキテクチャのアーキテクチャを示しています。モノリシックシステムのアーキテクチャは、主にプレゼンテーション-ドメイン-データレイヤーでした。
ステージ1 - 単一ドメインのダークローンチサービス
まず、チームは、レガシーシステムと同期を維持するための機能を備えた、単一のビジネスドメインのサービスセットを作成しました。
サービスはダークローンチングを使用しました。つまり、コンシューマーによって使用されるのではなく、代わりにサービスは、チームがデータ移行と同期がレガシーデータストアと100%同等であることを検証できるようにしました。調整チェックに問題があった場合、チームはそれについて検討して修正し、ビジネスに影響を与えることなく整合性を確保できました。
履歴データの移行は、「1回限りの」データ移行プロセスを通じて実現されました。厳密にはイベントインターセプションではありませんが、継続的な同期は変更データキャプチャ(CDC)プロセスを使用して実現されました。
ステージ2 - すべての読み取りをインターセプトし、新しいサービスにリダイレクトする
ステージ2では、チームはレガシーパーシステンス層を更新して、すべての読み取り操作(このドメインの場合)をインターセプトしてリダイレクトし、新しいドメインサービスからデータを取得しました。書き込み操作は、依然としてレガシーデータストアを利用しました。これは、抽象化による分岐の例です。パーシステンス層のインターフェースは変更されず、新しい基盤となる実装が導入されました。
ステージ3 - すべての書き込みをインターセプトし、新しいサービスにリダイレクトする
ステージ3では、多くの変更が発生しました。書き込み操作(ドメインの場合)はインターセプトされ、リダイレクトされて、新しいドメインサービス内でデータを作成/更新/削除しました。
この変更により、新しいドメインサービスがこのデータのシステムオブレコードになりました。レガシーデータストアは更新されなくなったためです。レポートなど、そのデータのダウンストリームでの使用も、新しいドメインサービスの一部になるか、新しいドメインサービスを使用するように移行する必要がありました。
ステージ4 - ドメインビジネスルール/ロジックを新しいサービスに移行する
ステージ4では、ビジネスロジックが新しいドメインサービスに移行されました(それらを貧弱な「データサービス」から真のビジネスサービスに変えました)。フロントエンドは変更されず、新しいドメインサービスへの実装をリダイレクトするレガシーファサードを使用していました。
使用するタイミング
ストラングラーフィグパターンを使用している場合、何らかの形のイベントインターセプションも使用していることになります。創造的であれば、このパターンを使用して継ぎ目を作成できる場所がたくさんあることがわかります。
いくつかの代替アプローチ/考慮事項
ヒューマンイベントインターセプター
イベントがユーザーアクションから発生すると仮定すると、ユーザーに別のことをしてもらうことで、イベントをソースでインターセプトする機会がある可能性があります。近代化の取り組みを最大限に活用するようにビジネスプロセスを再設計すると、レガシーイベントを適用する必要がなくなる可能性があります。それらが必要な場合は、技術的な継ぎ目をまったく作成しないことに対して、ユーザーエクスペリエンスの低下と運用効率の低下を一定期間トレードオフすることが可能になる場合があります。いわゆる「スイベルチェア統合」(ユーザーに新しいシステムで特定のアクションを実行し、古いシステムで別のアクションを実行するように依頼する)は、レガシーパーツの置換を迅速に進めるために必要な継ぎ目を提供できます。
データベーストリガー - コミット後
「コミット後」トリガーは書き込みイベントをインターセプトしませんが、特定の状態変化が発生したことを他のシステムに通知するイベントを作成するのにも役立ちます。
変更データキャプチャ(CDC)
CDC(Change Data Capture)は、データベースのトランザクションログに追加されたエントリからイベントストリームを作成できる技術を包括的に指します。たとえば、私たちのチームでは、Debeziumを使用してKafkaのイベントストリームを作成し、新しいアプリケーションで利用するという良い経験をしています。繰り返しますが、厳密にはインターセプトそのものではありませんが、イベントストリームは並行して運用されている新しいシステムで利用できます。
レガシー内でのイベントルーティング
イベントインターセプトの目的の1つは、新しいシステムとの統合を可能にするためにレガシーシステムを更新する必要性を最小限に抑える、または回避することですが、明らかな代替案として、インターセプターを導入するのではなく、新しいシステムを直接呼び出すように呼び出し元を変更できる場合があります。考慮すべきトレードオフの一部を以下に示します。
- 関心の分離と必要な複雑さ。
呼び出し元は、インターセプターによって処理されるはずのすべての機能と運用上の懸念事項を引き受ける必要があります。たとえば、新しいシステムのインターフェースの契約、メッセージ構造、エラー処理、ロギング、監視、アラートなどを理解する必要があります。 - 追加の複雑さの回避。
レガシーを修正することで、過渡的なアーキテクチャをもう1つ追加する必要がなくなります。これは、問題が発生する可能性が少なく、運用するものが少なくなり、認知負荷が軽減されることを意味します。 - 単一のインターフェースに対して複数の呼び出し元があり、そのインターフェースのプロバイダーが置き換えられる場合、代わりにレガシー模倣パターンを使用することを検討する価値があるかもしれません。新しいコンポーネントはレガシーインターフェースを実装するため、追加の過渡的なアーキテクチャを追加することなく、イベントインターセプターの責任を引き受けます。
さらに詳しく
このパターンとレガシー模倣は、マーティンの最初の投稿にある、より一般化された絞め殺しイチジクパターンをどのように実現できるかの例です。
このパターンは、もともと2004年にMartin Fowlerによってこのサイトにblikiエントリとして公開されましたが、このテキストはその説明に取って代わるものです。
このページは、以下の一部です。
レガシーの置き換えのパターン

パターン
大幅な改訂
2024年3月5日