Arquiteturas comuns de aplicativo WebCommon web application architectures

"Se você acha que uma boa arquitetura é cara, tente usar uma arquitetura ruim.""If you think good architecture is expensive, try bad architecture." - Brian Foote e Joseph Yoder- Brian Foote and Joseph Yoder

A maioria dos aplicativos .NET tradicionais é implantada como unidades individuais correspondentes a um executável ou a um único aplicativo Web em execução em um único AppDomain do IIS.Most traditional .NET applications are deployed as single units corresponding to an executable or a single web application running within a single IIS appdomain. Essa abordagem é o modelo de implantação mais simples e fornece muitos aplicativos públicos internos e menores muito bem.This approach is the simplest deployment model and serves many internal and smaller public applications very well. No entanto, mesmo considerando essa única unidade de implantação, a maioria dos aplicativos de negócios não triviais se beneficia de uma separação lógica em várias camadas.However, even given this single unit of deployment, most non-trivial business applications benefit from some logical separation into several layers.

O que é um aplicativo monolítico?What is a monolithic application?

Um aplicativo monolítico é aquele que é totalmente autossuficiente, em termos de comportamento.A monolithic application is one that is entirely self-contained, in terms of its behavior. Ele pode interagir com outros serviços ou armazenamentos de dados durante a execução de suas operações, mas o núcleo de seu comportamento é executado em seu próprio processo e o aplicativo inteiro normalmente é implantado como uma única unidade.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. Se um aplicativo desse tipo precisar ser dimensionado horizontalmente, em geral, o aplicativo inteiro será duplicado em vários servidores ou máquinas virtuais.If such an application needs to scale horizontally, typically the entire application is duplicated across multiple servers or virtual machines.

Aplicativos todos-em-umAll-in-one applications

O menor número possível de projetos para uma arquitetura de aplicativo é um.The smallest possible number of projects for an application architecture is one. Nessa arquitetura, toda a lógica do aplicativo está contida em um único projeto, compilada em um único assembly e implantada como uma única unidade.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.

Um novo projeto ASP.NET Core, seja ele criado no Visual Studio ou por meio da linha de comando, começa como um simples monólito "todos-em-um".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. Ele contém todo o comportamento do aplicativo, incluindo a lógica de apresentação, de negócios e de acesso a dados.It contains all of the behavior of the application, including presentation, business, and data access logic. A Figura 5-1 mostra a estrutura de arquivos de um aplicativo de projeto único.Figure 5-1 shows the file structure of a single-project app.

Um aplicativo ASP.NET Core de projeto único

Figura 5-1.Figure 5-1. Um único projeto de aplicativo ASP.NET Core.A single project ASP.NET Core app.

Em um cenário de projeto único, a separação de interesses é obtida com o uso de pastas.In a single project scenario, separation of concerns is achieved through the use of folders. O modelo padrão inclui pastas separadas para as responsabilidades do padrão MVC de Modelos, Exibições e Controladores, bem como pastas adicionais para Dados e Serviços.The default template includes separate folders for MVC pattern responsibilities of Models, Views, and Controllers, as well as additional folders for Data and Services. Nessa disposição, os detalhes de apresentação devem ser limitados tanto quanto possível à pasta Views e os detalhes de implementação de acesso a dados devem ser limitados às classes mantidas na pasta 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. A lógica de negócios deve residir nos serviços e nas classes dentro da pasta Models.Business logic should reside in services and classes within the Models folder.

Embora simples, a solução monolítica de projeto único traz algumas desvantagens.Although simple, the single-project monolithic solution has some disadvantages. À medida que o tamanho e a complexidade do projeto aumentam, o número de arquivos e pastas continuará crescendo também.As the project's size and complexity grows, the number of files and folders will continue to grow as well. Os interesses de UI (interface do usuário) (modelos, exibições, controladores) residem em várias pastas, que não são agrupadas em ordem alfabética.User interface (UI) concerns (models, views, controllers) reside in multiple folders, which aren't grouped together alphabetically. Esse problema só fica pior quando constructos adicionais no nível da interface do usuário, como Filters ou ModelBinders, são adicionados em suas próprias pastas.This issue only gets worse when additional UI-level constructs, such as Filters or ModelBinders, are added in their own folders. A lógica de negócios é distribuída entre as pastas Modelos e Serviços e não há nenhuma indicação clara de quais classes em quais pastas devem depender de qual delas.Business logic is scattered between the Models and Services folders, and there's no clear indication of which classes in which folders should depend on which others. Essa falta de organização no nível do projeto costuma levar ao código espaguete.This lack of organization at the project level frequently leads to spaghetti code.

Para resolver esses problemas, os aplicativos geralmente evoluem para soluções de vários projetos, em que cada projeto é considerado um residente de determinada camada do aplicativo.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.

O que são camadas?What are layers?

Conforme a complexidade dos aplicativos aumenta, uma maneira de gerenciar essa complexidade é dividir o aplicativo de acordo com suas responsabilidades ou interesses.As applications grow in complexity, one way to manage that complexity is to break up the application according to its responsibilities or concerns. Essa abordagem segue a separação do princípio de preocupações e pode ajudar a manter uma base de código crescente organizada para que os desenvolvedores possam encontrar facilmente onde determinadas funcionalidades são implementadas.This approach 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. Apesar disso, a arquitetura em camadas oferece inúmeras vantagens, além de apenas a organização do código.Layered architecture offers a number of advantages beyond just code organization, though.

