一般的な Web アプリケーション アーキテクチャCommon Web Application Architectures

"優れたアーキテクチャが高価であると思うならば、不完全なアーキテクチャを試してみてください。""If you think good architecture is expensive, try bad architecture."
- Brian Foote および Joseph Yoder- Brian Foote and Joseph Yoder

まとめSummary

従来の .NET アプリケーションのほとんどは、実行可能ファイルに対応する単一のユニットとして、または 1 つの IIS appdomain 内で実行される単一の Web アプリケーションとして展開されます。Most traditional .NET applications are deployed as single units corresponding to an executable or a single web application running within a single IIS appdomain. これは最も簡単な展開モデルであり、多くの内部的アプリケーションおよび小さなパブリック アプリケーションに適切に対応します。This is the simplest deployment model and serves many internal and smaller public applications very well. ただし、このように単位ユニットとして展開されても、重要なビジネス アプリケーションの大部分は複数のレイヤーへの論理的な分離から恩恵を受けます。However, even given this single unit of deployment, most non-trivial business applications benefit from some logical separation into several layers.

モノリシック アプリケーションとは?What is a monolithic application?

モノリシック アプリケーションは、そのビヘイビアーの観点から見ると、完全な自己独立型のアプリケーションです。A monolithic application is one that is entirely self-contained, in terms of its behavior. このアプリケーションは、操作の実行中に他のサービスまたはデータ ストアとやり取りすることがありますが、アプリケーションのビヘイビアーの中核を成す部分は独自のプロセス内で実行され、通常はアプリケーション全体が単一ユニットとして展開されます。It may interact with other services or data stores in the course of performing its operations, but the core of its behavior runs within its own process and the entire application is typically deployed as a single unit. このようなアプリケーションを水平方向にスケーリングする必要がある場合、通常は、アプリケーション全体を複数のサーバーまたは仮想マシンに複製します。If such an application needs to scale horizontally, typically the entire application is duplicated across multiple servers or virtual machines.

オールインワン アプリケーションAll-in-One applications

アプリケーション アーキテクチャ用の最小限のプロジェクト数は 1 となります。The smallest possible number of projects for an application architecture is one. このアーキテクチャでは、アプリケーションのロジック全体が単一のプロジェクトに含められ、単一のアセンブリにコンパイルされ、単一ユニットとして展開されます。In this architecture, the entire logic of the application is contained in a single project, compiled to a single assembly, and deployed as a single unit.

新しい ASP.NET Core プロジェクトは、Visual Studio またはコマンド ラインのいずれで作成されたかに関係なく、簡単な "オールインワン" モノシリックとして開始されます。A new ASP.NET Core project, whether created in Visual Studio or from the command line, starts out as a simple "all-in-one" monolith. これには、プレゼンテーション、ビジネス、データ アクセス ロジックなど、アプリケーションのあらゆるビヘイビアーが含まれています。It contains all of the behavior of the application, including presentation, business, and data access logic. 図 5-1 に、単一プロジェクト アプリのファイル構造を示します。Figure 5-1 shows the file structure of a single-project app.

図 5-1Figure 5-1. 単一プロジェクトの ASP.NET Core アプリA single project ASP.NET Core app

単一プロジェクトのシナリオでは、フォルダーを使用して懸念事項の分離が実現されます。In a single project scenario, separation of concerns is achieved through the use of folders. 既定のテンプレートには、Models、Views、および Controllers の MVC パターン責任用の分離フォルダーに加えて、Data および Services 用の追加のフォルダーが含まれています。The default template includes separate folders for MVC pattern responsibilities of Models, Views, and Controllers, as well as additional folders for Data and Services. この配置では、プレゼンテーションの詳細は可能な限り Views フォルダーに限定する必要があり、データ アクセス実装の詳細は Data フォルダー内に保持されるクラスに限定する必要があります。In this arrangement, presentation details should be limited as much as possible to the Views folder, and data access implementation details should be limited to classes kept in the Data folder. ビジネス ロジックは、Models フォルダーにあるサービスとモデル内に配置する必要があります。Business logic should reside in services and classes within the Models folder.

