O encapsulamento, um princípio fundamental da programação orientada a objetos, tem sido amplamente adotado como uma forma de estruturar e organizar o código-fonte. No entanto, além de sua utilidade em termos de modularidade e segurança/ocultação do código, o encapsulamento também pode desempenhar um papel crucial no desenvolvimento de um domínio rico.
Normalmente, ao desenvolver uma aplicação, quando iniciamos a modelagem de dados utilizando .NET, tendemos a criar inicialmente um domínio anêmico. Domínio anêmico refere-se à prática de listar apenas as propriedades com os métodos get e set.
Exemplo SEM utilizar encapsulamento:
public class Pedido { public int Id { get; set; } public DateTime DataCriacao { get; set; } public decimal ValorTotal { get; set; } } public class PedidoService { public void AplicarAcrescimo(Pedido pedido, decimal percentualAcrescimo) { decimal valorAcrescimo = pedido.ValorTotal * (percentualAcrescimo / 100); pedido.ValorTotal += valorAcrescimo; } } public class Program { public static void Main(string[] args) { Pedido pedido = new Pedido { Id = 1, DataCriacao = DateTime.Now, ValorTotal = 100.0m< }; PedidoService pedidoService = new PedidoService(); Console.WriteLine("Valor total antes do acréscimo: " + pedido.ValorTotal); pedidoService.AplicarAcrescimo(pedido, 30); Console.WriteLine("Valor total após o acréscimo: " + pedido.ValorTotal);< } }
Mas qual é a relação do encapsulamento com isso?
Em programação orientada a objetos, o encapsulamento tem o objetivo de proteger a classe, assegurando suas informações e evitando que suas propriedades sejam alteradas indevidamente. Portanto, o principal objetivo desse princípio é utilizar os getters e setters de forma segura.
Agora, se considerarmos a combinação desses dois conceitos, o domínio anêmico, que expõe os métodos get e set publicamente, vai contra o objetivo do encapsulamento. Porém, é possível alcançar um domínio rico, no qual o modelo possui métodos públicos que executam ações baseadas em suas propriedades privadas. Isso acontece porque ninguém além da própria classe tem acesso direto aos dados, e apenas métodos são expostos externamente.
Essa abordagem substitui a necessidade de utilizar métodos em serviços que fazem comparações ou verificam a existência de dados, por exemplo, evitando modificações indevidas ao ter um setter público. Todas as regras, filtros e comparações relacionados à classe são mantidos dentro do seu próprio domínio.
Exemplo utilizando encapsulamento resultando em um domínio rico:
public class Pedido { public int Id { get; private set; } public DateTime DataCriacao { get; private set; } private decimal valorTotal; public decimal ValorTotal { get { return valorTotal; } set { valorTotal = value; } } public Pedido(int id, DateTime dataCriacao, decimal valorTotal) { Id = id; DataCriacao = dataCriacao; this.valorTotal = valorTotal; } public void AplicarAcrescimo(decimal percentualAcrescimo) { decimal valorAcrescimo = valorTotal * (percentualAcrescimo / 100); valorTotal += valorAcrescimo; } } public class Program { public static void Main(string[] args) { Pedido pedido = new Pedido(1, DateTime.Now, 100.0m); Console.WriteLine("Valor total antes do acréscimo: " + pedido.ValorTotal); pedido.AplicarAcrescimo(30); Console.WriteLine("Valor total após o acréscimo: " + pedido.ValorTotal); } }
Em conclusão, o encapsulamento pode, de fato, resultar em um domínio rico. Ao ocultar os detalhes de implementação e fornecer uma interface clara e bem definida, o encapsulamento promove a modularidade e a separação de preocupações. Isso permite que os desenvolvedores se concentrem no comportamento e nas interações dos objetos, levando a um código mais legível, compreensível e facilmente mantido.