レイヤードアーキテクチャパターンは、正しく実装された場合にコードを編成する一貫性のある安全な方法を提供する。ただし、これらのレイヤーが相互作用する方法は依然として最大の懸念事項といえる。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
コード構造を設計するときは、ソフトウェアスタック内で機能を分離する方法を検討すると役立つことがしばしばある。その方法の一つとして、アプリケーションのレイヤーをその上下に存在する他のレイヤーから抽象化することが挙げられる。これは、「レイヤードアーキテクチャパターン」と呼ばれることが多いアプローチだ。
レイヤードアーキテクチャの各レイヤーは、特定のアプリケーションまたはビジネス目標に合わせて設計される。そのため、レイヤーとレイヤーが管理する機能の間には、明確な抽象化が存在する。例えば、アプリケーションは、ユーザービューをレンダリングするレイヤー、Web APIへの応答を中継するレイヤーおよびファイルシステムまたはデータベースへのデータの保存を担当するレイヤーを維持しているかもしれない。
関連するレイヤーの数に特別な制限はないが、一般的なWebベースのアプリケーションアーキテクチャには、次の4つの基本レイヤーが含まれる場合がある。
この分離により、アプリケーションロジックをカプセル化し、システムの単一部分における変更の影響を分離し、個々のアプリケーションコンポーネントに対して独立したテストを実行する方法が提供される。開発者は、隣接するレイヤーのスタブ実装を挿入して相互作用を評価し、操作を分離したままにすることもできる。
さらに、プレゼンテーションレイヤーをドメインから分離すると、機密データのフィールドがサードパーティーまたはその他の権限のないエンドユーザーに公開されることを制限できる。例えば、アプリケーションが新しいユーザープロファイルオブジェクトをレンダリングするとき、単純な見落としによって、ドメインまたはエンティティオブジェクト内のハッシュされたパスワードやその他の機密資格情報が誤って公開される可能性がある。
ただし、プレゼンテーションレイヤーが応答のレンダリングに独自の表現を使用している場合、それらのオブジェクトを処理する永続レイヤーのエラーによって機密データが誤ってユーザーに公開される可能性は低くなる。
レイヤードアーキテクチャ設計を追求する開発チームは、実装中に幾つかの基本ガイドラインに従う必要がある。
アーキテクチャ内のレイヤーは、抽象化と運用上の価値の適切なバランスを提供する必要がある。チームは、アーキテクチャ設計プロセスのできるだけ早い段階で、レイヤー名、その目的およびレイヤー内に存在する関連エンティティを特定する必要がある。下図は、単一の映画チケット予約アプリケーションで使用可能な全てのオブジェクトのリストをレイヤーごとに示している。
基本的なレイヤードアーキテクチャパターンでは、スタック内のレイヤーは、隣接するレイヤーにのみ作用する。これにより変更の影響が制限され、各レイヤーがそのコア機能に関連するある程度の独立したアプリケーションロジックを維持することが期待される。
ただし、特定のアプリケーション操作には特定のレイヤーが関与する必要がない場合がある。このような場合、開発者はレイヤーをオープンにすると、隣接するレイヤーがそのレイヤーを通過するか、完全にスキップする可能性がある。一方、閉じたレイヤーには常にパススルーが必要だ。下図は、一般的なアーキテクチャ設定におけるオープンレイヤーとクローズドレイヤーの概念を示している。
レイヤーごとに、そのレイヤーに固有のストアとプロセスの詳細を分離することが重要だ。例えば、下図のコード例では、「PaymentReceiptPresenter」は、UIをレンダリングするために必要なフィールドを永続データストアに保存する。ただし、PaymentEntityオブジェクト(これも永続データストア内に存在する必要がある)は、ユーザーに表示されるべきではない機密性の高いアカウントデータをキャプチャーして保存する。この2つをそれぞれプレゼンテーションレイヤーまたは永続レイヤーのいずれかに常駐できる個別のクラスに分離すると、データのカプセル化が強化され、意図しない情報漏えいの可能性が減る。
レイヤードアーキテクチャパターンを使用すると、幾つかの問題が発生する可能性がある。これは多くの場合、実装中に現れる問題に関係するものだ。レイヤードアーキテクチャを最大限に活用するには、これらの潜在的なリスクに注意することが重要だ。
レイヤードアーキテクチャは、さまざまなアプリケーションレイヤーにわたる並列処理には適していない。代わりに、アーキテクチャの設計では、リクエストが各レイヤーを順番に通過して目的を達成することを前提としている。
ワークフロー内のレイヤーの一つがオブジェクトの状態を操作する必要がある場合、開発者は、リクエストを次のレイヤーに渡すか、次のレイヤーに渡すかどうかについてそのレイヤーが独自の決定を行えるようにするための追加の措置を講じる必要がある(レイヤーを開いたり閉じたりするなど)。それを他の場所に中継する。レイヤードアーキテクチャの設計では、デフォルトではこれらの問題に対処できない。
一部のレイヤーは、特定の操作を実行せずにリクエストを通過させる中間プロキシとして機能できる。ただし、ワークフロー内のレイヤーが多過ぎると、単なるパススルーとして機能し、コストを正当化するのに十分な実用性がなくなり、オーバーヘッドになる可能性がある。開発チームは、削除できる冗長なレイヤーを作成するか、必要に応じてオープンレイヤーに変換することで、この問題に対処できる。ワークフロー内でプロキシとしてのみ機能するレイヤーの数を20%未満に抑えるようにすべきだ。
レイヤードアーキテクチャは、コードベース内のアプリケーション機能の小さくまとまった単位に、十分な可読性、信頼性および構造を与えることができる。ただし、コードの量が増加するにつれて、時間の経過とともに各レイヤーの機能とドメインの概念が蓄積され、エンティティ間に論理的な境界を引くことがますます困難になる可能性がある。さらに、これによってレイヤー間でコンポーネントが緊密に結合される可能性があり、最終的には更新やテストのために個々のモジュールを取り出すことが困難になる。
開発チームは、開発サイクルの早い段階で包括的な機能パッケージをリリースすることで、この問題に正面から対処できる。結合が制御不能にならないように、レイヤードアーキテクチャ内の依存関係を継続的に管理することも重要だ。
Copyright © ITmedia, Inc. All Rights Reserved.