単一プロジェクトのモノリシック ソリューションは簡単なのですが、いくつかの欠点があります。Although simple, the single-project monolithic solution has some disadvantages. プロジェクトの規模と複雑さが増大するに従い、ファイルとフォルダーの数も増加し続けます。As the project's size and complexity grows, the number of files and folders will continue to grow as well. アルファベット順にグループ化されていない複数のフォルダーには UI の懸念事項が存在します (Models、Views、Controllers)。UI concerns (models, views, controllers) reside in multiple folders, which are not grouped together alphabetically. この問題は、Filters や ModelBinders などの UI レベル構造が独自のフォルダーに追加される場合にのみ深刻になります。This issue only gets worse when additional UI-level constructs, such as Filters or ModelBinders, are added in their own folders. ビジネス ロジックは Models フォルダーと Services フォルダーに分散され、どのフォルダーのどのクラスが他のどれに依存すべきかは明示されません。Business logic is scattered between the Models and Services folders, and there is no clear indication of which classes in which folders should depend on which others. プロジェクト レベルでのこの編成不足は、スパゲティ コードの原因となることがよくあります。This lack of organization at the project level frequently leads to spaghetti code.

これらの問題に対処するために、アプリケーションは多くの場合、マルチ プロジェクト ソリューションに展開されます。ここで、各プロジェクトは、アプリケーションの特定の "レイヤー" に配置されているとみなされます。In order to address these issues, applications often evolve into multi-project solutions, where each project is considered to reside in a particular layer of the application.

レイヤーとは?What are layers?

アプリケーションの複雑さが増すにつれて、その複雑さを管理することが必要です。その方法の 1 つが、アプリケーションをその責任や懸念事項に従って分割するというものです。As applications grow in complexity, one way to manage that complexity is to break the application up according to its responsibilities or concerns. この方法は懸念事項の分離の原則に従って実施されます。また、この方法を使用すれば、特定の機能が実装されている場所を開発者が容易に見つけられるように、増大するコードベースを常に整理された状態に維持することができます。This follows the separation of concerns principle, and can help keep a growing codebase organized so that developers can easily find where certain functionality is implemented. ただし、レイヤー化されたアーキテクチャには、単なるコード編成に勝る利点が複数あります。Layered architecture offers a number of advantages beyond just code organization, though.

コードをレイヤーに編成することにより、よく使われる下位機能をアプリケーション全体で再利用できるようになります。By organizing code into layers, common low-level functionality can be reused throughout the application. この再利用を行うと、コードをほとんど記述する必要がなくなり、DRY 原則に従って単一の実装でアプリケーションを標準化できるようになるので、便利です。This reuse is beneficial because it means less code needs to be written and because it can allow the application to standardize on a single implementation, following the DRY principle.

レイヤー化されたアーキテクチャの場合、アプリケーションではレイヤー間のやり取りに対して制限を加えることができます。With a layered architecture, applications can enforce restrictions on which layers can communicate with other layers. この制限を利用することで、カプセル化を容易に実現できます。This helps to achieve encapsulation. レイヤーを変更または置換した場合、そのレイヤーと連携しているその他のレイヤーのみが影響を受けます。When a layer is changed or replaced, only those layers that work with it should be impacted. レイヤー同士の依存関係を制限することにより、1 つの変更がアプリケーション全体に影響しないように変更の及ぼす影響を軽減することができます。By limiting which layers depend on which other layers, the impact of changes can be mitigated so that a single change doesn't impact the entire application.

レイヤー (およびカプセル化) により、アプリケーション内で機能を容易に置換できるようになります。Layers (and encapsulation) make it much easier to replace functionality within the application. たとえば、アプリケーションで最初は永続化のために独自の SQL Server データベースが使用されている場合でも、後でクラウド ベースの永続化の方法または Web API の背後での永続化の方法を使用するように選択することが可能です。For example, an application might initially use its own SQL Server database for persistence, but later could choose to use a cloud-based persistence strategy, or one behind a web API. 論理層内でアプリケーションによって永続化の実装が適切にカプセル化されている場合、その SQL Server に固有のレイヤーを、同じパブリック インターフェイスを実装する新しいレイヤーに置き換えることが可能です。If the application has properly encapsulated its persistence implementation within a logical layer, that SQL Server specific layer could be replaced by a new one implementing the same public interface.

将来的な要件の変更に合わせて実装を交換できることに加えて、アプリケーション レイヤーではテスト目的で実装を容易に交換することもできます。In addition to the potential of swapping out implementations in response to future changes in requirements, application layers can also make it easier to swap out implementations for testing purposes. アプリケーションの実際のデータ レイヤーまたは UI レイヤーに対して動作するテストを記述しなくても、これらのレイヤーをテスト時に、要求に対して既知の応答を提供するフェイク実装に置き換えることができます。Instead of having to write tests that operate against the real data layer or UI layer of the application, these layers can be replaced at test time with fake implementations that provide known responses to requests. この方法は、アプリケーションの実際のインフラストラクチャに対してテストを実行する場合と比較して、一般的にテストの記述が簡単であり、テストをより迅速に実行することができます。This typically makes tests much easier to write and much faster to run when compared to running tests again the application's real infrastructure.

