No desenvolvimento de aplicativos em ASP.NET Core, lidar com múltiplos tipos de uma única entidade é um desafio comum. À medida que diferentes tipos de entidades surgem, com suas propriedades e regras de validação distintas, a estrutura do código pode se tornar complexa. Isso afeta a criação e manutenção de DTOs (Data Transfer Objects), validações e controladores.
Neste artigo, abordaremos as melhores práticas e padrões de design para gerenciar diferentes DTOs, otimizar validações, e organizar controladores ao lidar com múltiplos tipos de uma entidade. Vamos usar como exemplo o caso de uma entidade "Produto" com tipos variados, como produtos físicos e digitais.
Entendendo o Problema
Imagine que você está desenvolvendo um sistema de gerenciamento de produtos, onde cada produto pode ser classificado como Produto Físico ou Produto Digital. Cada um desses tipos possui propriedades específicas e regras de validação próprias.
-
Produto Físico: Propriedades como
Peso
,Dimensões
,Material
. -
Produto Digital: Propriedades como
Tamanho do Arquivo
,Formato
,Licença
.
Dado esse cenário, os problemas que podem surgir incluem:
- Gerenciamento de DTOs: Criar e manter DTOs distintos para cada tipo de entidade, adaptando as propriedades e as validações.
- Validações Complexas: Implementar validações específicas para cada tipo de produto sem tornar o código confuso.
- Controladores Sobrecarregados: Manipular diferentes tipos de produtos em um único controlador pode resultar em código bagunçado e difícil de entender.
Para evitar esses problemas, é necessário adotar uma abordagem organizada e sustentável.
Abordagem Limpa e Sustentável
Aqui estão algumas práticas recomendadas para lidar com múltiplos tipos de entidades em um projeto ASP.NET Core, garantindo clareza e manutenibilidade.
1. Utilização do Padrão de Projeto DTO
O padrão DTO separa a lógica de negócios da lógica de apresentação, sendo essencial quando lidamos com múltiplos tipos de entidade. Criar DTOs específicos para cada tipo de produto permite que apenas as propriedades e validações relevantes sejam incluídas.
Exemplo de DTOs para diferentes tipos de produtos:
public class ProdutoFisicoDTO {
public string Nome { get; set; }
public decimal Preco { get; set; }
public decimal Peso { get; set; }
public string Dimensoes { get; set; }
}
public class ProdutoDigitalDTO {
public string Nome { get; set; }
public decimal Preco { get; set; }
public long TamanhoArquivo { get; set; }
public string TipoMidia { get; set; }
}
Cada DTO é focado nas propriedades relevantes para o seu tipo de produto, garantindo uma separação clara entre os dados que estão sendo transferidos.
2. Aplicação de Validações Específicas
No ASP.NET Core, você pode utilizar anotações de dados (Data Annotations) para definir validações específicas para cada DTO. No caso de múltiplos tipos de entidades, isso permite aplicar regras customizadas sem poluir o código com validações desnecessárias.
Validações específicas em DTOs:
public class ProdutoFisicoDTO {
[Required]
public string Nome { get; set; }
[Range(0, 10000)]
public decimal Peso { get; set; }
[Required]
public string Dimensoes { get; set; }
}
public class ProdutoDigitalDTO {
[Required]
public string Nome { get; set; }
[Range(1, long.MaxValue, ErrorMessage = "Tamanho do arquivo deve ser positivo")]
public long TamanhoArquivo { get; set; }
[Required]
public string TipoMidia { get; set; }
}
Essas validações garantem que cada tipo de produto seja validado conforme suas necessidades, evitando a dispersão de regras por todo o código.
3. Controladores Específicos para Cada Tipo de Entidade
Uma boa prática ao lidar com múltiplos tipos de entidades é separar os controladores por tipo. Isso melhora a organização e clareza do código, facilitando a manutenção.
Em vez de usar um único controlador para gerenciar todos os tipos de produto, crie controladores específicos, como ProdutoFisicoController
e ProdutoDigitalController
.
Exemplo de controlador para ProdutoFisico
:
[ApiController]
[Route("api/[controller]")]
public class ProdutoFisicoController : ControllerBase {
[HttpPost]
public IActionResult CriarProduto([FromBody] ProdutoFisicoDTO produtoDTO) {
if (!ModelState.IsValid)
return BadRequest(ModelState);
// Lógica de criação de produto físico
return Ok("Produto físico criado com sucesso");
}
}
E um controlador para ProdutoDigital
:
[ApiController]
[Route("api/[controller]")]
public class ProdutoDigitalController : ControllerBase {
[HttpPost]
public IActionResult CriarProduto([FromBody] ProdutoDigitalDTO produtoDTO) {
if (!ModelState.IsValid)
return BadRequest(ModelState);
// Lógica de criação de produto digital
return Ok("Produto digital criado com sucesso");
}
}