Introdução

Clean Architecture é uma arquitetura que mantém o foco no domain. Seu objetivo principal é isolar e manter independência do domínio. A Clean propõe que o domínio (domain) nunca deve depender de detalhes externos.

O conceito foi baseado nas boas práticas e nas arquitetureas hexagonal e cebola, dentre outras, que já propunham a separação das responsabilidades em camadas e tinham como objetivo produzir sistemas com as seguintes características.

Isto é:

Camadas

A princípio essa arquitetura possui 4 camadas mínimas, o número suficiente manter o isolamento funcional (apesar de não haver restrição de número máximo).

image.png

Entidades (Entities)

No centro da arquitetura, temos as classes responsáveis pelas regras de negócios, que podem ser dois tipos: Entidades e Casos de Uso.

Entidade: conjunto de regras de negócios relacionadas que são críticas para o funcionamento do aplicativo.

Como as entidades não conhecem as outras camadas elas não dependem de nada

Casos de uso (Use cases)

Nessa camada contém as regras de negócio específica do aplicativo. Dizem como automatizar o sistema determinando o seu comportamento.

Alguns exemplos de casos de usos são:

Como vimos na imagem acima, os casos de usos interagem e dependem das entidades, mas não sabem nada mais sobre as camadas mais distantes.

Adptadores (Adpters)

Na terceira camada a partir do centro, temos classes e interfaces chamadas de Adaptadores. A função dela é converter os dados de um formato para outro. São os tradutores entre domínio e a infraestrutura.

Eles convertem os dados do formato mais convenientes para os casos de usos e entidades

Esssa é a camada que vai conter a implementação MVC de uma UI com apresentadores, vizualizações e controladores, ou que poderá realizar a implementação dos endpoints de uma API REST

Nenhum código dentro desse círculo deve saber absolutamente nada sobre o banco de dados

Camada mais externa

Essa camada é para onde vão todos os componentes de entrada ou saída (input, output), a interface com o usuário (UI), o banco de dados, os frameworks, os dispositivos, etc.

Essa camada é para onde vão todos os detalhes como as interfaces e banco de dados. Ela é a camada mais volátil, pois pode mudar com frequência. E por isso, essa camada é mantida o mais longe possível das camadas de domínio.

Como elas são mantidas separadas, é fácil fazer alterações ou trocar um componente por outro. (por exemplo UI, banco de dados, estruturas e dispositivos)

Considerações finais das camadas

clean-architecture-cone.jpg

Desse modo, podemos dizer que

As camadas internas são mais estáveis

As camadas externas são mais sujeitas a mudanças

As entidades raramente devem ser modificadas

Alterações nos Use Cases não devem ser motivadas por mudanças na tecnologia, banco de dados, frameworks, etc.

A Regra de dependência garante que as entidades e os casos de usos sejam classes limpas de qualquer tecnologia ou serviço externo ao sistema

The Dependency Rule

**The Dependency Rule.** Essa é a regra de ouro dessa arquitetura: Dependências sempre apontam para dentro. Ou seja, a camada interna nunca depende de uma externa.

Relação da Clean com o DDD

A Clean Architecture não é um substituto do DDD, ela é na verdade uma arquitetura que facilita o DDD.

Desse modo, podemos afirmar que o DDD define o que modelar (o negócio), e a Clean define como organizar (a arquitetura protege o negócio)

Clean na prática com .NET

Como já vimos na teoria tudo começa pelo domínio, e as dependências sempre apontam para dentro. O fluxo existe para garantir que as dependências sempre apontem para dentro, mas nunca ao contrário. É o que Uncle Bob chama de Dependency Rule. Então, abaixo mostrei o fluxo de execução conceitual e das dependências.

Fluxo conceitual (de execução)

Quando o sistema roda, o fluxo natural de execução é:

Usuário → API → Application → Domain → Infrastructure

ou, em palavras:

  1. O usuário chama um endpoint (ex: POST /pedidos).
  2. O Controller (camada API) recebe a requisição e aciona o Use Case.
  3. O Use Case orquestra as regras e cria entidades do Domain.
  4. O Domain aplica suas regras, invariantes e validações.
  5. O Use Case pode então chamar um repositório (definido como interface no Application), cuja implementação concreta está na Infrastructure (ex: gravação no banco).

Então o fluxo de execução vai “pra baixo” — mas o fluxo de dependência vai pra dentro.

O fluxo das dependências (de código-fonte)

Agora o segredo:

Mesmo que o fluxo de execução vá da API → Infra, o código e as referências entre projetos apontam no sentido oposto:

MyApp.Api ──→ MyApp.Application ──→ MyApp.Domain
                    ↑
                    │
         MyApp.Infrastructure (implementa interfaces)

então, resumidamente, as dependências possuem esse tipo de papel:

Camada Papel Depende de
Domain Regras puras (núcleo) Ninguém
Application Usa as regras do domínio Domain
API (ou UI) Mostra o sistema pro mundo Application
Infrastructure Conecta o sistema ao mundo real Domain + Applicatio

Estrutura típica de um projeto .NET

Geralmente a solução .sln fica assim:

CleanOrders/
│
├── src/
│   ├── CleanOrders.Domain/
│   ├── CleanOrders.Application/
│   ├── CleanOrders.Infrastructure/
│   └── CleanOrders.Api/
│
├── tests/
│   ├── CleanOrders.UnitTests/
│   └── CleanOrders.IntegrationTests/
│
└── CleanOrders.sln