論理的なレイヤー化は、エンタープライズ ソフトウェア アプリケーションでのコード編成を改善するための一般的な手法です。コードをレイヤーに編成する方法には複数あります。Logical layering is a common technique for improving the organization of code in enterprise software applications, and there are several ways in which code can be organized into layers.

注意

"レイヤー" とは、アプリケーション内での論理的な分離を表します。Layers represent logical separation within the application. アプリケーション ロジックを個々のサーバーまたはプロセスに物理的に分散するイベントでは、このような個々の物理的展開ターゲットを "階層" と呼んでいます。In the event that application logic is physically distributed to separate servers or processes, these separate physical deployment targets are referred to as tiers. N レイヤー アプリケーションを単一の階層に展開することは可能であり、これは非常に一般的な方法です。It's possible, and quite common, to have an N-Layer application that is deployed to a single tier.

従来の "N レイヤー" アーキテクチャ アプリケーションTraditional "N-Layer" architecture applications

図 5-2 に、レイヤーへのアプリケーション ロジックの最も一般的な編成を示します。The most common organization of application logic into layers it shown in Figure 5-2.

図 5-2Figure 5-2. 代表的なアプリケーション レイヤー。Typical application layers.

これらのレイヤーは多くの場合、UI、BLL (ビジネス ロジック層)、DAL (データ アクセス層) と略称で表現されます。These layers are frequently abbreviated as UI, BLL (Business Logic Layer), and DAL (Data Access Layer). このアーキテクチャを使用する場合、ユーザーは UI レイヤーを介して要求を行います。UI レイヤーは BLL とのみやり取りします。Using this architecture, users make requests through the UI layer, which interacts only with the BLL. 次に BLL は、データ アクセス要求のために DAL を呼び出すことができます。The BLL, in turn, can call the DAL for data access requests. UI レイヤーは DAL に要求を直接出すことも、他の手段によって永続化と直接やり取りすることもありません。The UI layer should not make any requests to the DAL directly, nor should it interact with persistence directly through other means. 同様に、BLL は DAL を経由して永続化とやり取りするだけです。Likewise, the BLL should only interact with persistence by going through the DAL. この方法では、各レイヤーには独自の既知の責任があります。In this way, each layer has its own well-known responsibility.

この従来のレイヤー化アプローチの欠点の 1 つは、コンパイル時の依存関係が上位から下位に向かって適用されるということです。One disadvantage of this traditional layering approach is that compile-time dependencies run from the top to the bottom. つまり、UI レイヤーは BLL に依存し、BLL は DAL に依存するということです。That is, the UI layer depends on the BLL, which depends on the DAL. このことは、アプリケーション内で、通常、最も重要なロジックを保持する BLL が、データ アクセスの実装の詳細 (およびしばしばデータベースの存在) に依存することを意味します。This means that the BLL, which usually holds the most important logic in the application, is dependent on data access implementation details (and often on the existence of a database). このようなアーキテクチャでビジネス ロジックをテストするのは困難なことが多く、テスト データベースが必要となります。Testing business logic in such an architecture is often difficult, requiring a test database. 次のセクションで示すように、依存関係逆転の原則 (Dependency Inversion principle) を使用すれば、この問題に対処できます。The dependency inversion principle can be used to address this issue, as you'll see in the next section.

図 5-3 に、責任 (またはレイヤー) ごとに 3 つのプロジェクトにアプリケーションを分割するソリューションの例を示します。Figure 5-3 shows an example solution, breaking the application into three projects by responsibility (or layer).

図 5-3Figure 5-3. 3 つのプロジェクトによる単純なモノリシック アプリケーション。A simple monolithic application with three projects.

このアプリケーションでは編成上の目的で複数のプロジェクトを使用していますが、アプリケーションは引き続き単一ユニットとして展開され、そのクライアントは単一の Web アプリとしてこのアプリケーションとやり取りします。Although this application uses several projects for organizational purposes, it is still deployed as a single unit and its clients will interact with it as a single web app. これにより、展開プロセスが非常に簡単になります。This allows for very simple deployment process. 図 5-4 に、そのようなアプリを Windows Azure を使用してホストする場合の方法を示します。Figure 5-4 shows how such an app might be hosted using Windows Azure.

図 5-4Figure 5-4. Azure Web アプリの単純な展開Simple deployment of Azure Web App

