Entidades vs Objeto de Valor

Nunca se falou tanto sobre Domain-Driven-Design (DDD) como se fala atualmente, mesmo sabendo que este assunto não é algo novo, mas ainda que não seja novo, é Atemporal em se tratando de implementação de negócio. Tenho trabalhado em alguns projetos e sempre encontro muita gente falando que aplica os conceitos do DDD, mas quando começo a conversar com o time que está "supostamente" usando DDD, é o momento que começo a identificar as famosas falhas, não só de aplicação dos conceitos básicos do DDD, como também:

  • Identificar os usuários chaves;
  • Extrair dos usuários chaves, o entendimento do negócio;
  • Identificar os Contextos Delimitados (Bounded Context);
  • Identificar como os contextos se comunicam;
  • Identificar qual é a Linguagem Ubuíqua (Ubiquitous Language - UL);
  • Identificar o que pode se tornar, potencialmente uma Entitidade ou Objeto de Valor.

Existem muitos conceitos, premissas e orientações que o DDD tem à nos oferecer com o objetivo de conseguirmos alcançar um código fiel ao negócio, e que seja:

  • Confiável;
  • Representativo;
  • Reutilizável.

No artigo de hoje, vou abordar algumas técnicas que te auxiliarão na identificação de Entidades e Objetos de Valor. Mesmo que você já conhece algumas formas de identificaçao desses tipos, continue lendo este artigo! Quem sabe você pode encontrar uma forma diferente, sobre o que, habitualmente, você implementa.

Entidades vs Objeto de Valor

Tipos de comparação

Igualdade por Identificador (Identifier Equality)

Essa tipo de implementação, permite que seja possível identificar uma instância de uma entidade com uma outra instância, através de seus Identificadores. O que nós conhecemos por Id. Ou seja, duas instâncias são exatamente iguais, quando ambas possuem o mesmo valor em seus respectivos Identificadores, Id.

Igualdade por Referência (Reference Equality)

O tipo de comparação por Referência, permite que o julgamento de igualdade entre duas instâncias, seja feito através do valor de suas respectivas referências em memória.

Igualdade Valor Estrutural (Structural Equality)

O tipo de comparação estrutural, é o que torna um objeto de valor ser o que ele é, ou seja, um Objeto IMUTÁVEL. Para que esse tipo de comparação tenha validade, TODAS as propriedades desse tipo de classe, precisam ser exatamente IGUAIS.

Você pode perceber num primeiro instante que Entidades e Objetos de Valor podem ser comparados da mesma forma. Mas NÃO. A grande diferença entre esses dois tipos de objetos, dentro da abordagem Tática do Domain-Driven-Design é a forma de comparação entre eles. O tipo de comparação por Identificador pertence, exclusivamente, as Entidades. Enquanto que o tipo de comparação estrutural pertecen aos Objetos de Valor.

Imagine que você está morando no endereço: Rua comandante alvarez, Vila Mariana (bairro), São Paulo (Cidade), SP (Estado), 01542-102 (Cep). Amanhã você conhece um novo colega de trabalho que, por coincidência da vida, tem em seu registro de funcionário da empresa, um endereço com os mesmos dados. Ou seja: Rua comandante alvarez, Vila Mariana (bairro), São Paulo (Cidade), SP (Estado), 01542-102 (Cep). Isso quer dizer que o objeto de valor: Endereco, é o mesmo para ambos os funcionários.

Tempo de Vida

Uma Entidade, além de possuir um Identificador, possui o seu tempo de vida dentro do dominio. Toda entidade, possui acontecimentos que houveram em seu ciclo de existência, ou seja, as Entidades tem uma história de vida.

Quanto aos Objetos de Valor, esses não possuem nenhum tipo de vinculo com o ciclo de vida do dominio ou aplicação. Todo e qualquer objeto de valor, devido sua Imutabilidade (tema abordado no próximo tópico abaixo), podem ser destruídos e criados novamente.

A grande questão que guia a distinção de existência entre uma Entidade e um Objeto de Valor, é que um OV não tem vida própria, ou seja, sua existência depende essencialmente a existência de uma ou mais entidades.

Desta forma, você pode entender um OV como sendo uma representação de valor que pertence à apenas a classe que este está vinculado. Como por exemplo: Quando você está preenchendo o formulário de contratação em um novo emprego, qual a pergunta que normalmente você precisa preencher, dentre várias? Onde você mora? Ou seja, Qual é o seu ENREDEÇO. Neste caso, Endereço é um objeto de valor de uma classe Funcionário, por exemplo.

Imutabilidade

Imutabilidade é uma das características mais marcantes da implementação de um Objeto de Valor. Mas o que vem a ser o conceito de Imutabilidade?

Como o próprio nome já diz por si, Imutabilidade é a capacidade do objeto de valor não permitir a alteração dos valores de suas propriedades, até que um novo objeto seja criado e receba novos dados em seu construtor.

Questione-se: O meu suposto Objeto de Valor necessita mudar seu estado e seus valores. Se Sim, ele não é um Objeto de Valor. Lembre-se: Um Objeto de Valor, NÃO pode permitir que seus valores sejam alterados para a mesma instância.

Encontrando cada uma das peças: Entidade e Objetos de Valor