Com a organização do código em camadas, a funcionalidade comum de baixo nível pode ser reutilizada em todo o aplicativo.By organizing code into layers, common low-level functionality can be reused throughout the application. Essa reutilização é útil porque significa que menos código precisa ser escrito e ainda pode permitir que o aplicativo seja padronizado em uma única implementação, seguindo o princípio DRY (Don't Repeat Yourself).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 don't repeat yourself (DRY) principle.

Com uma arquitetura em camadas, os aplicativos podem impor restrições sobre quais camadas podem se comunicar com outras camadas.With a layered architecture, applications can enforce restrictions on which layers can communicate with other layers. Essa arquitetura ajuda a atingir o encapsulamento.This architecture helps to achieve encapsulation. Quando uma camada é alterada ou substituída, somente as camadas que trabalham com ela devem ser afetadas.When a layer is changed or replaced, only those layers that work with it should be impacted. Ao limitar quais camadas dependem de outras camadas, o impacto das alterações pode ser reduzido, de modo que uma única alteração não afete todo o aplicativo.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.

As camadas (e o encapsulamento) facilitam grande parte da substituição da funcionalidade dentro do aplicativo.Layers (and encapsulation) make it much easier to replace functionality within the application. Por exemplo, um aplicativo inicialmente pode usar seu próprio banco de dados do SQL Server para persistência, mas, posteriormente, pode optar por usar uma estratégia de persistência baseada em nuvem ou uma protegida por uma API Web.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. Se o aplicativo encapsulasse corretamente sua implementação de persistência dentro de uma camada lógica, essa camada específica de SQL Server poderia ser substituída por uma nova implementação da mesma interface pública.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.

Além do potencial de alternância de implementações em resposta a alterações futuras nos requisitos, as camadas de aplicativo também podem facilitar a alternância de implementações para fins de teste.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. Em vez da necessidade de gravar testes que operam na camada de dados reais ou na camada de interface do usuário do aplicativo, essas camadas podem ser substituídas em tempo de teste com implementações fictícias que fornecem respostas conhecidas a solicitações.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. Essa abordagem geralmente torna os testes muito mais fáceis de escrever e muito mais rápidos para serem executados em comparação com os testes em execução na infraestrutura real do aplicativo.This approach typically makes tests much easier to write and much faster to run when compared to running tests against the application's real infrastructure.

A disposição em camadas lógicas é uma técnica comum para melhorar a organização do código em aplicativos de software empresariais, e há várias maneiras pelas quais o código pode ser organizado em camadas.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.

Observação

As camadas representam uma separação lógica dentro do aplicativo.Layers represent logical separation within the application. Caso a lógica do aplicativo seja fisicamente distribuída em servidores ou processos separados, esses destinos de implantação física separados são chamados de camadas.In the event that application logic is physically distributed to separate servers or processes, these separate physical deployment targets are referred to as tiers. É possível, e bastante comum, ter um aplicativo de N-Camadas que é implantado em uma única camada.It's possible, and quite common, to have an N-Layer application that is deployed to a single tier.

Aplicativos tradicionais da arquitetura de "N Camadas"Traditional "N-Layer" architecture applications

A organização mais comum da lógica do aplicativo em camadas é mostrada na Figura 5-2.The most common organization of application logic into layers is shown in Figure 5-2.

Camadas de aplicativo típicas

Figura 5-2.Figure 5-2. Camadas de aplicativo típicas.Typical application layers.

Essas camadas são frequentemente abreviadas como interface do usuário, BLL (Camada de Lógica de Negócios) e DAL (Camada de Acesso a Dados).These layers are frequently abbreviated as UI, BLL (Business Logic Layer), and DAL (Data Access Layer). Usando essa arquitetura, os usuários fazem solicitações por meio da camada de interface do usuário, que interage com a BLL.Using this architecture, users make requests through the UI layer, which interacts only with the BLL. A BLL, por sua vez, pode chamar a DAL para solicitações de acesso a dados.The BLL, in turn, can call the DAL for data access requests. A camada de interface do usuário não deve fazer solicitações à DAL diretamente nem interagir com persistência diretamente por outros meios.The UI layer shouldn't make any requests to the DAL directly, nor should it interact with persistence directly through other means. Da mesma forma, a BLL só deve interagir com persistência por meio da DAL.Likewise, the BLL should only interact with persistence by going through the DAL. Assim, cada camada tem sua própria responsabilidade conhecida.In this way, each layer has its own well-known responsibility.

Uma desvantagem dessa abordagem tradicional de disposição em camadas é que as dependências em tempo de compilação são executadas de cima para baixo.One disadvantage of this traditional layering approach is that compile-time dependencies run from the top to the bottom. Ou seja, a camada de interface do usuário depende da BLL, que depende da DAL.That is, the UI layer depends on the BLL, which depends on the DAL. Isso significa que a BLL, que normalmente contém a lógica mais importante no aplicativo, depende dos detalhes de implementação de acesso a dados (e geralmente da existência de um banco de dados).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). O teste da lógica de negócios em uma arquitetura como essa costuma ser difícil, exigindo um banco de dados de teste.Testing business logic in such an architecture is often difficult, requiring a test database. O princípio da inversão de dependência pode ser usado para resolver esse problema, como você verá na próxima seção.The dependency inversion principle can be used to address this issue, as you'll see in the next section.

A Figura 5-3 mostra uma solução de exemplo, que divide o aplicativo em três projetos por responsabilidade (ou camada).Figure 5-3 shows an example solution, breaking the application into three projects by responsibility (or layer).

Um aplicativo monolítico simples com três projetos

