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:
Um projeto que contém todos os contratos (as classes) e abstrações, enquanto
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:
O projeto onde as Migrações são executadas
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: