Clean Architecture - Fundamentos


 Neste artigo vamos recordar os fundamentos da Clean Architecture.
 
Criar projetos escalonáveis, sustentáveis e testáveis é fundamental no cenário em constante evolução do desenvolvimento de software, e uma abordagem arquitetônica que ganhou popularidade significativa para atingir esses objetivos é a Clean Architecture ou Arquitetura Limpa.

Compreendendo a Clean Architecture

A Clean Architecture, também conhecida como Arquitetura Limpa, é um conjunto de princípios e práticas de design de software propostos por Robert C. Martin, um renomado autor e consultor na área de desenvolvimento de software. A ideia principal por trás da Clean Architecture é criar sistemas modularizados e independentes, facilitando a manutenção, testabilidade e evolução do software ao longo do tempo.

Robert C. Martin, também conhecido como “Uncle Bob”, apresentou a Arquitetura Limpa como uma filosofia de design de software que prioriza a separação de preocupações e a capacidade de manutenção.

A Arquitetura Limpa, em sua essência, divide a aplicação em camadas, cada uma assumindo sua própria responsabilidade, facilitando assim o gerenciamento e a evolução mais fáceis.

Os aplicativos que seguem o Princípio de Inversão de Dependência e os princípios de Design Orientado a Domínio (DDD) são chamados de arquitetura limpa. Com uma arquitetura limpa, as camadas de Domínio e de Aplicativo/APl estão no centro do design. Isso é conhecido como o núcleo do sistema da Arquitetura Limpa.

Benefícios da Clean Architecture

A Clean Architecture oferece vários benefícios para o desenvolvimento de software, contribuindo para a criação de sistemas robustos, flexíveis e de fácil manutenção. Alguns dos principais benefícios incluem:

  1. Manutenibilidade: A separação clara de responsabilidades entre as camadas facilita a manutenção do código ao longo do tempo. As mudanças em uma parte do sistema não devem impactar outras partes, permitindo uma evolução mais suave e rápida.

  2. Testabilidade: A Clean Architecture promove a testabilidade, pois as camadas internas podem ser testadas de forma isolada, sem depender das camadas externas. Isso facilita a criação de testes unitários, testes de integração e outros tipos de testes, contribuindo para a qualidade do software.

  3. Flexibilidade e Extensibilidade: A arquitetura modular facilita a substituição de componentes sem afetar o restante do sistema. Isso torna o software mais flexível e extensível, permitindo a adição de novos recursos ou a troca de tecnologias sem grandes impactos.

  4. Independência de Frameworks e Bibliotecas: A separação entre as camadas permite que a lógica de negócios fique independente de frameworks e bibliotecas específicos. Isso é benéfico, pois facilita a migração para novas tecnologias ou a adaptação a mudanças nas tecnologias existentes.

  5. Foco no Domínio do Negócio: A Clean Architecture coloca ênfase no núcleo do domínio da aplicação, isolando-o de detalhes de implementação externos. Isso melhora a compreensão do negócio e facilita a comunicação entre desenvolvedores e stakeholders.

  6. Facilita a Adoção de Práticas Ágeis: A separação de responsabilidades e a ênfase na simplicidade e clareza do código facilitam a adoção de práticas ágeis, como Desenvolvimento Orientado a Testes (TDD) e integração contínua.

  7. Redução de Acoplamento: A arquitetura limpa visa reduzir o acoplamento entre componentes, tornando as diferentes partes do sistema mais independentes. Isso diminui o risco de mudanças em uma parte do sistema afetar outras partes de maneira inesperada.

Clean Architecture

Appliction Core - Lógica de Negócio e Casos de Uso

A Clean Architecture coloca a lógica de negócio da aplicação e os modelos da aplicação no centro da aplicação. Isso garante que os aspectos mais cruciais do software sejam independentes e bem definidos.

Dependência Invertida

Em vez de fazer com que a lógica de negócios dependa do acesso aos dados ou de preocupações com a infraestrutura, a arquitetura limpa promove uma dependência invertida. Isso significa que os detalhes de infraestrutura e implementação dependem da Application Core, revertendo o fluxo típico de dependência.

Abstrações Definidas no Núcleo do Aplicativo

A Application Core define abstrações claras, muitas vezes na forma de interfaces, representando os contratos essenciais aos quais o restante do aplicativo deve aderir. Essas abstrações definem os limites da funcionalidade principal.

Infrastructure

A implementação concreta destas abstrações é feita na camada de Infraestrutura. Esta camada contém os detalhes de como os dados são acessados, os serviços externos são integrados e outros aspectos técnicos são implementados.

Fluxo Interno de Dependências

Todas as dependências fluem para dentro em direção ao Application Core. O Core não depende de nenhuma outra camada, impondo uma separação estrita de interesses e garantindo que a lógica de negócios permaneça independente e focada.

Direção de Dependência

A direção das dependências é clara: tanto as camadas de Infraestrutura quanto de Apresentação dependem da Application Core. As camadas dos casos de uso e Infraestrutura contam com os contratos definidos no Core, garantindo uma interação bem definida e controlada entre as diferentes partes do sistema. princípios
 

Camadas e Testes