アプリケーション ニーズの拡大に合わせて、より複雑で堅牢な展開ソリューションが必要な場合があります。As application needs grow, more complex and robust deployment solutions may be required. 図 5-5 に、追加の機能をサポートするより複雑な展開計画の例を示します。Figure 5-5 shows an example of a more complex deployment plan that supports additional capabilities.

図 5-5Figure 5-5. Azure App Service への Web アプリの公開Deploying a web app to an Azure App Service

内部的には、このプロジェクトを責任に基づいて複数のプロジェクトに編成することにより、アプリケーションの保守容易性が向上します。Internally, this project's organization into multiple projects based on responsibility improves the maintainability of the application.

このユニットをスケール アップまたはスケール アウトすることで、クラウド ベースのオンデマンドのスケーラビリティを活用することができます。This unit can be scaled up or out to take advantage of cloud-based on-demand scalability. スケール アップとは、アプリをホストしているサーバーに CPU、メモリ、ディスク領域などのリソースを追加することを意味します。Scaling up means adding additional CPU, memory, disk space, or other resources to the server(s) hosting your app. スケール アウトとは、そのようなサーバーが物理サーバーか仮想マシンかに関係なく、サーバーのインスタンスを追加することを意味します。Scaling out means adding additional instances of such servers, whether these are physical servers or virtual machines. アプリが複数のインスタンスでホストされている場合は、ロード バランサーを使用して個々のアプリ インスタンスに要求が割り当てられます。When your app is hosted across multiple instances, a load balancer is used to assign requests to individual app instances.

Azure 内で Web アプリケーションをスケーリングする最も簡単な方法は、アプリケーションの App Service プランでスケーリングを手動で構成するというものです。The simplest approach to scaling a web application in Azure is to configure scaling manually in the application's App Service Plan. 図 5-6 に、アプリを提供しているインスタンスの数を構成する適切な Azure ダッシュボード画面を示します。Figure 5-6 show the appropriate Azure dashboard screen to configure how many instances are serving an app.

図 5-6Figure 5-6. App での App Service プランによるスケーリング。App Service Plan scaling in Azure.

クリーン アーキテクチャClean architecture

依存関係逆転の原則ならびにドメイン駆動設計 (DDD) の原則に従うアプリケーションは、同様のアーキテクチャに到達する傾向があります。Applications that follow the Dependency Inversion Principle as well as Domain-Driven Design (DDD) principles tend to arrive at a similar architecture. このアーキテクチャには長年にわたってさまざまな名称が付けられてきました。This architecture has gone by many names over the years. 最初の名前の 1 つがヘキサゴナル アーキテクチャ (Hexagonal Architecture) でした。その後に使用された名前がポート アンド アダプター (Ports-and-Adapters) でした。One of the first names was Hexagonal Architecture, followed by Ports-and-Adapters. 最近では、このアーキテクチャはオニオン アーキテクチャまたはクリーン アーキテクチャとして引用されています。More recently, it's been cited as the Onion Architecture or Clean Architecture. 最も新しい名前が "クリーン アーキテクチャ" です。この電子ブックでは、アーキテクチャの説明で基本的にこの名前が使用されています。It is this last name, Clean Architecture, that is used as the basis for describing the architecture in this e-book.

注意

クリーン アーキテクチャという用語は、DDD 原則を使用して構築されたアプリケーションにも、DDD 原則を使用して構築されていないアプリケーションにも適用できます。The term Clean Architecture can be applied to applications that are built using DDD Principles as well as to those that are not built using DDD. 前者の場合、この組み合わせを "クリーン DDD アーキテクチャ" と呼ぶことがあります。In the case of the former, this combination may be referred to as "Clean DDD Architecture".

クリーン アーキテクチャでは、ビジネス ロジックとアプリケーション モデルをアプリケーションの中心に配置します。Clean architecture puts the business logic and application model at the center of the application. ビジネス ロジックはデータ アクセスまたはその他のインフラストラクチャの懸念事項に依存するのでなく、この依存関係は逆転されます。つまり、インフラストラクチャおよび実装の詳細はアプリケーション コアに依存します。Instead of having business logic depend on data access or other infrastructure concerns, this dependency is inverted: infrastructure and implementation details depend on the Application Core. これを達成するには、アプリケーション コア内で抽象化またはインターフェイスを定義し、それらをインフラストラクチャ レイヤーで定義された型によって実装します。This is achieved by defining abstractions, or interfaces, in the Application Core, which are then implemented by types defined in the Infrastructure layer. このアーキテクチャを視覚化するための一般的な方法としては、オニオンに似た一連の同心円を使用します。A common way of visualizing this architecture is to use a series of concentric circles, similar to an onion. 図 5-X に、このスタイルのアーキテクチャを表現した例を示します。Figure 5-X shows an example of this style of architectural representation.