Essa parte de identificação de entidades não é sempre uma tarefa fácil de conclusão. Dado que o seu dominio vive em constante mudança, devido a necessidade de adaptação ao negócio que está sendo moldado e traduzido em código; Identificar o que é uma Entidade e o que é um Objeto de Valor nem sempre será tão claro, num primeiro instante de análise.

No caso que citamos acima, onde temos uma classe "Funcionário" e uma outra classe chamada "Endereco", é claro observar que um Funcionário em uma empresa ele tem:

  • Ciclo de Vida (Contratado/Dispensado)
  • História (Promoções, Férias)
  • Identificação (Id)

Além de tudo que citamos acima, um Funcionário também tem um: Endereco. Vamos supor que esse funcionário tenha um tempo de permanência dentro da empresa de 10 anos, e que dentro desses 10 anos, aconteceram 3 mudanças de endereço desta mesma pessoa. O que aconteceu com o Endereco? Foi possível mudar suas propriedades? NÃO! Dentro do dominio, o que aconteceu foi a substituição da referência de Endereco Antiga para uma Nova Instância de Endereco, contendo os novos dados do endereco do Funcionário.

Uma técnica que eu costumo usar é comprar um Objeto de Valor com um tipo primitivo, por exemplo: string. Quando eu estou comparando um Endereco, eu estou comparando vários atributos do tipo String e uma do tipo Integer (int). O que me faz perceber que, se eu permaneço com uma classe como no exemplo abaixo:

É notório a necessidade de comparação dentre as strings que correspondem a representação de Endereco. Ou seja, apartir dessa caracteristica e semelhança com tipos primitivos, levando-se em consideração o fator de imutabilidade e o reuso, surge a necessidade de criação de um Objeto de Valor: Endereco.

Agora que já consigo identificar a diferença entre uma Entidade e um Objeto de Valor, também já compreendi quais são os tipos de comparação entre eles... E como tudo isso fica para persistir no banco de dados?

Abordagem para modelar seu objeto com o banco de dados

Essa é uma questão que gera bastante discussão para que está começando a implementar DDD em seus projetos e, até mesmo, para àqueles que já tem alguma vivência e implementar novas técnicas de codificação em seus projetos. Vamos quebrar alguns paradigmas? Vamos utilizar o mesmo cenário de exemplo:Funcionário (Entidade) e Endereço (Objeto de Valor).

A forma mais comum e usual de persitência de dados, que mais encontramos em projetos que participamos, ainda é o famoso: Banco de dados RELACIONAL. E é nesse momento que começam a aparecer alguns problemas de modelagem de dados e que dificulta a implementação do DDD ou até mesmo, inviabiliza o projeto, em alguns casos, devido ao modelo mental de normalização de dados que usamos durante anos.

Habitualmente, a modelagem de dados que logo nos vem a mente é criar uma tabela "Funcionario", adicionar um campo EnderecoId e relacionar esse campo com uma outra tabela chamada: "Endereco". Conforme a imagem abaixo:

Para um modelo de dados e implementação de dados, pura e simplesmente, a imagem acima representa uma modelagem válida, para o cenário de base de dados. Contudo, há alguns pontos que não se encaixam bem com uma modelagem de domínio.

Se você observar, na tabela "Endereco" existe um campo Id, o que obrigatia o meu Objeto de Valor a possuir um Identificador, ou seja, eu precisaria implementar um atribuito Id dentro do meu Objeto de Valor. Com isso, eu começo a ferir a definição de um OV.

Outro ponto de atenção e extremamente importante, não só para o dominio, mas também para a consistência de dados do banco de dados, é que imagine que eu continue com esta modelagem de dados, o sistema está funcionando em perfeito estado, até que eu decida EXCLUIR um funcionário da minha empresa (supondo que o negócio permita esse tipo de ação em um funcionário), Vamos pensar o que aconteceria com o funcionário e Endereço? O funcionário seria excluído da base de dados, e o Endereço? Caso não tenha sido deletado, ficaria órfão dentro da base de dados, o que causaria outra violação sobre o tempo de vida de um objeto de valor que depende diretamente do tempo de vida da entidade que o possui, no caso o "Funcionario".

Pare resolver o cenário de relacionamentos entre várias tabelas, a imagem abaixo apresenta uma modelagem que representa o dominio da aplicação:

Campos do objeto de valor na mesma tabela

A solução para a modelagem de dados apresentada na imagem acima, resolve a o problema causado pela primeira forma de modelagem, ou seja, garantindo que o tempo de vida de um objeto de valor será o mesmo tempo de vida que a Entidade que o possui.

Dica: NÃO CRIE TABELAS SEPARADAS PARA OBJETOS DE VALOR

Conclusão

Entidades

  • Possuem Identificadores;
  • Possuem ciclo de vida, hisórias e acontecimentos;
  • São comparadas por Identificadores ou Referência.

Objetos de Valor

  • Não possuem Identificadores;
  • A existência Depente da Entidade que o possui, ou seja, não tem vida própria;
  • São Imutáveis
  • Para reconhecer um OV, tente compará-lo com um tipo primitivo: string, por exemplo;
  • Não possuem suas próprias tabelas.

Comments