A Clean Architecture propõe uma divisão de um sistema em camadas concêntricas, cada uma com um propósito específico. As camadas principais são:

  1. Entities (Entidades): Esta camada contém as entidades de negócios, que representam conceitos fundamentais do domínio da aplicação. As entidades geralmente possuem métodos que encapsulam a lógica de negócios e são independentes das camadas externas.

  2. Use Cases (Casos de Uso): Na camada de Casos de Uso, encontram-se as regras de negócios específicas da aplicação. Os casos de uso coordenam as interações entre as entidades para realizar operações específicas. Esta camada é responsável por orquestrar o fluxo de trabalho da aplicação.

  3. Interface Adapters (Adaptadores de Interface): Os Adaptadores de Interface convertem dados entre as camadas internas e externas. Eles incluem a lógica de apresentação, como controladores, presenters e views, adaptando a informação para ser utilizada pela camada de Casos de Uso.

  4. Frameworks and Drivers (Frameworks e Drivers): A camada mais externa é composta pelos Frameworks e Drivers, e contém os detalhes de implementação externos, como frameworks específicos, bancos de dados, dispositivos de entrada/saída, entre outros. Essa camada é a menos importante para o domínio central da aplicação.

Testes

Os principais testes usados em aplicações que usam a abordagem da Clean Architecture :

Teste funcional para funcionalidade de endpoint de API:

Os testes funcionais, também conhecidos como testes de caixa preta, são de fato mais complexos comparados aos testes unitários. Os testes funcionais avaliam a funcionalidade geral do sistema, geralmente testando o fluxo completo de um recurso específico ou endpoint de API. Esses testes simulam interações reais do usuário e ajudam a garantir que o aplicativo se comporte conforme esperado da perspectiva do usuário final.

Testes de unidade automatizados para o núcleo do aplicativo:

Como o Application Core foi projetado para ser independente de questões de infraestrutura, torna-se simples escrever testes unitários automatizados para essa camada. A ausência de dependências externas permite que os desenvolvedores isolem e testem a lógica central do negócio em um ambiente controlado, facilitando testes e feedback mais rápido durante o processo de desenvolvimento.

Testes de Integração no Projeto de Infraestrutura:

Os testes de integração no projeto de Infraestrutura envolvem testar as implementações reais com dependências externas. Este tipo de teste garante que os diversos componentes integrados à camada de Infraestrutura funcionem juntos conforme o esperado. É crucial validar se a interação da aplicação com bases de dados, APIs externas ou outros componentes da infraestrutura funciona corretamente num ambiente integrado.

Estrutura da Clean Architecture

Considerando um projeto ASP.NET Core Web API que é consumida por uma aplicação React temos a seguir a estrutura básica que pode ser considerada:

O projeto API contém o código do microsserviço com ações do controlador.

No projeto Core temos o Domain que representa a camada Domínio e contém lógica corporativa ou de domínio e inclui entidades, enums, exceções, interfaces, tipos e lógica específica para a camada de domínio. Esta camada não depende de nada externo e  define interfaces que são implementadas por camadas externas. Por exemplo, se a aplicação precisar acessar um serviço de notificação, uma nova interface seria adicionada ao Core e a implementação seria criada dentro da Infraestrutura.

O projeto de Infrastructure representa a camada Infraestrutura e contém classes para acessar recursos externos, como sistemas de arquivos, serviços web, SMTP e assim por diante. Essas classes devem ser baseadas em interfaces definidas na camada Core (Application).

O projeto de Testes contém vários projetos de testes de unidade e integração para ajudá-lo a começar a trabalhar rapidamente. Os detalhes desses projetos serão explorados em uma postagem de acompanhamento. Enquanto isso, fique à vontade para explorar e fazer qualquer pergunta abaixo.

Observação: o projeto Ul pode ser colocado no repositório Git para que possamos gerenciar implantações de forma independente e fácil para operações DevOps.

Princípios seguidos na Clean Architecture

A seguir temos os princípios usados na implementação da Clean Architecture:

1. Separação de preocupações: Evita misturar diferentes responsabilidades de código no mesmo projeto, método, classe;

2. Responsabilidade Única (SRP): Enfatiza que cada módulo ou componente deve ter apenas um motivo para mudança;

3. Não se repita: DRY (Don´t Repeate Yourself) Incentiva a evitar código ou lógica duplicada dentro do sistema;

4. Inverter (e injetar) Dependências: O Princípio de Inversão de Dependência (DIP) defende a inversão da direção das
dependências dentro do sistema. A Clean Architecture consegue isso garantindo que as políticas de alto nível (por exemplo, regras de negócios) não dependam de detalhes de baixo nível (por exemplo, acesso ao banco de dados). A injeção de dependência é frequentemente empregada para facilitar essa inversão, promovendo baixo acoplamento e flexibilidade.

Concluindo podemos dizer que a Clean Architecture fornece uma base robusta para a construção de microsserviços usando a ASP.NET Core. Ao aderir aos princípios de separação de preocupações e inversão de dependência, os desenvolvedores podem criar aplicativos escalonáveis, fáceis de manter e testáveis.

Adotar a Arquitetura Limpa em seus microsserviços na plataforma .NET garante uma base sólida para as demandas em constante mudança do desenvolvimento de software moderno.

E estamos conversados...

"Na verdade, na verdade vos digo que vós chorareis e vos lamentareis, e o mundo se alegrará, e vós estareis tristes, mas a vossa tristeza se converterá em alegria."
João 16:20

Referências:


José Carlos Macoratti