図 5-7Figure 5-7. クリーン アーキテクチャ。オニオン ビューClean Architecture; onion view

この図では、依存関係が最も内側の円に向かっています。In this diagram, dependencies flow toward the innermost circle. したがって、アプリケーション コア (この名前は、この図の中心に位置するところから取ったもの) は他のアプリケーション レイヤーに依存していないことがわかります。Thus, you can see that the Application Core (which takes its name from its position at the core of this diagram) has no dependencies on other application layers. 真中には、アプリケーションのエンティティとのインターフェイスがあります。At the very center are the application's entities and interfaces. そのすぐ外側 (まだアプリケーション コア内) は、ドメイン サービスです。ここでは通常、内側の円で定義されたインターフェイスを実装します。Just outside, but still in the Application Core, are domain services, which typically implement interfaces defined in the inner circle. アプリケーション コアの外側にはユーザー インターフェイス レイヤーとインフラストラクチャ レイヤーがあります。この 2 つはアプリケーション コアに依存しますが、相互に依存関係があるとは限りません。Outside of the Application Core, both the User Interface and the Infrastructure layers depend on the Application Core, but not on one another (necessarily).

図 5-X に、UI とその他のレイヤーの間の依存関係をより正確に反映させた、従来の水平方向レイヤー図を示します。Figure 5-X shows a more traditional horizontal layer diagram that better reflects the dependency between the UI and other layers.

図 5-8Figure 5-8. クリーン アーキテクチャ。水平方向のレイヤー ビューClean Architecture; horizontal layer view

破線の矢印はコンパイル時の依存関係を表し、実線の矢印は実行時専用の依存関係を表します。Note that the solid arrows represent compile-time dependencies, while the dashed arrow represents a runtime-only dependency. クリーン アーキテクチャを使用する場合、UI レイヤーではコンパイル時にアプリケーション コアで定義されたインターフェイスを操作します。インフラストラクチャ レイヤーで定義された実装型を把握しなくてもよいのが理想的です。Using the clean architecture, the UI layer works with interfaces defined in the Application Core at compile time, and ideally should not have any knowledge of the implementation types defined in the Infrastructure layer. ただし、実行時にこれらの実装型は、アプリを実行するために必須となるので、存在する必要があり、また依存関係挿入を介してアプリケーション コアのインターフェイスに接続される必要があります。At runtime, however, these implementation types will be required for the app to execute, so they will need to be present and wired up to the Application Core interfaces via dependency injection.

図 5-9 に、これらの推奨事項に従って ASP.NET Core アプリケーションのアーキテクチャを構築した場合の詳細なビューを示します。Figure 5-9 shows a more detailed view of an ASP.NET Core application's architecture when built following these recommendations.

ASPNET コア アーキテクチャ

図 5-9Figure 5-9. クリーン アーキテクチャに基づく ASP.NET Core アーキテクチャの図。ASP.NET Core architecture diagram following Clean Architecture.

アプリケーション コアはインフラストラクチャに依存していないので、このレイヤーを対象にした自動化された単体テストを記述するのは非常に簡単です。Because the Application Core doesn't depend on Infrastructure, it is very easy to write automated unit tests for this layer. 図 5-10 と図 5-11 に、このアーキテクチャにテストがどのように適合するのかを示します。Figures 5-10 and 5-11 show how tests fit into this architecture.

UnitTestCore

図 5-10Figure 5-10. 分離環境でのアプリケーション コアの単体テスト。Unit testing Application Core in isolation.

IntegrationTests

図 5-11Figure 5-11. 外部依存関係を持つインフラストラクチャ実装の統合テスト。Integration testing Infrastructure implementations with external dependencies.

UI レイヤーはインフラストラクチャ プロジェクトで定義された型に対して直接的な依存関係を持たないことから、テストの促進、またはアプリケーション要件の変更への対応を目的として実装を交換することも容易にできます。Since the UI layer doesn't have any direct dependency on types defined in the Infrastructure project, it is likewise very easy to swap out implementations, either to facilitate testing or in response to changing application requirements. ASP.NET Core には依存関係挿入の使用とサポートが組み込まれているので、このアーキテクチャは重要なモノリシック アプリケーションを構築する方法として最適です。ASP.NET Core's built-in use of and support for dependency injection makes this architecture the most appropriate way to structure non-trivial monolithic applications.