Figura 5-3.Figure 5-3. Um aplicativo monolítico simples com três projetos.A simple monolithic application with three projects.

Embora esse aplicativo use vários projetos para fins de organização, ele ainda é implantado como uma única unidade e seus clientes interagirão com ele como um único aplicativo Web.Although this application uses several projects for organizational purposes, it's still deployed as a single unit and its clients will interact with it as a single web app. Isso possibilita um processo de implantação muito simples.This allows for very simple deployment process. A Figura 5-4 mostra como um aplicativo desse tipo pode ser hospedado usando o Azure.Figure 5-4 shows how such an app might be hosted using Azure.

Implantação simples do Aplicativo Web do Azure

Figura 5-4.Figure 5-4. Implantação simples do Aplicativo Web do AzureSimple deployment of Azure Web App

Conforme o aplicativo precisar ser aumentado, soluções de implantação mais robustas e complexas poderão ser necessárias.As application needs grow, more complex and robust deployment solutions may be required. A Figura 5-5 mostra um exemplo de um plano de implantação mais complexo compatível com funcionalidades adicionais.Figure 5-5 shows an example of a more complex deployment plan that supports additional capabilities.

Implantando um aplicativo Web em um Serviço de Aplicativo do Azure

Figura 5-5.Figure 5-5. Implantando um aplicativo Web em um Serviço de Aplicativo do AzureDeploying a web app to an Azure App Service

Internamente, a organização desse projeto em vários projetos com base na responsabilidade melhora a facilidade de manutenção do aplicativo.Internally, this project's organization into multiple projects based on responsibility improves the maintainability of the application.

Essa unidade pode ser escalada verticalmente ou expandida para aproveitar a escalabilidade sob demanda baseada em nuvem.This unit can be scaled up or out to take advantage of cloud-based on-demand scalability. Escalar verticalmente significa adicionar mais CPU, memória, espaço em disco ou outros recursos aos servidores que hospedam o aplicativo.Scaling up means adding additional CPU, memory, disk space, or other resources to the server(s) hosting your app. Escalar horizontalmente significa adicionar mais instâncias desses servidores, sejam eles servidores físicos, máquinas virtuais ou contêineres.Scaling out means adding additional instances of such servers, whether these are physical servers, virtual machines, or containers. Quando o aplicativo é hospedado em várias instâncias, um balanceador de carga é usado para atribuir solicitações a instâncias individuais do aplicativo.When your app is hosted across multiple instances, a load balancer is used to assign requests to individual app instances.

A abordagem mais simples para dimensionar um aplicativo Web no Azure é configurar o dimensionamento manualmente no Plano do Serviço de Aplicativo do aplicativo.The simplest approach to scaling a web application in Azure is to configure scaling manually in the application's App Service Plan. A Figura 5-6 mostra a tela apropriada do painel do Azure para configurar a quantidade de instâncias que atendem um aplicativo.Figure 5-6 shows the appropriate Azure dashboard screen to configure how many instances are serving an app.

Dimensionamento do plano do serviço de aplicativo no Azure

Figura 5-6.Figure 5-6. Dimensionamento do Plano do Serviço de Aplicativo no Azure.App Service Plan scaling in Azure.

Arquitetura limpaClean architecture

Os aplicativos que seguem o Princípio da Inversão de Dependência, bem como os princípios de DDD (Design Controlado por Domínio), tendem a chegar a uma arquitetura semelhante.Applications that follow the Dependency Inversion Principle as well as the Domain-Driven Design (DDD) principles tend to arrive at a similar architecture. Essa arquitetura foi conhecida por muitos nomes ao longo dos anos.This architecture has gone by many names over the years. Um dos primeiros nomes foi Arquitetura Hexagonal, seguido por Portas e Adaptadores.One of the first names was Hexagonal Architecture, followed by Ports-and-Adapters. Mais recentemente, ela é citada como a Arquitetura Cebola ou Arquitetura Limpa.More recently, it's been cited as the Onion Architecture or Clean Architecture. O último nome, Arquitetura Limpa, é usado como o nome dessa arquitetura neste livro eletrônico.The latter name, Clean Architecture, is used as the name for this architecture in this e-book.

O aplicativo de referência eShopOnWeb usa a abordagem de arquitetura limpa para organizar seu código em projetos.The eShopOnWeb reference application uses the Clean Architecture approach in organizing its code into projects. Você pode encontrar um modelo de solução que pode ser usado como um ponto de partida para seu próprio ASP.NET Core no repositório GitHub ardalis/cleanarchitecture .You can find a solution template you can use as a starting point for your own ASP.NET Core on the ardalis/cleanarchitecture GitHub repository.

A arquitetura limpa coloca a lógica de negócios e o modelo de aplicativo no centro do aplicativo.Clean architecture puts the business logic and application model at the center of the application. Em vez de fazer com que a lógica de negócios dependa do acesso a dados ou de outros interesses da infraestrutura, essa dependência é invertida: os detalhes de implementação e a infraestrutura dependem do Núcleo do Aplicativo.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. Essa funcionalidade é obtida definindo-se abstrações, ou interfaces, no núcleo do aplicativo, que são implementadas por tipos definidos na camada de infraestrutura.This functionality is achieved by defining abstractions, or interfaces, in the Application Core, which are then implemented by types defined in the Infrastructure layer. Uma maneira comum de visualizar essa arquitetura é usar uma série de círculos concêntricos, semelhantes a uma cebola.A common way of visualizing this architecture is to use a series of concentric circles, similar to an onion. A Figura 5-7 mostra um exemplo desse estilo de representação de arquitetura.Figure 5-7 shows an example of this style of architectural representation.

