C# - Apresentando Value Object
Hoje vamos apresentar o conceito de Value Object usando a abordagem Domain Driven Design. |
Um Value Object é um tipo imutável que é distinguível apenas pelo estado de suas propriedades, ou seja, ele não possui uma identidade, e, de forma simples é óbvia, ele é um objeto que representa um valor.
Você entendeu ???
Aposto que não. E, eu não o culpo, para um primeiro contato pode ser confuso mesmo.
O que significa não possuir uma identidade ? O que é ser imutável ? O que é representar um valor ? E o que significa ser distinguível apenas pelo estado de suas propriedades ?
Vamos com calma.
Na linguagem C# podemos dizer que os tipos string e DateTime são exemplos de Value Objects.
Eles não possuem nenhuma identidade e são considerados iguais se suas propriedades são iguais e também são imutáveis.
Quando você cria um tipo string e a seguir aplica o método ToLower() para alterar a string, na verdade você cria uma nova instância da string.
A mesma coisa acontece quando você cria um tipo DateTime e aplica o método AddDays(1) ou outro método; você cria uma nova instância do tipo.
Nesses dois exemplos a instância original permanece inalterada e não importa a identidade do tipo, importa o seu valor.
Um exemplo clássico de Value Object que você vai encontrar na literatura é o dinheiro. Dinheiro é um exemplo de Value Object pois não nos importamos com a identidade da cédula ou moeda mas sim com seu valor.
Vejamos um pouco de código para clarear o entendimento...
A seguir temos uma classe Cliente :
Esta classe representa uma Entity ou Entidade e possui :
Esta classe não é imutável (definimos os get e set) e mesmo se eu criar dois objetos com valores iguais eles serão diferentes como mostra o código abaixo:
Vamos agora definir um Value Object seguindo as seguintes diretrizes:
Na classe Cliente estamos usando as propriedades Nome e Sobrenome como tipos string que requerem validação. (são chamados de tipos primitivos)
Podemos agrupar essas propriedades e criar um Value Object representando um composto que pode ser expresso por uma classe NomeCompleto com duas propriedades Nome e Sobrenome:
Agora confira:
Você acabou de criar o seu primeiro Value Object.
Assim, você até poderá substituir as propriedades Nome e Sobrenome que são do tipo strings pelo Value Object NomeCompleto na classe Cliente:
Agora nossa Entity representada pela classe Cliente possui uma identidade definida pelo Id, uma propriedade Email do tipo string e um Value Object que acabamos de criar : NomeCompleto.
O estado referente a nome e sobrenome agora é passado no construtor parametrizado como um objeto de valor.
As propriedades são somente leitura (somente get) e isso torna possível fazer a validação para o email.
Nosso cliente esta definido como imutável, mas ele não precisa ser imutável. Em uma base de código real, a classe Cliente deve encapsular sua própria lógica de domínio. Isso torna mais fácil proteger a entidade de um estado inválido.
Com isso temos que as validações são definidas apenas no Value Object e podemos reutilizá-lo em todo o nosso projeto.
Você já deve ter percebido que poderíamos criar outro Value Object para Email. E como podemos usar esse valor para verificar se dois objetos são iguais teríamos que sobrescrever o método Equals de forma a identificar cada objeto comparando os Emails pelo seu valor.
Nota: Como os Value Objects carecem de identidade, eles podem ser comparados com base em seu estado coletivo. Se todas as propriedades forem iguais, então dois Value Objects podem ser considerados iguais. (Igual aos tipos de string.)
Mas creio que você já entendeu o conceito de Value Objects e qual a diferença para uma Entity.
Obs: Com a implementação do tipo Record no C# 9.0 teremos uma valiosa ferramenta para implementar Value Objects com mais facilidade.
Assim podemos considerar o uso de Value Objects como uma técnica que pode tornar o seu código mais legível e fácil de manter.
Pegue o projeto completo aqui: CShp_ValueObjects.zip
"Porque, como o
relâmpago ilumina desde uma extremidade inferior do céu até à outra extremidade,
assim será também o Filho do homem no seu dia."
Lucas 17:24
Referências:
C# - Tasks x Threads. Qual a diferença
VB .NET - Datas, horas: conceitos e operações
C# - Programação Assíncrona como : Asycn e Task
O tratamento de datas no VB.NET
C# - Obtendo a data e a hora por TimeZone
C# - O Struct Guid - Macoratti.net
Formatação de data e hora para uma cultura
C# - Calculando a diferença entre duas datas
C# - Fundamentos : Definindo DateTime como Null
ASP .NET Core - Usando conceitos do DDD - Macoratti.net
Domain Driven Design - Área de Aplicação - Macoratti.net