モノリシック アプリケーションの場合、アプリケーション コア、インフラストラクチャ、ユーザー インターフェイスの各プロジェクトはいずれも単一のアプリケーションとして実行されます。For monolithic applications the Application Core, Infrastructure, and User Interface projects are all run as a single application. ランタイム アプリケーションのアーキテクチャは、図 5-12 のようなものになります。The runtime application architecture might look something like Figure 5-12.

ASPNET コア アーキテクチャ 2

図 5-12Figure 5-12. ASP.NET Core アプリのランタイム アーキテクチャの例。A sample ASP.NET Core app's runtime architecture.

クリーン アーキテクチャ内でのコードの整理Organizing Code in Clean Architecture

クリーン アーキテクチャでは、各プロジェクトが明確な責任を担っています。In a Clean Architecture solution, each project has clear responsibilities. そのため、各プロジェクトにはそれぞれ特定の型が属しており、該当するプロジェクトではこれらの型に対応するフォルダーを頻繁に確認できます。As such, certain types will belong in each project and you'll frequently find folders corresponding to these types in the appropriate project.

アプリケーション コアでは、エンティティ、サービス、およびインターフェイスが含まれるビジネス モデルを保持します。The Application Core holds the business model, which includes entities, services, and interfaces. これらのインターフェイスには、データ アクセス、ファイル システム アクセス、ネットワーク呼び出しなどのインフラストラクチャを使用して実行される操作のための抽象化が含まれます。このレイヤーで定義されたサービスまたはインターフェイスは場合によって、UI またはインフラストラクチャに対して依存関係を持たない非エンティティ型を操作する必要があります。These interfaces include abstractions for operations that will be performed using Infrastructure, such as data access, file system access, network calls, etc. Sometimes services or interfaces defined at this layer will need to work with non-entity types that have no dependencies on UI or Infrastructure. これらは単純なデータ転送オブジェクト (DTO) として定義することができます。These can be defined as simple Data Transfer Objects (DTOs).

アプリケーション コアの種類Application Core Types

  • エンティティ (永続化されたビジネス モデル クラス)Entities (business model classes that are persisted)
  • インターフェイスInterfaces
  • サービスServices
  • DTODTOs

インフラストラクチャ プロジェクトには、通常、データ アクセス実装が含まれます。The Infrastructure project will typically include data access implementations. 代表的な ASP.NET Core Web アプリケーションでは、これにはエンティティ フレームワーク DbContext、定義済みの任意の EF コア移行、およびデータ アクセス実装クラスが含まれます。In a typical ASP.NET Core web application, this will include the Entity Framework DbContext, any EF Core Migrations that have been defined, and data access implementation classes. データ アクセス実装コードを抽象化するには、リポジトリ デザイン パターンを使用するのが最も一般的な方法です。The most common way to abstract data access implementation code is through the use of the Repository design pattern.

データ アクセス実装に加えて、インフラストラクチャ プロジェクトにはインフラストラクチャの懸念事項とやり取りする必要があるサービスの実装を含める必要があります。In addition to data access implementations, the Infrastructure project should contain implementations of services that must interact with infrastructure concerns. これらのサービスではアプリケーション コアで定義されているインターフェイスを実装する必要があります。そのため、インフラストラクチャにはアプリケーション コア プロジェクトへの参照を含める必要があります。These services should implement interfaces defined in the Application Core, and so Infrastructure should have a reference to the Application Core project.

インフラストラクチャの種類Infrastructure Types

  • EF コア型 (DbContext、移行)EF Core types (DbContext, Migrations)
  • データ アクセス実装型 (リポジトリ)Data access implementation types (Repositories)
  • インフラストラクチャに固有のサービス (FileLogger、SmtpNotifier など)Infrastructure-specific services (FileLogger, SmtpNotifier, etc.)

ASP.NET Core MVC アプリケーション内のユーザー インターフェイス レイヤーは、アプリケーションのエントリ ポイントになると共に、ASP.NET Core MVC プロジェクトになります。The user interface layer in an ASP.NET Core MVC application will be the entry point for the application, and will be an ASP.NET Core MVC project. このプロジェクトはアプリケーション コア プロジェクトを参照する必要があり、その型はアプリケーション コアで定義されているインターフェイスを介してインフラストラクチャと厳密にやり取りする必要があります。This project should reference the Application Core project, and its types should interact with infrastructure strictly through interfaces defined in Application Core. UI レイヤーにおいて、インフラストラクチャ レイヤー型の直接的なインスタンス化 (またはその静的呼び出し) は許可すべきではありません。No direct instantiation of (or static calls to) Infrastructure layer types should be permitted in the UI layer.