Arquitetura Limpa; exibição de cebola

Figura 5-7.Figure 5-7. Arquitetura Limpa; exibição de cebolaClean Architecture; onion view

Nesse diagrama, as dependências fluem para o círculo interno.In this diagram, dependencies flow toward the innermost circle. O núcleo do aplicativo obtém seu nome por meio de sua posição no centro desse diagrama.The Application Core takes its name from its position at the core of this diagram. E você pode ver no diagrama que o Núcleo do Aplicativo não tem dependências de outras camadas do aplicativo.And you can see on the diagram that the Application Core has no dependencies on other application layers. As entidades e as interfaces do aplicativo ficam bem no centro.The application's entities and interfaces are at the very center. Fora dele, mas ainda no Núcleo do Aplicativo, estão os serviços de domínio, que normalmente implementam interfaces definidas no círculo interno.Just outside, but still in the Application Core, are domain services, which typically implement interfaces defined in the inner circle. Fora do Núcleo do Aplicativo, as camadas de Interface do Usuário e de Infraestrutura dependem do Núcleo do Aplicativo, mas não (necessariamente) uma da outra.Outside of the Application Core, both the UI and the Infrastructure layers depend on the Application Core, but not on one another (necessarily).

A Figura 5-8 mostra um diagrama de camada horizontal mais tradicional que reflete melhor a dependência entre a interface do usuário e as outras camadas.Figure 5-8 shows a more traditional horizontal layer diagram that better reflects the dependency between the UI and other layers.

Arquitetura Limpa; exibição de camada horizontal

Figura 5-8.Figure 5-8. Arquitetura Limpa; exibição de camada horizontalClean Architecture; horizontal layer view

Observe que as setas sólidas representam as dependências em tempo de compilação, enquanto a seta tracejada representa uma dependência somente em runtime.Note that the solid arrows represent compile-time dependencies, while the dashed arrow represents a runtime-only dependency. Usando a arquitetura limpa, a camada de interface do usuário funciona com as interfaces definidas no Núcleo do Aplicativo no tempo de compilação. O ideal é que ela não tenha conhecimento dos tipos de implementação definidos na camada de Infraestrutura.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. No entanto, no tempo de execução, esses tipos de implementação serão necessários para a execução do aplicativo e, portanto, precisam estar presentes e conectados às interfaces do Núcleo do Aplicativo por meio da injeção de dependência.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.

A Figura 5-9 mostra uma exibição mais detalhada da arquitetura de um aplicativo ASP.NET Core quando criado seguindo essas recomendações.Figure 5-9 shows a more detailed view of an ASP.NET Core application's architecture when built following these recommendations.

Diagrama de arquitetura de ASP.NET Core seguindo a arquitetura limpa

Figura 5-9.Figure 5-9. Diagrama da arquitetura do ASP.NET Core que segue a Arquitetura Limpa.ASP.NET Core architecture diagram following Clean Architecture.

Como o Núcleo do Aplicativo não depende da Infraestrutura, é muito fácil escrever testes de unidade automatizados para essa camada.Because the Application Core doesn't depend on Infrastructure, it's very easy to write automated unit tests for this layer. A Figuras 5-10 e 5-11 mostram como os testes se enquadram nessa arquitetura.Figures 5-10 and 5-11 show how tests fit into this architecture.

UnitTestCore

Figura 5-10.Figure 5-10. Realizando o teste de unidade do Núcleo do Aplicativo em isolamento.Unit testing Application Core in isolation.

IntegrationTests

Figura 5-11.Figure 5-11. Realizando o teste de integração de implementações de Infraestrutura com dependências externas.Integration testing Infrastructure implementations with external dependencies.

Como a camada de interface do usuário não tem nenhuma dependência direta dos tipos definidos no projeto de Infraestrutura, da mesma forma, é muito fácil alternar entre implementações, para facilitar o teste ou em resposta a alterações nos requisitos do aplicativo.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. O uso interno do ASP.NET Core e o suporte à injeção de dependência torna essa arquitetura a maneira mais apropriada de estruturar aplicativos monolíticos não triviais.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.

Para aplicativos monolíticos, o núcleo do aplicativo, a infraestrutura e os projetos de interface do usuário são executados como um único aplicativo.For monolithic applications, the Application Core, Infrastructure, and UI projects are all run as a single application. A arquitetura do aplicativo em runtime pode ser semelhante à Figura 5-12.The runtime application architecture might look something like Figure 5-12.

Arquitetura do ASP.NET Core 2

Figura 5-12.Figure 5-12. Arquitetura em runtime de um aplicativo ASP.NET Core de exemplo.A sample ASP.NET Core app's runtime architecture.

Organizando o código na arquitetura limpaOrganizing code in Clean Architecture

Em uma solução de Arquitetura Limpa, cada projeto tem responsabilidades bem-definidas.In a Clean Architecture solution, each project has clear responsibilities. Assim, determinados tipos pertencem a cada projeto e, com frequência, haverá pastas correspondentes a esses tipos no projeto apropriado.As such, certain types belong in each project and you'll frequently find folders corresponding to these types in the appropriate project.

Núcleo do aplicativoApplication Core

O Núcleo do Aplicativo contém o modelo de negócios, que inclui entidades, serviços e interfaces.The Application Core holds the business model, which includes entities, services, and interfaces. Essas interfaces incluem abstrações para operações que serão executadas usando a infraestrutura, como acesso a dados, acesso ao sistema de arquivos, chamadas de rede, etc. Às vezes, serviços ou interfaces definidos nessa camada precisarão trabalhar com tipos que não sejam de entidade que não tenham dependências na interface do usuário ou na infraestrutura.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. Eles podem ser definidos como DTOs (Objetos de Transferência de Dados) simples.These can be defined as simple Data Transfer Objects (DTOs).

