Como Migrar de uma Arquitetura de 3 Camadas para uma Arquitetura Limpa

Como Migrar de uma Arquitetura de 3 Camadas para uma Arquitetura Limpa

Migrar de uma arquitetura de 3 camadas para uma arquitetura limpa pode parecer desafiador, mas é um passo importante para melhorar a manutenibilidade, escalabilidade e flexibilidade de um projeto. Enquanto a arquitetura de 3 camadas separa as preocupações de apresentação, lógica de negócios e acesso a dados, a Arquitetura Limpa (ou Clean Architecture) busca uma maior separação de responsabilidades, enfatizando a inversão de dependência, de forma que a lógica central da aplicação (Domínio) não dependa de implementações de infraestrutura.

Neste artigo, exploraremos como realizar essa migração, focando em um exemplo C#/.NET, embora o conceito também possa ser aplicado a outras tecnologias.

Arquitetura de 3 Camadas vs Arquitetura Limpa

Antes de iniciarmos a migração, é importante entender a diferença entre as duas arquiteturas.

  • Arquitetura de 3 camadas: Normalmente consiste em uma Camada de Apresentação (UI), uma Camada de Negócio (lógica de aplicação) e uma Camada de Acesso a Dados. Aqui, a camada de negócio frequentemente se conecta diretamente à camada de dados.

  • Arquitetura Limpa: Baseada no princípio da inversão de dependência, ela separa mais claramente as preocupações em quatro grandes camadas: Domínio, Aplicação, Infraestrutura e Interface de Usuário. A regra de ouro da Arquitetura Limpa é que as dependências devem sempre apontar para o centro, ou seja, as camadas externas dependem das internas, mas nunca o contrário.

A transição entre essas duas arquiteturas pode melhorar o design da aplicação, facilitando a testabilidade e a manutenção.

Configurando os Projetos para Arquitetura Limpa

Para começar, você precisará reorganizar seus projetos de forma que reflitam a separação de responsabilidades da Arquitetura Limpa. Siga estas etapas:

1. Renomeie sua Camada de Acesso a Dados para Camada de Domínio

A Camada de Domínio contém as entidades, regras de negócio e lógica de domínio fundamentais da aplicação. Na Arquitetura de 3 Camadas, a lógica de negócio pode estar misturada à camada de acesso a dados. Na Arquitetura Limpa, ela é movida para o Domínio, com foco em manter a lógica de negócios independente de qualquer infraestrutura ou tecnologia específica.

2. Renomeie sua Camada de Negócio para Camada de Aplicação

A Camada de Aplicação lida com casos de uso específicos e coordena o comportamento do sistema. Ela define interfaces para repositórios e serviços que serão implementados em outras camadas (como a Infraestrutura), mas não contém implementações concretas. Isso permite que a camada de aplicação seja totalmente testável e independente da infraestrutura.

3. Adicione a Camada de Infraestrutura

A Camada de Infraestrutura contém as implementações concretas dos repositórios, serviços de terceiros, contexto de banco de dados, entre outros. Esta camada é onde sua aplicação se conecta ao mundo externo (banco de dados, APIs, etc.), mas essas implementações devem ser abstraídas por interfaces que estão definidas nas camadas mais internas, como o Domínio ou a Aplicação.

4. Atualize as Referências

Na Arquitetura Limpa, as referências entre as camadas devem sempre seguir a regra de dependências apontando para o centro. Uma referência típica seria:

  • Apresentação (UI)AplicaçãoDomínio
  • InfraestruturaAplicação

Ou seja, a UI depende da aplicação, que por sua vez depende do domínio. A infraestrutura, que implementa detalhes como o acesso ao banco de dados, também depende da aplicação, mas a aplicação nunca deve depender diretamente da infraestrutura.

Movendo o Contexto do Banco de Dados

Na arquitetura de 3 camadas, o contexto de banco de dados (ex. DbContext no Entity Framework) costuma estar na camada de acesso a dados. Em uma Arquitetura Limpa, o contexto de banco de dados deve ser movido para a Camada de Infraestrutura, pois trata-se de um detalhe de implementação. A lógica de negócios e as regras associadas ao comportamento do domínio permanecem na Camada de Domínio.

  • Infraestrutura: Implementa o DbContext, repositórios e quaisquer interações diretas com o banco de dados.
  • Domínio: Contém as entidades e objetos de valor (sem dependências de infraestrutura).

Implementando o Repositório

Na Camada de Aplicação, você define interfaces para os repositórios. Por exemplo, pode-se definir uma interface IProductRepository na camada de aplicação:

public interface IProductRepository
{
Task<Product> GetByIdAsync(int id);
Task<IEnumerable<Product>> GetAllAsync();
// Outros métodos...
}

A implementação concreta desta interface será feita na Camada de Infraestrutura. A inversão de dependência garante que a aplicação possa funcionar com qualquer implementação de repositório, tornando mais fácil mudar de um banco de dados SQL para NoSQL, por exemplo, sem alterar o restante do código.

public class ProductRepository : IProductRepository
{
private readonly ApplicationDbContext _context;

public ProductRepository(ApplicationDbContext context)
{
_context = context;
}

public async Task<Product> GetByIdAsync(int id)
{
return await _context.Products.FindAsync(id);
}

public async Task<IEnumerable<Product>> GetAllAsync()
{
return await _context.Products.ToListAsync();
}
}

Consumindo o Repositório na Camada de Aplicação

Uma vez que o repositório foi implementado na camada de infraestrutura, você pode consumi-lo na camada de aplicação por meio da injeção de dependência. A Camada de Aplicação deve depender apenas de interfaces, não de implementações concretas.

Exemplo de um caso de uso que consome o repositório:

public class GetProductByIdQueryHandler
{
private readonly IProductRepository _productRepository;

public GetProductByIdQueryHandler(IProductRepository productRepository)
{
_productRepository = productRepository;
}

public async Task<ProductDto> Handle(int productId)
{
var product = await _productRepository.GetByIdAsync(productId);
return new ProductDto(product);
}
}

Atualizando Nomes e Referências

Durante a migração, é crucial atualizar os nomes dos arquivos, namespaces e referências de projetos para seguir a nova organização. Isso inclui:

  • Renomear Data Access Layer (DAL) para Infraestrutura.
  • Atualizar a camada de negócio para ser a Aplicação, que define interfaces e casos de uso.
  • Verificar se o registro de serviços no Startup.cs (ou Program.cs) está correto, especialmente para a injeção de dependência entre as camadas.

Lembre-se de recompilar o projeto após cada modificação significativa para garantir que não haja erros ou referências quebradas.

Conclusão

Migrar de uma arquitetura de 3 camadas para uma Arquitetura Limpa pode parecer uma tarefa desafiadora no início, mas o processo pode ser simplificado ao seguir os princípios de inversão de dependência e separação clara de responsabilidades. A reorganização das camadas melhora a manutenibilidade do sistema, permitindo uma maior flexibilidade ao adicionar ou modificar funcionalidades no futuro.

Conteúdo Relacionado

Tillbaka till blogg

Lämna en kommentar

Notera att kommentarer behöver godkännas innan de publiceras.