UI レイヤーの種類UI Layer Types

  • ControllersControllers
  • フィルターFilters
  • ビューViews
  • ViewModelsViewModels
  • スタートアップStartup

スタートアップ クラスはアプリケーションの構成と、インターフェイスへの実装型の接続とを担当します。これにより、依存関係挿入は実行時に適切に機能します。The Startup class is responsible for configuring the application, and for wiring up implementation types to interfaces, allowing dependency injection to work properly at run time.

注意

UI プロジェクトの Startup.cs ファイル内の ConfigureServices で依存関係挿入を接続するために、プロジェクトはインフラストラクチャ プロジェクトを参照することが必要な場合があります。In order to wire up dependency injection in ConfigureServices in the Startup.cs file of the UI project, the project may need to reference the Infrastructure project. この依存関係を排除するには、カスタム DI コンテナーを使用するのが最も簡単な方法です。This dependency can be eliminated, most easily by using a custom DI container. このサンプルの目的を考慮すると、UI プロジェクトでインフラストラクチャ プロジェクトを参照できるようにするのが最も簡単な方法です。For the purposes of this sample, the simplest approach is to allow the UI project to reference the Infrastructure project.

モノリシック アプリケーションとコンテナーMonolithic Applications and Containers

モノリシックに展開された単一の Web アプリケーションまたはサービスを構築し、それをコンテナーとして展開することができます。You can build a single and monolithic-deployment based Web Application or Service and deploy it as a container. アプリケーション内では、それはモノリシックとはならずにいくつかのライブラリ、コンポーネント、またはレイヤーに編成される場合があります。Within the application, it might not be monolithic but organized into several libraries, components or layers. 外部的には、単一のプロセス、単一の Web アプリケーション、または単一のサービスのような単一のコンテナーです。Externally it is a single container like a single process, single web application or single service.

このモデルを管理するには、アプリケーションを表す単一のコンテナーを展開します。To manage this model, you deploy a single container to represent the application. ロード バランサーを前面に配置してコピーを追加するだけで、スケーリングできます。To scale, just add additional copies with a load balancer in front. 単一のコンテナーまたは VM で単一の展開を管理することで、このように簡単になります。The simplicity comes from managing a single deployment in a single container or VM.

図 5-X に示すように、複数のコンポーネント/ライブラリ、または内部レイヤーを各コンテナーに含めることができます。You can include multiple components/libraries or internal layers within each container, as illustrated in Figure 5-X. ただし、"コンテナーは 1 つのことを実行し、それを 1 つのプロセスで実行する" というコンテナーの原則に従えば、このモノリシック パターンは矛盾する可能性があります。But, following the container principal of "a container does one thing, and does it in one process", the monolithic pattern might be a conflict.

このアプローチの欠点は、アプリケーションが大きくなり、スケーリングする必要が出てきた場合に顕著になります。The downside of this approach comes if/when the application grows, requiring it to scale. アプリケーション全体がスケーリングすれば、実際には問題ではありません。If the entire application scaled, it's not really a problem. ただし、ほとんどの場合、スケーリングする必要があるネックはアプリケーションの一部であり、他のコンポーネントはそれほど使用されません。However, in most cases, a few parts of the application are the choke points requiring scaling, while other components are used less.

一般的な E コマースを例にとると、スケーリングする必要が生じるのは多くの場合、製品情報のコンポーネントです。Using the typical eCommerce example; what you likely need to scale is the product information component. 製品を購入するユーザーよりも多くのユーザーが製品を参照します。Many more customers browse products than purchase them. より多くの顧客が、支払いパイプラインではなくバスケットを使用します。More customers use their basket than use the payment pipeline. コメントを追加したり、購入履歴を表示したりする顧客はそれほどいません。Fewer customers add comments or view their purchase history. また、単一のリージョンで、コンテンツとマーケティング キャンペーンを管理する必要がある従業員数は多分、ほんの一握りです。And you likely only have a handful of employees, in a single region, that need to manage the content and marketing campaigns. モノリシック デザインのスケーリングにより、コード全体は複数回展開されます。By scaling the monolithic design, all the code is deployed multiple times.

ただし、すべてのコンポーネントをスケーリングする問題に加えて、単一のコンポーネントを変更するには、アプリケーション全体を完全に再テストし、すべてのインスタンスを完全に再展開する必要があります。In addition to the scale everything problem, changes to a single component require complete retesting of the entire application, and a complete redeployment of all the instances.