Tipos de Núcleo do AplicativoApplication Core types
  • Entidades (classes de modelo de negócios que são persistidas)Entities (business model classes that are persisted)
  • InterfacesInterfaces
  • ServiçosServices
  • DTOsDTOs

InfraestruturaInfrastructure

O projeto de Infraestrutura normalmente incluirá implementações de acesso a dados.The Infrastructure project typically includes data access implementations. Em um aplicativo Web ASP.NET Core típico, essas implementações incluem o DbContext do EF (Entity Framework), todos os objetos Migration do EF Core que foram definidos e as classes de implementação de acesso a dados.In a typical ASP.NET Core web application, these implementations include the Entity Framework (EF) DbContext, any EF Core Migration objects that have been defined, and data access implementation classes. A maneira mais comum de abstrair o código de implementação de acesso a dados é pelo uso do padrão de design de Repositório.The most common way to abstract data access implementation code is through the use of the Repository design pattern.

Além das implementações de acesso a dados, o projeto de Infraestrutura deve conter implementações de serviços que devem interagir com os interesses de infraestrutura.In addition to data access implementations, the Infrastructure project should contain implementations of services that must interact with infrastructure concerns. Esses serviços devem implementar as interfaces definidas no Núcleo do Aplicativo e, portanto, a Infraestrutura deve ter uma referência ao projeto de Núcleo do Aplicativo.These services should implement interfaces defined in the Application Core, and so Infrastructure should have a reference to the Application Core project.

Tipos de infraestruturaInfrastructure types
  • Tipos do EF Core (DbContext, Migration)EF Core types (DbContext, Migration)
  • Tipos de implementação de acesso a dados (Repositórios)Data access implementation types (Repositories)
  • Serviços específicos de infraestrutura (por exemplo, FileLogger ou SmtpNotifier)Infrastructure-specific services (for example, FileLogger or SmtpNotifier)

Camada de interface do usuárioUI Layer

A camada de interface do usuário em um aplicativo ASP.NET Core MVC é o ponto de entrada para o aplicativo.The user interface layer in an ASP.NET Core MVC application is the entry point for the application. Esse projeto deve referenciar o projeto de Núcleo do Aplicativo e seus tipos devem interagir com a infraestrutura estritamente por meio das interfaces definidas no Núcleo do Aplicativo.This project should reference the Application Core project, and its types should interact with infrastructure strictly through interfaces defined in Application Core. Não deve ser permitida nenhuma criação de instância direta de tipos da camada de Infraestrutura nem nenhuma chamada estática a esses tipos na camada de interface do usuário.No direct instantiation of or static calls to the Infrastructure layer types should be allowed in the UI layer.

Tipos de camada de interface do usuárioUI Layer types
  • ControladoresControllers
  • FiltrosFilters
  • ExibiçõesViews
  • ViewModelsViewModels
  • InicializaçãoStartup

A classe Startup é responsável por configurar o aplicativo e conectar os tipos de implementação às interfaces, permitindo que a injeção de dependência funcione corretamente em tempo de execução.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.

Observação

Para conectar a injeção de dependência em ConfigureServices no arquivo Startup.cs do projeto de interface do usuário, o projeto poderá precisar referenciar o projeto de Infraestrutura.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. Essa dependência pode ser eliminada com mais facilidade por meio de um contêiner de DI personalizado.This dependency can be eliminated, most easily by using a custom DI container. Para as finalidades desta amostra, a abordagem mais simples é permitir que o projeto de interface do usuário referencie o projeto de Infraestrutura.For the purposes of this sample, the simplest approach is to allow the UI project to reference the Infrastructure project.

Contêineres e aplicativos monolíticosMonolithic applications and containers

Você pode criar um Aplicativo ou Serviço Web baseado em uma implantação única e monolítica e implantá-lo como um contêiner.You can build a single and monolithic-deployment based Web Application or Service and deploy it as a container. Dentro do aplicativo, ele pode não ser monolítico, mas organizado em várias bibliotecas, componentes ou camadas.Within the application, it might not be monolithic but organized into several libraries, components, or layers. Externamente, ele é um único contêiner, como um único processo, um único aplicativo Web ou um único serviço.Externally, it's a single container like a single process, single web application, or single service.

Para gerenciar esse modelo, implante um contêiner único para representar o aplicativo.To manage this model, you deploy a single container to represent the application. Para dimensionar, basta adicionar mais cópias com um balanceador de carga na frente.To scale, just add additional copies with a load balancer in front. A simplicidade está em gerenciar um a implantação única em um contêiner ou VM único.The simplicity comes from managing a single deployment in a single container or VM.

Figura 5-13

É possível incluir vários componentes/bibliotecas ou camadas internas em cada contêiner, conforme ilustrado na Figura 5-13.You can include multiple components/libraries or internal layers within each container, as illustrated in Figure 5-13. Mas, seguindo o princípio de contêiner de "um contêiner executa uma ação e faz isso em um processo", o padrão monolítico pode gerar um conflito.But, following the container principle of "a container does one thing, and does it in one process", the monolithic pattern might be a conflict.

