Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Ola galera
Tenho pesquisado muito sobre este assunto na internet, e durante estas pesquisa descobri que uma Entidade possui uma identidade, já o Value Object não possui uma identidade. Queria saber isso na prática(no código) como seria essa "identidade" no decorrer de um projeto, agradeço desde já
Atributos definem um estado e são mutáveis. Identidade não é mutável, é única.
Entretanto, um ValueObject (VO) tem seu estado, de certa forma, imutável. Toda a vez que você tentar alterar o estado de um VO, você receberá uma nova instância do mesmo objeto com o seu novo estado.
Você deve entender que Entity e ValueObject são padrões de estrutura. A Entity é utilizada para definir um object de negócio normalmente, não sempre, associado a um storage.
Já o ValueObject, tem como intuito impedir a cópia por referência. O que normalmente ocorre com objetos que representam dinheiro ou hora.
Por exemplo:
function showNextDay(\DateTimeInterface $dateTime) {
$dateTime->add(new \DateInterval('P1D'));
echo $dateTime->format('d/m/Y');
}
Uso:
$now = new \DateTime();
echo $now->format('d/m/Y');
showNextDay($now);
echo $now->format('d/m/Y');
Saída:
22/09/2015
23/09/2015
23/09/2015 //Valor alterado pela referência
Agora, utilizando um ValueObject (é necessária alterar a implementação da function showNextDay():
function showNextDay(\DateTimeInterface $dateTime) {
echo $dateTime->add(new \DateInterval('P1D'))->format('d/m/Y');
}
Uso:
$now = new \DateTimeImmutable();
echo $now->format('d/m/Y');
showNextDay($now);
echo $now->format('d/m/Y');
Saída:
22/09/2015
23/09/2015
22/09/2015
Depois percebi que esqueci de mencionar sobre a identidade.
A diferença entre ambos, sobre identidade, é a forma para se verificar que um objeto é igual ao outro.
Em um Entity, pode ser usado '===' normalmente. Mas em um ValueObject, essa abordagem não funciona.
Entretanto, utilizando o exemplo de dinheiro, R$ 5,00 são tão bons, e iguais, quanto qualquer outros R$ 5,00. Ou seja, uma nota de R$ 5,00 é tão bom quanto 5 moedas de R$ 1,00 (isso em questões de valores, não vamos considerar peso/volume :lol: )
Então veja só:
<?php
class Money {
private $value;
/**
* @param int|float
**/
public function __construct($value) {
if(!is_numeric($value)) {
throw new \UnexpectedValueException('Only numeric values are accepted');
}
$this->value = $value;
}
public function getValue() {
return $this->value;
}
public function add(\Money $money) {
return new self($this->getValue() + $money->getValue());
}
public function remove(\Money $money) {
return new self($this->getValue() - $money->getValue());
}
public function isEqual(\Money $money) {
return (boolean)($this->getValue() == $money->getValue());
}
}
Temos nossa classe Money implementada, vamos ao seu uso:
$money = new Money(5.00);
$cofrinho = new Money(0);
$cofrinho100 = $cofrinho->add(new Money(1));
$cofrinho150 = $cofrinho100->add(new Money(0.50));
$cofrinho300 = $cofrinho150->add(new Money(1.50));
$cofrinho500 = $cofrinho300->add(new Money(2.00));
var_dump($money == $cofrinho);//False, não possuem o mesmo estado
var_dump($money == $cofrinho500);//True, possuem o mesmo estado
var_dump($money === $cofrinho);//False, não são os mesmos objetos
var_dump($money === $cofrinho500);//False, não são os mesmos objetos
var_dump($money->isEqual($cofrinho500));//True
Assim, como na vida real, quando você "junta" o dinheiro, você não deixa de ter o dinheiro original (quantidade/valores de notas e/ou moedas), mas possui um novo montante.
Obrigado pelas explicações @rnu.silva, @Gabriel Heming
Gabriel perfeito o seus exemplos, entendi perfeitamente. Mas só uma dúvida você falou que nos padrões value objects, o que importa e o seu estado(os seus atributos) né?! então se caso o dinheiro tivesse outro atributo chamado de "tipo_de_material"(papel, moeda e etc..), nesse caso um montante de R$5,00 de papel seria diferente de um montante de R$5,00 de moeda, certo?
Não, o montante de R$ 5,00 é igual em qualquer tipo físico (ou digital). Se eu adicionasse o atributo de tipo, o método isEqual deve considerar apenas o valor.
Dessa forma, o '==' passaria a ser false (em alguns casos) e apenas o isEqual seria parâmetro para comparação.
Apesar de possuirem estados diferente, economicamente falando, R$ 5,00 em moedas são tão bons quanto qualquer outros R$ 5,00.
Muito obrigado pela ajuda Gabriel
Eu entendo que a identidade de uma Entidade seja o conjunto dos atributos utilizados no mundo virtual.
Ex: no mundo real temos a Entidade carro, com os seguintes atributos: cor, ano, modelo, potencia, etc...
No mundo virtual temos para esta Entidade, uma identidade com estes atributos de forma literal.
Carro
string cor
int ano
string modelo
os objetos são frutos dessas identidades, uma vez que cada objeto é originário de uma classe que possui tais atributos.
Ex: a classe carro pode gerar n's carros com valores distintos em seus atributos
carro1
cor vermelha
ano 2001
modelo gol
carro2
cor azul
ano 2015
modelo celta
etc..