Guia: Arquitetura com Camadas Domain e Infrastructure
À medida que os projetos crescem, a simples separação em Controllers
, Models
e Entities
pode não ser suficiente. Para construir aplicações robustas, testáveis e fáceis de manter, adotamos padrões de arquitetura mais avançados, como a Arquitetura Limpa (Clean Architecture) e o Design Orientado a Domínio (DDD).
A introdução das camadas Domain
e Infrastructure
é um passo fundamental nessa direção. O objetivo é simples: separar o "o quê" (as regras de negócio) do "como" (os detalhes técnicos).
1. A Camada de Domain
(O Núcleo do Negócio)
Pense na camada de Domain
como o cérebro e o coração da sua aplicação. Ela contém a lógica e as regras que definem o seu negócio, independentemente de qualquer tecnologia.
- Responsabilidade: Definir o que a aplicação faz.
- Regra de Ouro: Esta camada não pode ter dependências de frameworks, bancos de dados ou qualquer detalhe externo. É puro C#.
O que vai dentro da pasta Domain
?
-
Entities (Entidades): As classes que representam os conceitos centrais do seu negócio (
Contact
,User
,Product
). Elas possuem uma identidade (Id
) e um ciclo de vida. -
Value Objects (Objetos de Valor): Classes que representam um valor, como
Email
,Address
ouMoney
. Eles não têm identidade e são imutáveis, ajudando a encapsular regras de validação (ex: umEmail
não pode ser criado com um formato inválido). -
Repository Interfaces (Contratos de Persistência): Este é um ponto crucial. O
Domain
define o contrato de como ele precisa acessar os dados, mas não se importa com a implementação. Ele diz: "Eu preciso de algo que possa salvar, buscar e deletar umContact
".
Exemplo de interface no Domain
:
// Domain/Interfaces/IContactRepository.cs
public interface IContactRepository
{
Task<Contact> GetByIdAsync(int id);
Task<IEnumerable<Contact>> GetAllAsync();
Task AddAsync(Contact contact);
Task UpdateAsync(Contact contact);
Task DeleteAsync(int id);
}
2. A Camada de Infrastructure
(Os Detalhes Técnicos)
A camada de Infrastructure
é onde a "mágica" técnica acontece. Ela implementa os contratos (interfaces) definidos no Domain
usando ferramentas e tecnologias específicas.
- Responsabilidade: Definir como as coisas são feitas.
- Regra de Ouro: Esta camada depende do
Domain
, mas oDomain
nunca depende daInfrastructure
. Isso é chamado de Princípio da Inversão de Dependência.
O que vai dentro da pasta Infrastructure
?
- Repository Implementations: A implementação concreta das interfaces de repositório, usando uma tecnologia específica como o Entity Framework Core.
Exemplo de implementação no Infrastructure
:
// Infrastructure/Data/Repositories/EFContactRepository.cs
public class EFContactRepository : IContactRepository
{
private readonly AgendaContext _context;
public EFContactRepository(AgendaContext context)
{
_context = context;
}
public async Task AddAsync(Contact contact)
{
await _context.Contacts.AddAsync(contact);
await _context.SaveChangesAsync();
}
// ... outras implementações da interface
}
-
Acesso a Dados: O
DbContext
do Entity Framework, as configurações de conexão e asMigrations
pertencem aqui, pois são detalhes de implementação da persistência. -
Serviços Externos: Código para se comunicar com outras APIs, enviar e-mails (usando SendGrid, por exemplo), fazer upload de arquivos para um S3, etc.
Estrutura de Projeto Sugerida
Ao aplicar esses conceitos, a estrutura de uma API pode evoluir para algo mais organizado e escalável:
/src/api/Apps/HelloWorld/
│
├── Application/ # Camada de Aplicação (orquestração)
│ ├── DTOs/ # Seus DTOs (CreateContactDto, ContactResponseDto)
│ └── UseCases/ # Lógica de casos de uso (ex: CreateContactUseCase)
│
├── Domain/ # O CORAÇÃO DO NEGÓCIO
│ ├── Entities/ # Suas entidades (Contact.cs)
│ └── Interfaces/ # Contratos (IContactRepository.cs)
│
├── Infrastructure/ # DETALHES TÉCNICOS
│ ├── Data/
│ │ ├── Context/ # AgendaContext.cs
│ │ ├── Migrations/ # Migrações do EF
│ │ └── Repositories/# Implementações (EFContactRepository.cs)
│ └── Services/ # Serviços externos (EmailService.cs)
│
└── WebApi/ # PONTO DE ENTRADA (Apresentação)
├── Controllers/ # Seus controllers (ContactController.cs)
└── Program.cs # Configuração e injeção de dependência
Nota: Adicionamos a camada
Application
para orquestrar o fluxo entre aWebApi
e oDomain
, e aWebApi
(ouPresentation
) para lidar exclusivamente com as requisições HTTP.
Conclusão: Por que se preocupar com isso?
- Testabilidade: Você pode testar suas regras de negócio (
Domain
) de forma isolada, sem precisar de um banco de dados ou de uma API externa. - Flexibilidade: Quer trocar o SQL Server pelo PostgreSQL? Basta criar uma nova implementação do repositório na
Infrastructure
. ODomain
não será afetado. - Manutenção: A separação clara de responsabilidades torna o código mais fácil de entender, depurar e evoluir.