O ponto negativo dessa abordagem ficará evidente se ou quando o aplicativo crescer e for necessário dimensioná-lo.The downside of this approach comes if/when the application grows, requiring it to scale. Não haverá problema se o aplicativo inteiro for dimensionado.If the entire application scales, it's not really a problem. Entretanto, na maioria dos casos, apenas algumas partes do aplicativo são os pontos de redução que exigem dimensionamento, enquanto outros componentes são menos utilizados.However, in most cases, a few parts of the application are the choke points requiring scaling, while other components are used less.

Usando o exemplo de comércio eletrônico típico, o que você provavelmente precisa dimensionar é o componente de informações do produto.Using the typical eCommerce example, what you likely need to scale is the product information component. Uma quantidade muito maior de clientes procura produtos em vez de comprá-los.Many more customers browse products than purchase them. Mais clientes usam o carrinho em vez do pipeline de pagamento.More customers use their basket than use the payment pipeline. Menos clientes fazem comentários ou exibem o histórico de compras.Fewer customers add comments or view their purchase history. E você provavelmente tem apenas um grupo de funcionários, em uma única região, que precisa gerenciar o conteúdo e as campanhas de marketing.And you likely only have a handful of employees, in a single region, that need to manage the content and marketing campaigns. Ao dimensionar o design monolítico, todo o código é implantado várias vezes.By scaling the monolithic design, all the code is deployed multiple times.

Além do problema de “ter que dimensionar tudo”, a alteração de um único componente exige um novo teste completo de todo o aplicativo e uma reimplantação completa de todas as instâncias.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.

A abordagem monolítica é comum e muitas organizações estão desenvolvendo aplicativos com essa abordagem de arquitetura.The monolithic approach is common, and many organizations are developing with this architectural approach. Muitas estão tendo resultados bons o suficiente, enquanto outras estão atingindo os limites.Many are having good enough results, while others are hitting limits. Muitas criaram seus aplicativos nesse modelo porque as ferramentas e a infraestrutura eram muito difíceis para criar SOAs (arquiteturas orientadas a serviços) e elas não viam a necessidade até que o aplicativo crescesse.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. Se você achar que está chegando ao limite da abordagem monolítica, a divisão do aplicativo para permitir que ele aproveite melhor os contêineres e os microsserviços poderá ser a próxima etapa lógica.If you find you're hitting the limits of the monolithic approach, breaking up the app to enable it to better leverage containers and microservices may be the next logical step.

Figura 5-14

A implantação de aplicativos monolíticos no Microsoft Azure pode ser feita por meio de VMs dedicadas para cada instância.Deploying monolithic applications in Microsoft Azure can be achieved using dedicated VMs for each instance. Usando Conjuntos de Dimensionamento de Máquinas Virtuais do Azure, você pode dimensionar VMs facilmente.Using Azure Virtual Machine Scale Sets, you can easily scale the VMs. Os Serviços de Aplicativos do Azure podem executar aplicativos monolíticos e dimensionar instâncias com facilidade, sem a necessidade de gerenciar as VMs.Azure App Services can run monolithic applications and easily scale instances without having to manage the VMs. Os Serviços de Aplicativos do Azure também podem executar instâncias únicas de contêineres do Docker, simplificando a implantação.Azure App Services can run single instances of Docker containers as well, simplifying the deployment. Usando o Docker, você pode implantar uma única VM como um host do Docker e executar várias instâncias.Using Docker, you can deploy a single VM as a Docker host, and run multiple instances. Usando o balanceador do Azure, conforme mostrado na Figura 5-14, você pode gerenciar o dimensionamento.Using the Azure balancer, as shown in the Figure 5-14, you can manage scaling.

A implantação em vários hosts pode ser gerenciada com técnicas de implantação tradicionais.The deployment to the various hosts can be managed with traditional deployment techniques. Os hosts do Docker podem ser gerenciados manualmente com comandos como docker run executados manualmente ou por meio da automação, como os pipelines de CD (Entrega Contínua).The Docker hosts can be managed with commands like docker run performed manually, or through automation such as Continuous Delivery (CD) pipelines.

Aplicativo monolítico implantado como um contêinerMonolithic application deployed as a container

Há benefícios no uso de contêineres para gerenciar implantações de aplicativos monolíticos.There are benefits of using containers to manage monolithic application deployments. O dimensionamento das instâncias de contêineres é muito mais rápido e fácil do que a implantação de VMs adicionais.Scaling the instances of containers is far faster and easier than deploying additional VMs. Mesmo quando você usa conjuntos de dimensionamento de máquinas virtuais para dimensionar VMs, a criação de instância das VMs é demorada.Even when using virtual machine scale sets to scale VMs, they take time to instance. Quando implantada como instâncias de aplicativo, a configuração do aplicativo é gerenciada como parte da VM.When deployed as app instances, the configuration of the app is managed as part of the VM.

Implantar atualizações como imagens do Docker é muito mais rápido e eficiente em termos de rede.Deploying updates as Docker images is far faster and network efficient. As Imagens do Docker costumam ser iniciadas em segundos, o que agiliza as distribuições.Docker Images typically start in seconds, speeding rollouts. Desmontar uma instância do Docker é tão fácil quanto emitir um comando docker stop e geralmente leva menos de um segundo.Tearing down a Docker instance is as easy as issuing a docker stop command, typically completing in less than a second.

Como os contêineres são, de forma inerente, imutáveis por design, você nunca precisa se preocupar com VMs corrompidas, enquanto os scripts de atualização podem se esquecer de considerar uma configuração específica ou um arquivo deixado no disco.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 the disk.