モノリシック アプローチは一般的であり、多くの組織が、このアーキテクチャ アプローチによって開発を行っています。The monolithic approach is common, and many organizations are developing with this architectural approach. 多くの組織が十分に良好な結果を収めている一方で、限界に達している組織もあります。Many are having good enough results, while others are hitting limits. 多くの組織は、このモデルでアプリケーションを設計していました。これは、ツールとインフラストラクチャのせいでサービス指向アーキテクチャ (SOA) の構築が非常に困難だったためと、アプリケーションが大きくなるまで SOA の必要性がわからなかったためです。Many designed their applications in this model, because the tools and infrastructure were too difficult to build service oriented architectures (SOA), and they didn't see the need - until the app grew. モノリシック アプローチの限界に達しているとわかった場合は、コンテナーとマイクロサービスを有効活用できるようにアプリに分割することを次の論理的な手順とすることができます。If you find you're hitting the limits of the monolithic approach, breaking the app up to enable it to better leverage containers and microservices may be the next logical step.

Microsoft Azure のモノリシック アプリケーションは、各インスタンスに専用の VM を使用して展開できます。Deploying monolithic applications in Microsoft Azure can be achieved using dedicated VMs for each instance. Azure Virtual Machine Scale Sets を使用すると、VM のスケーリングを簡単に行うことができます。Using Azure VM Scale Sets, you can easily scale the VMs. Azure App Service では、VM の管理を必要とせずに、モノリシック アプリケーションを実行し、インスタンスを簡単にスケーリングすることができます。Azure App Services can run monolithic applications and easily scale instances without having to manage the VMs. Azure App Services では、Docker コンテナーの単一インスタンスも実行できるため、展開が簡単になります。Azure App Services can run single instances of Docker containers as well, simplifying the deployment. Docker を使用すれば、1 つの VM を Docker ホストとして展開し、複数のインスタンスを実行できます。Using Docker, you can deploy a single VM as a Docker host, and run multiple instances. 図 5-14 に示すように、Azure バランサーを使用してスケーリングを管理できます。Using the Azure balancer, as shown in the Figure 5-14, you can manage scaling.

さまざまなホストへの展開は、従来の展開手法で管理できます。The deployment to the various hosts can be managed with traditional deployment techniques. Docker ホストは、docker run などのコマンドを使用して手動で管理するか、継続的デリバリー (CD) パイプラインなどのオートメーションによって管理できます。The Docker hosts can be managed with commands like docker run performed manually, or through automation such as Continuous Delivery (CD) pipelines.

コンテナーとして展開するモノリシック アプリケーションMonolithic application deployed as a container

コンテナーを使用してモノリシック アプリケーションの展開を管理することには利点があります。There are benefits of using containers to manage monolithic application deployments. コンテナーのインスタンスをスケーリングする処理は、追加の VM を展開するよりもはるかに高速で簡単です。Scaling the instances of containers is far faster and easier than deploying additional VMs. VM Scale Sets を使用して VM を拡張する場合も、インスタンス化には時間がかかります。Even when using VM Scale Sets to scale VMs, they take time to instance. アプリのインスタンスとして展開する場合、アプリの構成は VM の一部として管理されます。When deployed as app instances, the configuration of the app is managed as part of the VM.

更新プログラムを Docker イメージとして展開する方がはるかに高速で、ネットワークの効率が高くなります。Deploying updates as Docker images is far faster and network efficient. 通常、Docker イメージは秒単位で起動するので、ロールアウトが高速になります。Docker Images typically start in seconds, speeding rollouts. Docker インスタンスの破棄は、docker stop コマンドの発行と同じくらい簡単で、通常は 1 秒未満で完了します。Tearing down a Docker instance is as easy as issuing a docker stop command, typically completing in less than a second.

コンテナーは本質的に設計上、変更不可であるため、VM の破損について心配する必要はありません。一方、更新スクリプトではディスク上に残された特定の構成またはファイルが考慮されない場合があります。As containers are inherently immutable by design, you never need to worry about corrupted VMs, whereas update scripts might forget to account for some specific configuration or file left on disk.

モノシリック アプリが Docker から恩恵を受けることができる一方で、モノリシック アプリケーションを、スケーリング、開発、および展開を個別に実行できるサブシステムに分割することが、マイクロサービスの領域への入り口になる場合があります。While monolithic apps can benefit from Docker, breaking up the monolithic application into sub systems which can be scaled, developed and deployed individually may be your entry point into the realm of microservices.

参照: 一般的な Web アーキテクチャReferences – Common Web Architectures