https://camo.githubusercontent.com/0a28487424adffaad267906742fe50021a39c2cb/68747470733a2f2f77686974657061706572736865616c74682e626c6f622e636f72652e77696e646f77732e6e65742f617070736572766963652f696d616765322e706e67

Figure 5-4. Simple deployment of Azure Web App

As application needs grow, more complex and robust deployment solutions may be required. Figure 5-5 shows an example of a more complex deployment plan that supports additional capabilities.

https://docs.microsoft.com/en-us/azure/architecture/reference-architectures/_images/blueprints/paas-basic-web-app.png

Figure 5-5. 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. 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 or containers. When your app is hosted across multiple instances, a load balancer is used to assign requests to individual app instances.

The simplest approach to scaling a web application in Azure is to configure scaling manually in the application’s App Service Plan. Figure 5-6 shows the appropriate Azure dashboard screen to configure how many instances are serving an app.

https://docs.microsoft.com/en-us/azure/app-service-web/media/app-service-web-scale-a-web-app-in-an-app-service-environment/aseappscale-manualscale.png

Figure 5-6. App Service Plan scaling in Azure.

 

Clean architecture

Applications that follow the Dependency Inversion Principle as well as the Domain-Driven Design (DDD) principles tend to arrive at a similar architecture. This architecture has gone by many names over the years. 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. The most recent name, Clean Architecture, is used to describe this architecture in this e-book.

Note: 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. 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. Figure 5-7 shows an example of this style of architectural representation.

 

 

C:\Users\steve_000\AppData\Local\Microsoft\Windows\INetCache\Content.Word\CleanArchitectureOnion.png

Figure 5-7. Clean Architecture; onion view

In this diagram, dependencies flow toward the innermost circle. The Application Core takes its name from its position at the core of this diagram. It has no dependencies on other application layers. The application’s entities and interfaces are at the very center. Just outside, but still in the Application Core, are domain services, which typically implement interfaces defined in the inner circle. Outside of the Application Core, both the UI and the Infrastructure layers depend on the Application Core, but not on one another (necessarily).

Figure 5-8 shows a more traditional horizontal layer diagram that better reflects the dependency between the UI and other layers.

Image

Figure 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. With the clean architecture, the UI layer works with interfaces defined in the Application Core at compile time, and ideally shouldn’t know about the implementation types defined in the Infrastructure layer. At run time, however, these implementation types are required for the app to execute, so they need to be present and wired up to the Application Core interfaces via dependency injection.

Figure 5-9 shows a more detailed view of an ASP.NET Core application’s architecture when built following these recommendations.

ASPNET Core Architecture

Figure 5-9. ASP.NET Core architecture diagram following Clean Architecture.

Because the Application Core doesn’t depend on Infrastructure, it’s very easy to write automated unit tests for this layer. Figures 5-10 and 5-11 show how tests fit into this architecture.

 

UnitTestCore

Figure 5-10. Unit testing Application Core in isolation.

IntegrationTests

Figure 5-11. Integration testing Infrastructure implementations with external dependencies.

Since the UI layer doesn’t have any direct dependency on types defined in the Infrastructure project, it’s likewise very easy to swap out implementations, either to facilitate testing or in response to changing application requirements. 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.