Você pode usar contêineres do Docker para uma implantação monolítica de aplicativos Web mais simples.You can use Docker containers for a monolithic deployment of simpler web applications. Essa abordagem melhora a integração contínua e os pipelines de implantação contínua e ajuda a atingir o sucesso da implantação para a produção.This approach improves continuous integration and continuous deployment pipelines and helps achieve deployment-to-production success. Não mais "ele funciona em meu computador, por que ele não funciona em produção?"No more “It works on my machine, why does it not work in production?”

Uma arquitetura baseada em microsserviços tem muitos benefícios, mas esses benefícios são fornecidos ao custo do aumento da complexidade.A microservices-based architecture has many benefits, but those benefits come at a cost of increased complexity. Em alguns casos, os custos superam os benefícios, portanto, um aplicativo de implantação monolítica em execução em um único contêiner ou em alguns contêineres é uma opção melhor.In some cases, the costs outweigh the benefits, so a monolithic deployment application running in a single container or in just a few containers is a better option.

Um aplicativo monolítico não pode ser facilmente decomposto em microsserviços bem separados.A monolithic application might not be easily decomposable into well-separated microservices. Os microsserviços devem funcionar independentemente uns dos outros para fornecer um aplicativo mais resiliente.Microservices should work independently of each other to provide a more resilient application. Se você não puder entregar fatias independentes de recurso do aplicativo, separá-las apenas aumentará a complexidade.If you can't deliver independent feature slices of the application, separating it only adds complexity.

Talvez o aplicativo ainda não precise dimensionar recursos de modo independente.An application might not yet need to scale features independently. Muitos aplicativos, quando precisam ser dimensionados para mais de uma única instância, podem passar pelo processo relativamente simples de clonagem da instância inteira.Many applications, when they need to scale beyond a single instance, can do so through the relatively simple process of cloning that entire instance. O trabalho adicional para separar o aplicativo em serviços discretos fornece um benefício mínimo ao dimensionar as instâncias completas do aplicativo é simples e econômico.The additional work to separate the application into discrete services provides a minimal benefit when scaling full instances of the application is simple and cost-effective.

No início do desenvolvimento de um aplicativo, você pode não ter uma ideia clara de onde estão os limites funcionais naturais.Early in the development of an application, you might not have a clear idea where the natural functional boundaries are. Mesmo depois de desenvolve rum produto mínimo viável, a separação natural pode ainda não ter surgido.As you develop a minimum viable product, the natural separation might not yet have emerged. Algumas dessas condições podem ser temporárias.Some of these conditions might be temporary. Você pode começar criando um aplicativo monolítico e posteriormente separar alguns recursos para serem desenvolvidos e implantados como microsserviços.You might start by creating a monolithic application, and later separate some features to be developed and deployed as microservices. Outras condições podem ser essenciais para o espaço problemático do aplicativo, o que significa que o aplicativo pode nunca ser dividido em vários microserviços.Other conditions might be essential to the application's problem space, meaning that the application might never be broken into multiple microservices.

A separação de um aplicativo em vários processos distintos também apresenta sobrecarga.Separating an application into many discrete processes also introduces overhead. É mais complexo separar recursos em processos diferentes.There's more complexity in separating features into different processes. Os protocolos de comunicação tornam-se mais complexos.The communication protocols become more complex. Em vez de chamadas de método, você deve usar a comunicação assíncrona entre serviços.Instead of method calls, you must use asynchronous communications between services. Ao passar para uma arquitetura de microsserviços, você precisa adicionar muitos dos blocos de construção implementados na versão de microsserviços do aplicativo eShopOnContainers: manipulação de barramento de eventos, resiliência e novas tentativas de mensagem, consistência eventual e muito mais.As you move to a microservices architecture, you need to add many of the building blocks implemented in the microservices version of the eShopOnContainers application: event bus handling, message resiliency and retries, eventual consistency, and more.

O aplicativo de referência eShopOnWeb muito mais simples dá suporte ao uso de único contêiner monolítico.The much simpler eShopOnWeb reference application supports single-container monolithic container usage. O aplicativo inclui um aplicativo Web com exibições de MVC, APIs Web e Razor Pages tradicionais.The application includes one web application that includes traditional MVC views, web APIs, and Razor Pages. Este aplicativo pode ser iniciado na raiz da solução com os comandos docker-compose build e docker-compose up.This application can be launched from the solution root using the docker-compose build and docker-compose up commands. Esse comando configura um contêiner para a instância da Web usando o Dockerfile encontrado na raiz do projeto Web e executa o contêiner em uma porta especificada.This command configures a container for the web instance, using the Dockerfile found in the web project's root, and runs the container on a specified port. Você pode baixar o código-fonte desse aplicativo do GitHub e executá-lo localmente.You can download the source for this application from GitHub and run it locally. Até mesmo esse aplicativo monolítico beneficia-se de ser implantado em um ambiente do contêiner.Even this monolithic application benefits from being deployed in a container environment.

Por exemplo, a implantação em contêineres significa que cada instância do aplicativo é executada no mesmo ambiente.For one, the containerized deployment means that every instance of the application runs in the same environment. Essa abordagem inclui o ambiente de desenvolvimento no qual ocorrem testes e desenvolvimento antecipados.This approach includes the developer environment where early testing and development take place. A equipe de desenvolvimento pode executar o aplicativo em um ambiente em contêineres que corresponda ao ambiente de produção.The development team can run the application in a containerized environment that matches the production environment.

Além disso, os aplicativos em contêineres são expandidos a um custo mais baixo.In addition, containerized applications scale out at a lower cost. O uso de um ambiente de contêiner permite um compartilhamento maior de recursos do que os ambientes de VM tradicionais.Using a container environment enables greater resource sharing than traditional VM environments.

