Pular para o conteúdo

Valores e entidades

A distinção que decide metade da modelagem — e como cada lado é cobrado.

Duas pessoas com o mesmo nome são duas pessoas. E a mesma pessoa com outro nome continua sendo ela. O que separa uma entidade de um objeto de valor não é a mutabilidade — é a continuidade.

Objeto de valor#

dataforge
steady Dinheiro := D.valor("Dinheiro", ["quantia", "moeda"],
    regra := lambda v => v["quantia"] bigger_eq 0,
    motivo := "dinheiro nao e negativo")

dez := Dinheiro(10, "BRL")
outro := Dinheiro(10, "BRL")
assert dez is outro                  // o MESMO valor

vinte := dez.com(quantia := 20)      // outro valor; o original nao muda
assert dez.quantia is 10

O record da linguagem já dá a imutabilidade e a igualdade estrutural, e essas duas metades são a maior parte. O que ele não dá é a regra: um Dinheiro(-5, "BRL") é um record perfeitamente válido, e o negócio descobre isso três camadas adiante, num extrato negativo.

Uma regra que estoura não vira "valor inválido": ela vira um erro dizendo que a regra quebrou. Dizer "inválido" ali esconderia o defeito real, que é da regra e não do valor.

Entidade#

dataforge
ana := D.entidade("Pessoa", "1", nome := "Ana")
ana_maria := D.entidade("Pessoa", "1", nome := "Ana Maria")
homonima := D.entidade("Pessoa", "2", nome := "Ana")

assert ana is ana_maria       // mesma id, outro nome  -> a mesma pessoa
assert ana isnt homonima      // mesmo nome, outra id  -> duas pessoas

O identificador é texto, e nasce com o objeto (D.novo_id() dá um UUID4). Um id que o banco gera obriga a salvar antes de ter identidade — e no intervalo entre criar e confirmar o objeto existe sem ser ele mesmo.

E um valor não entra num repositório#

dataforge
D.repositorio("Dinheiro").guardar(Dinheiro(10, "BRL"))
// erro: o que vai para um repositorio precisa de identidade

Não é uma limitação: é a distinção sendo cobrada. Se a sua peça precisa distinguir duas instâncias iguais, ela é uma entidade — e o módulo diz isso em vez de deixar passar.