ASP.NET Core - Implementando Clean Architecture - I
  Neste artigo voltamos a tratar da Clean Architecture e sua implementação em uma aplicação ASP.NET Core.


Em uma Arquitetura Limpa, a solução é projetada com a camada de domínio ou Application Core no centro e a camada de apresentação ou UI e a camada de persistência ou Persistence dependendo do Core.
 



 

O Application Core define as abstrações necessárias, que a camada de infraestrutura implementa e a camada de interface do usuário usa para chamar funcionalidades. Dessa forma, as interações acontecem por meio de abstrações definidas na camada Core seguindo o princípio de Inversão de Dependência.

Pode-se visualizar essa abordagem na forma de uma cebola (daí o nome Onion Architecture). O Application Core está no centro, com as camadas de persistência e apresentação formando dois lados da camada externa.

 

 

Cabe destacar o seguinte:

 

- Na figura, note que as dependências fluem em direção ao círculo mais interno.

- O Application Core recebe o nome de sua posição no centro deste diagrama.

- Observe que o Application Core não tem dependências de outras camadas de aplicativos.

- As entidades e interfaces do aplicativo estão no centro.

- Fora, mas ainda no Application Core, estão os serviços de domínio, que normalmente implementam interfaces definidas no círculo interno.

- Fora do Application Core, as camadas de UI e Infraestrutura dependem do Application Core, mas não uma da outra (necessariamente).

 

Blocos de construção de uma solução usando a Clean Architecture

 

Uma solução simples projetada para usar a Clean Architecture geralmente possui 3 camadas:

 

1. Camada Application Core

 

A camada Application Core é o centro da arquitetura e é a camada mais baixa ou interna.

Ela contém a lógica de negócios principal junto com Entidades e Interfaces para comunicação com serviços de infraestrutura.

Ela também contém os DTOs (Data Transfer Objects) que podem ser exigidos pelos serviços para passar dados para as camadas superiores.

Um Application Core típico contém os seguintes tipos:

- Entidades
- Serviços
- Especificações
- Exceções personalizadas
- Eventos e manipuladores

 

Podemos dividir esta camada em dois projetos:

  1. Um projeto que contém todos os contratos (as classes) e abstrações, enquanto

  2. O outro projeto contém comportamentos e manipuladores.

2. A camada de persistência

A camada de persistência contém lógica para persistir dados (armazenar dados).

Esta camada também é chamada de infraestrutura, pois ela se comunica com a infraestrutura subjacente para armazenar e recuperar dados ou outros serviços.

No contexto em que o projeto usa o Entity Framework Core com um DbContext (assim como a maioria dos aplicativos de negócios corporativos), a Infraestrutura contém o DatabaseContext e os arquivos de migração necessários para se comunicar com o banco de dados por meio do DbContext.

Ele também contém implementações para as abstrações que o Application Core definiu para lidar com operações de acesso a dados, nós as chamamos de Repositórios.

A camada de Infraestrutura depende do Application Core para acessar essas abstrações.

Uma infraestrutura típica contém o seguinte:

- Contexto de banco de dados
- Arquivos de migração
- Implementações de repositório definidas no Application Core
- Quaisquer outras implementações de serviço que exijam chamar serviços de infraestrutura, como Loggers


Podemos dividir esta camada em dois projetos:

  1. O projeto onde as Migrações são executadas

  2. E o projeto onde existem as implementações do Repositório. É puramente uma escolha de design, mas funciona bem.

3. A camada de interface do usuário

A camada de interface do usuário ou a camada de apresentação é o ponto de entrada para o aplicativo através do qual a comunicação é iniciada

A camada de interface do usuário faz referência ao núcleo do aplicativo e usa as abstrações nele definidas para chamar as funcionalidades internas.

Como a camada de UI precisa registrar as abstrações com suas implementações para injeção de dependência, ela tem uma dependência somente de tempo de execução na camada de infraestrutura.

A camada de interface do usuário contém apenas o código necessário para apresentação e pode conter o seguinte:

- Controladores
- Filtros personalizados
- Middlewares personalizados
- Views
- ViewModels
- Classe de inicialização onde as implementações são registradas na DI

 

Como as dependências são mapeadas ?

A figura a seguir ilustra o fluxo de dependências na Clean Architecture:


Aqui vemos o seguinte:

Como a Application Core não depende de nenhuma outra camada, os testes unitários dos comportamentos do Core presentes no núcleo do aplicativo é relativamente mais simples e isso aumenta o escopo do teste de unidade.

Quando queremos realizar testes de integração junto com a Infraestrutura, também podemos fazê-lo porque agora exigimos apenas as dependências do projeto Application Core e Infrastructure. Comparando isso com o caso de uma abordagem N-Camadas linear onde para realizar uma integração você precisa passar pela camada de apresentação vemos como essa abordagem é mais robusta.

Conclusão

A Clean Architecture apresenta uma abordagem que pode ser usada em aplicações que devem crescer em tamanho e dessa forma podemos criar uma solução testável fracamente acoplada que também pode melhorar a cobertura do código.

E estamos conversados... 

"Olhai para as aves do céu, que nem semeiam, nem segam, nem ajuntam em celeiros; e vosso Pai celestial as alimenta. Não tendes vós muito mais valor do que elas?"
Mateus 6:26

Referências:


José Carlos Macoratti