Por fim, colocar o aplicativo em contêineres força uma separação entre a lógica de negócios e o servidor de armazenamento.Finally, containerizing the application forces a separation between the business logic and the storage server. À medida que o aplicativo for escalado horizontalmente, os vários contêineres dependerão de uma única mídia de armazenamento físico.As the application scales out, the multiple containers will all rely on a single physical storage medium. A mídia de armazenamento seria normalmente um servidor de alta disponibilidade executando um banco de dados do SQL Server.This storage medium would typically be a high-availability server running a SQL Server database.

Suporte ao DockerDocker support

O eShopOnWeb projeto é executado no .net.The eShopOnWeb project runs on .NET. Portanto, ele pode ser executado em contêineres baseados em Linux ou em Windows.Therefore, it can run in either Linux-based or Windows-based containers. Observe que, para a implantação do Docker, você deseja usar o mesmo tipo de host para o SQL Server.Note that for Docker deployment, you want to use the same host type for SQL Server. Os contêineres baseados em Linux permitem o uso de um espaço menor e são preferenciais.Linux-based containers allow a smaller footprint and are preferred.

Você pode usar o Visual Studio 2017 ou posterior para adicionar o suporte ao Docker a um aplicativo existente clicando com o botão direito do mouse em um projeto no Gerenciador de Soluções e escolhendo Adicionar > Suporte ao Docker.You can use Visual Studio 2017 or later to add Docker support to an existing application by right-clicking on a project in Solution Explorer and choosing Add > Docker Support. Esta etapa adiciona os arquivos necessários e modifica o projeto para usá-los.This step adds the files required and modifies the project to use them. O exemplo eShopOnWeb atual já têm esses arquivos.The current eShopOnWeb sample already has these files in place.

O arquivo docker-compose.yml no nível da solução contém informações sobre quais imagens devem ser criadas e quais contêineres devem ser iniciados.The solution-level docker-compose.yml file contains information about what images to build and what containers to launch. O arquivo permite que você use o comando docker-compose para iniciar vários aplicativos ao mesmo tempo.The file allows you to use the docker-compose command to launch multiple applications at the same time. Nesse caso, ele está iniciando apenas o projeto Web.In this case, it is only launching the Web project. Você também pode usá-lo para configurar dependências, como um contêiner de banco de dados separado.You can also use it to configure dependencies, such as a separate database container.

version: '3'

services:
  eshopwebmvc:
    image: eshopwebmvc
    build:
      context: .
      dockerfile: src/Web/Dockerfile
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
    ports:
      - "5106:5106"

networks:
  default:
    external:
      name: nat

O arquivo docker-compose.yml referencia o Dockerfile no projeto Web.The docker-compose.yml file references the Dockerfile in the Web project. O Dockerfile é usado para especificar qual contêiner base será usado e como o aplicativo será configurado nele.The Dockerfile is used to specify which base container will be used and how the application will be configured on it. O Dockerfile do Web:The Web' Dockerfile:

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /app

COPY *.sln .
COPY . .
WORKDIR /app/src/Web
RUN dotnet restore

RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS runtime
WORKDIR /app
COPY --from=build /app/src/Web/out ./

ENTRYPOINT ["dotnet", "Web.dll"]

Solução de problemas do DockerTroubleshooting Docker problems

Depois que você iniciar a execução do aplicativo em contêineres, ele continuará sendo executado até que você o pare.Once you run the containerized application, it continues to run until you stop it. É possível ver quais contêineres estão em execução com o comando docker ps.You can view which containers are running with the docker ps command. Você pode parar um contêiner em execução usando o comando docker stop e especificando a ID do contêiner.You can stop a running container by using the docker stop command and specifying the container ID.

Observe que a execução de contêineres do Docker pode ser associada a portas, que caso contrário, você tentaria usar em seu ambiente de desenvolvimento.Note that running Docker containers may be bound to ports you might otherwise try to use in your development environment. Se você tentar executar ou depurar um aplicativo usando a mesma porta, como um contêiner do Docker em execução, ocorrerá um erro informando que o servidor não pôde ser associado a essa porta.If you try to run or debug an application using the same port as a running Docker container, you'll get an error stating that the server can't bind to that port. Mais uma vez, parar o contêiner deverá resolver o problema.Once again, stopping the container should resolve the issue.

Para adicionar o suporte ao Docker ao aplicativo usando o Visual Studio, verifique se o Docker Desktop está em execução.If you want to add Docker support to your application using Visual Studio, make sure Docker Desktop is running when you do so. Quando você iniciar o assistente, ele não será executado corretamente se o Docker Desktop não estiver em execução.The wizard won't run correctly if Docker Desktop isn't running when you start the wizard. Além disso, o assistente examinará sua escolha de contêiner atual para adicionar o suporte ao Docker correto.In addition, the wizard examines your current container choice to add the correct Docker support. Se você quiser adicionar o, suporte para contêineres do Windows, será necessário executar o assistente enquanto houver área de trabalho do Docker em execução com contêineres do Windows configurados.If you want to add, support for Windows Containers, you need to run the wizard while you have Docker Desktop running with Windows Containers configured. Se você quiser adicionar o, suporte para contêineres do Linux, execute o assistente enquanto você tem o Docker em execução com contêineres do Linux configurados.If you want to add, support for Linux containers, run the wizard while you have Docker running with Linux containers configured.

Referências – arquiteturas comuns da WebReferences – Common web architectures