Javaにおけるストラングラーパターン:段階的な更新によるレガシーシステムの近代化
別名
- 絞め殺しの木
ストラングラーデザインパターンの意図
ストラングラーパターンは、古いシステムと並行して新しいシステムを構築し、最終的に古いシステムを「絞め殺す」ことで、レガシーシステムを段階的に置き換えます。このパターンを使用すると、古いシステムから新しいシステムへのシームレスな移行が可能になります。
現実世界の例を用いたストラングラーパターンの詳細な説明
現実世界の例
都市計画部門が、毎日の通勤に不可欠な古い橋を近代化することを決定したとします。古い橋を取り壊して大きな混乱を引き起こす代わりに、その隣に新しい近代的な橋を建設します。新しい橋のセクションが完成するにつれて、交通は徐々に古い橋から新しい橋に迂回されます。最終的に、交通の流れ全体が新しい橋に移り、古い橋は廃止されるか、取り壊されます。このようにして、移行はスムーズに行われ、都市の日常活動への影響は最小限に抑えられます。このアプローチは、レガシーシステムが新しいシステムによって段階的に置き換えられ、移行中の継続的な運用を保証するストラングラーデザインパターンを反映しています。
分かりやすく言うと
ストラングラーデザインパターンは、レガシーシステムと並行して新しいシステムを開発し、古いシステムが完全に置き換えられるまで機能を徐々に移行することで、レガシーシステムを段階的に置き換えます。
Wikipediaによると
ストラングラーデザインパターンは、新しいシステムで徐々に置き換えることにより、レガシーシステムを段階的に移行することを含みます。古いコードを新しいコードでラップし、古いコードの使用をリダイレクトまたはログに記録して、シームレスな移行を保証します。このパターンは、宿主の木の周りに成長し、最終的にそれを完全に置き換える絞め殺しのイチジク植物にちなんで名付けられました。モノリシックアプリケーションを近代化し、最小限のリスクと混乱でマイクロサービスアーキテクチャに移行する場合に特に役立ちます。
Javaにおけるストラングラーパターンのプログラム例
Javaにおけるストラングラーデザインパターンは、特定の機能を新しいアプリケーションとサービスで徐々に置き換えることにより、レガシーシステムを段階的に移行するソフトウェア設計パターンです。レガシーシステムの機能が置き換えられるにつれて、新しいシステムは最終的に古いシステムのすべての機能を置き換え、古いシステムを「絞め殺し」、廃止できるようにします。
提供されたコードでは、ストラングラーパターンの動作例を示しています。 `OldArithmetic`クラスはレガシーシステムを表し、`HalfArithmetic`クラスと`NewArithmetic`クラスは開発のさまざまな段階における新しいシステムを表します。
ストラングラーパターンがどのように実装されているかを理解するために、コードを分解してみましょう。
public class OldArithmetic {
private final OldSource source;
public OldArithmetic(OldSource source) {
this.source = source;
}
// The sum and mul methods represent the functionality of the legacy system.
public int sum(int... nums) {
return source.accumulateSum(nums);
}
public int mul(int... nums) {
return source.accumulateMul(nums);
}
}
`OldArithmetic`クラスはレガシーシステムを表します。 `sum`メソッドと`mul`メソッドの2つのメソッドがあり、`OldSource`クラスに依存しています。
public class HalfArithmetic {
private final HalfSource newSource;
private final OldSource oldSource;
public HalfArithmetic(HalfSource newSource, OldSource oldSource) {
this.newSource = newSource;
this.oldSource = oldSource;
}
// The sum method has been migrated to use the new source.
public int sum(int... nums) {
return newSource.accumulateSum(nums);
}
// The mul method still uses the old source.
public int mul(int... nums) {
return oldSource.accumulateMul(nums);
}
// The ifHasZero method is a new feature added in the new system.
public boolean ifHasZero(int... nums) {
return !newSource.ifNonZero(nums);
}
}
`HalfArithmetic`クラスは、移行プロセス中のシステムを表します。 `OldSource`クラスと`HalfSource`クラスの両方に依存しています。 `sum`メソッドは新しいソースを使用するように移行されましたが、`mul`メソッドは引き続き古いソースを使用しています。 `ifHasZero`メソッドは、新しいシステムに追加された新しい機能です。
public class NewArithmetic {
private final NewSource source;
public NewArithmetic(NewSource source) {
this.source = source;
}
// All methods now use the new source.
public int sum(int... nums) {
return source.accumulateSum(nums);
}
public int mul(int... nums) {
return source.accumulateMul(nums);
}
public boolean ifHasZero(int... nums) {
return !source.ifNonZero(nums);
}
}
`NewArithmetic`クラスは、移行プロセス後のシステムを表します。 `NewSource`クラスのみに依存しています。すべてのメソッドが新しいソースを使用するようになりました。
これは、例を実行する`main`メソッドです。
public static void main(final String[] args) {
final var nums = new int[]{1, 2, 3, 4, 5};
//Before migration
final var oldSystem = new OldArithmetic(new OldSource());
oldSystem.sum(nums);
oldSystem.mul(nums);
//In process of migration
final var halfSystem = new HalfArithmetic(new HalfSource(), new OldSource());
halfSystem.sum(nums);
halfSystem.mul(nums);
halfSystem.ifHasZero(nums);
//After migration
final var newSystem = new NewArithmetic(new NewSource());
newSystem.sum(nums);
newSystem.mul(nums);
newSystem.ifHasZero(nums);
}
コンソール出力
13:02:25.030 [main] INFO com.iluwatar.strangler.OldArithmetic -- Arithmetic sum 1.0
13:02:25.032 [main] INFO com.iluwatar.strangler.OldSource -- Source module 1.0
13:02:25.032 [main] INFO com.iluwatar.strangler.OldArithmetic -- Arithmetic mul 1.0
13:02:25.032 [main] INFO com.iluwatar.strangler.OldSource -- Source module 1.0
13:02:25.032 [main] INFO com.iluwatar.strangler.HalfArithmetic -- Arithmetic sum 1.5
13:02:25.032 [main] INFO com.iluwatar.strangler.HalfSource -- Source module 1.5
13:02:25.033 [main] INFO com.iluwatar.strangler.HalfArithmetic -- Arithmetic mul 1.5
13:02:25.033 [main] INFO com.iluwatar.strangler.OldSource -- Source module 1.0
13:02:25.033 [main] INFO com.iluwatar.strangler.HalfArithmetic -- Arithmetic check zero 1.5
13:02:25.033 [main] INFO com.iluwatar.strangler.HalfSource -- Source module 1.5
13:02:25.034 [main] INFO com.iluwatar.strangler.NewArithmetic -- Arithmetic sum 2.0
13:02:25.034 [main] INFO com.iluwatar.strangler.NewSource -- Source module 2.0
13:02:25.034 [main] INFO com.iluwatar.strangler.NewArithmetic -- Arithmetic mul 2.0
13:02:25.034 [main] INFO com.iluwatar.strangler.NewSource -- Source module 2.0
13:02:25.034 [main] INFO com.iluwatar.strangler.NewArithmetic -- Arithmetic check zero 2.0
13:02:25.035 [main] INFO com.iluwatar.strangler.NewSource -- Source module 2.0
これは、ストラングラーパターンの典型的な例です。レガシーシステム(`OldArithmetic`)は、新しいシステム(`HalfArithmetic`および`NewArithmetic`)によって徐々に置き換えられます。新しいシステムは段階的に開発され、各段階でレガシーシステムの一部を「絞め殺し」、レガシーシステムが完全に置き換えられるまで続けます。
Javaでストラングラーパターンを使用する場合
- モノリシックシステムまたはレガシーシステムを段階的に置き換える必要がある場合に使用します。
- リスクまたは複雑さのためにシステムを一度に置き換えることができないシナリオに最適です。
- 継続的な運用を確保しながら、アプリケーションの一部を近代化する必要がある場合に適しています。
- ダウンタイムなしで更新が必要なアプリケーションに最適なストラングラーパターンは、複雑なJavaシステムの段階的な更新をサポートします。
ストラングラーパターン Javaチュートリアル
Javaにおけるストラングラーパターンの実際の適用例
- レガシーモノリシックアプリケーションをマイクロサービスアーキテクチャに置き換えます。
- オンプレミスシステムからクラウドベースシステムへの移行。
- ダウンタイムなしで古いデータベーススキーマから新しいデータベーススキーマに段階的に移行します。
ストラングラーパターンの利点とトレードオフ
利点
- 段階的な交換を可能にすることでリスクを軽減します。
- 移行中の継続的な配信と運用を可能にします。
- 完全な交換の前に新しいコンポーネントをテストおよび検証できます。
トレードオフ
- 新旧システム間の相互作用を管理する必要があるため、複雑になる可能性があります。
- 新旧システムの共存により、一時的なパフォーマンスオーバーヘッドが発生する可能性があります。
- 統合の必要性のために、初期開発時間が長くなる可能性があります。
関連するJavaデザインパターン
- アダプター:移行期間中に新しいシステムが古いシステムと対話するために使用されます。
- ファサード:新旧システムへの統一されたインターフェースを提供し、クライアントの相互作用を簡素化できます。
- マイクロサービス:ストラングラーパターンが適用される多くの場合のターゲットアーキテクチャ。