<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Meriéli Manzano</title>
    <description>The latest articles on DEV Community by Meriéli Manzano (@merielimanzano).</description>
    <link>https://dev.to/merielimanzano</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F905006%2F77d91549-141c-41e3-9e92-bb7cc00ebed4.png</url>
      <title>DEV Community: Meriéli Manzano</title>
      <link>https://dev.to/merielimanzano</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/merielimanzano"/>
    <language>en</language>
    <item>
      <title>Dos fundamentos à prática: como construir Entidades ricas de verdade</title>
      <dc:creator>Meriéli Manzano</dc:creator>
      <pubDate>Thu, 11 Jun 2026 16:33:23 +0000</pubDate>
      <link>https://dev.to/merielimanzano/dos-fundamentos-a-pratica-como-construir-entidades-ricas-de-verdade-9jm</link>
      <guid>https://dev.to/merielimanzano/dos-fundamentos-a-pratica-como-construir-entidades-ricas-de-verdade-9jm</guid>
      <description>&lt;p&gt;Você já deve ter ouvido a palavra entidade em diferentes contextos no desenvolvimento de software. No banco de dados, uma entidade é quase uma linha numa tabela. No ORM (ferramenta que converte tabelas do banco em objetos), é uma classe cheia de getters e setters.&lt;/p&gt;

&lt;p&gt;Mas quando falamos de Domain-Driven Design (DDD) — uma abordagem para modelar software complexo focando no negócio — o significado é bem mais específico. E é sobre ele que vamos conversar hoje, sem complicação.&lt;/p&gt;

&lt;p&gt;Imagine que você está construindo um sistema de matrículas para uma escola. No começo, você faz o simples, cria uma classe Aluno com nome, email e cpf e guarda numa tabela. Para alterar o e-mail, você faz:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$student&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"new@email.com"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$student&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tudo funciona mas com o tempo, os pedidos mudam:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ao trocar de e-mail, é preciso registrar essa alteração para auditoria.&lt;/li&gt;
&lt;li&gt;Um aluno não pode se matricular se já tiver outro com o mesmo CPF ativo.&lt;/li&gt;
&lt;li&gt;Quando o aluno muda de nome, precisa enviar uma notificação para a secretaria.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Você tenta colocar essas regras nos controllers (camada que recebe requisições HTTP) ou nos services (camada de orquestração). O resultado? O código começa a se repetir com validação de CPF que aparece em três lugares diferentes; a lógica de notificação que se perde entre uma requisição e outra; o Aluno que vira um simples saco de dados, e qualquer parte do sistema pode deixá-lo em um estado inválido (por exemplo, um aluno ativo com CPF vazio).&lt;/p&gt;

&lt;p&gt;Essa dor tem nome: &lt;strong&gt;Modelo Anêmico&lt;/strong&gt;. É quando a classe tem apenas propriedades (atributos) e nenhum comportamento (métodos com regras de negócio). O sistema fica frágil, espalhado e difícil de mudar. É justamente isso que a Entidade do DDD resolve. Ela coloca a identidade e as regras dentro do próprio objeto, protegendo a consistência do negócio.&lt;/p&gt;

&lt;p&gt;No DDD, uma Entidade é um objeto com identidade própria (um ID único). Ela muda ao longo do tempo, mas continua sendo a mesma por causa dessa identidade. Ela contém &lt;strong&gt;atributos&lt;/strong&gt; (dados) e &lt;strong&gt;comportamentos&lt;/strong&gt; (regras de negócio) que garantem sua validade e evolução.&lt;/p&gt;

&lt;p&gt;Pense em uma pessoa. Ela nasce, troca de nome ao casar, muda de endereço várias vezes, talvez até de cor do cabelo. Apesar de todas essas mudanças, essa pessoa continua sendo ela mesma — sua identidade (documento, biometria, história) é o que a define. Uma empresa também: pode mudar de sede, de sócios, de produto principal, mas o CNPJ e a razão social permanecem. No software, a Entidade é exatamente isso: algo que reconhecemos pela identidade, e não pelos seus dados momentâneos.&lt;/p&gt;

&lt;p&gt;Abaixo um exemplo em PHP. Repare que não há set público solto — as mudanças acontecem por métodos nomeados com a intenção do negócio.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Generic base class for all Domain Entities&lt;/span&gt;
&lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Entity&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Entity&lt;/span&gt; &lt;span class="nv"&gt;$other&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nv"&gt;$other&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Concrete Student entity&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Student&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Entity&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nv"&gt;$active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$cpf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$email&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;changeEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$newEmail&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;str_contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$newEmail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'@'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;\InvalidArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Invalid email"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// Could register an "EmailChanged" event for audit here&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$newEmail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;deactivate&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;// Notify the registrar, etc.&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getEmail&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getName&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getCpf&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cpf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Como usar:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$student&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Student&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"111.222.333-44"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"João"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"joao@mail.com"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$student&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;changeEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"joao.novo@mail.com"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// valid&lt;/span&gt;
&lt;span class="nv"&gt;$student&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;deactivate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// $student-&amp;gt;email = "any" → error (private property, no public setter)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perceba: a &lt;strong&gt;identidade&lt;/strong&gt; é o id (passado no construtor). O objeto muda (&lt;code&gt;email&lt;/code&gt; e &lt;code&gt;active&lt;/code&gt;), mas o &lt;code&gt;id&lt;/code&gt; nunca muda. As regras de negócio ficam dentro da própria classe, não espalhadas.&lt;/p&gt;

&lt;p&gt;Exemplos de entidades são: Curso, Aula, Usuário, Progresso, Discussão, Anexo, Tutor, Post, Certificado, Produto, etc.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Não devemos focar o domínio no banco de dados! Há uma propensão de desenvolvedores focarem dados em vez de domínio. Isso pode ocorrer devido a abordagens que colocam a importância no banco de dados. Em vez de projetar conceitos de domínio com comportamentos ricos, pensam principalmente em atributos “colunas” e associações/relacionamentos “chaves estrangeiras”.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;em&gt;Você está projetando pensando em colunas ou em comportamentos de negócio? Pare e reflita: sua classe principal tem regras ou só getters?&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Com o tempo, o sistema se torna uma "&lt;em&gt;Big Ball of Mud&lt;/em&gt;". Essa expressão descreve um software com estrutura indefinida, cheio de dependências emaranhadas. É impossível prever o efeito de uma alteração. As regras de negócio ficam espalhadas por controllers, serviços e até helpers, tornando o sistema frágil e difícil de evoluir. Para converter um modelo anêmico em uma entidade rica (com comportamento), siga estes passos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Remova todos os setters públicos&lt;/strong&gt; da classe. Nenhuma propriedade poderá ser alterada diretamente de fora.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identifique os motivos de mudança&lt;/strong&gt; no negócio (ex: “cancelar pedido”, “aprovar pagamento”, “alterar e-mail do aluno”).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crie métodos públicos nomeados com esses verbos&lt;/strong&gt; (ex: cancelar(), aprovarPagamento(), alterarEmail($novoEmail)). Cada método deve conter as validações e regras necessárias, além de alterar o estado interno.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mova para dentro desses métodos&lt;/strong&gt; toda a lógica que antes estava em serviços ou controllers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proteja a criação&lt;/strong&gt; – use um construtor que exija os dados mínimos para a entidade existir em um estado válido (incluindo o ID de identidade).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ao seguir esses passos, você perceberá que a entidade deixa de ser um mero recipiente de dados. Ela passa a expressar, por si mesma, as regras do negócio. É aqui que alcançamos o verdadeiro propósito do DDD - ter uma entidade validada na aplicação. Isso significa que, se a entidade já existe (ou seja, foi construída respeitando suas invariantes), automaticamente ela já é válida. Você não precisa espalhar validações pelo sistema para garantir sua consistência. E mais, comportamentos ricos dentro da entidade expandem sua capacidade de evoluir sem quebrar o mundo lá fora.&lt;/p&gt;

&lt;p&gt;Esse é o coração do que chamamos de &lt;strong&gt;Modelo Rico&lt;/strong&gt;: um modelo que tem os atributos e os comportamentos, ou seja, os métodos que implementam as regras de negócio. Uma &lt;strong&gt;Entidade no DDD&lt;/strong&gt; não é teoria distante — é uma ferramenta prática para acabar com a bagunça do modelo anêmico e da &lt;em&gt;Big Ball of Mud&lt;/em&gt;. A diferença entre um sistema que só armazena dados e um que expressa o negócio está exatamente aí: nas classes que protegem sua própria identidade e evolução.&lt;/p&gt;

&lt;p&gt;Agora, pare por um momento e olhe para a classe mais crítica do seu projeto atual. Ela tem comportamento ou é só um saco de getters e setters? Se for a segunda opção, você já tem um candidato perfeito para aplicar os cinco passos que vimos.&lt;/p&gt;

&lt;p&gt;Não precisa refatorar tudo de uma vez. Comece pequeno: remova um setter, crie um método com nome de verbo do negócio, mova uma validação para dentro da entidade. O efeito é imediato: testes ficam mais claros, bugs diminuem e seu time volta a conversar sobre regras de negócio, não sobre colunas de banco.&lt;/p&gt;

&lt;p&gt;Dê identidade e comportamento à sua próxima Entidade. Você vai sentir a diferença na primeira regra de negócio que deixar de se repetir. Abra o código e comece agora!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Até a próxima galerinha.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>cleancode</category>
      <category>php</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Dê significado aos seus dados: Objetos de Valor na prática</title>
      <dc:creator>Meriéli Manzano</dc:creator>
      <pubDate>Thu, 28 May 2026 20:29:58 +0000</pubDate>
      <link>https://dev.to/merielimanzano/de-significado-aos-seus-dados-objetos-de-valor-na-pratica-1a0p</link>
      <guid>https://dev.to/merielimanzano/de-significado-aos-seus-dados-objetos-de-valor-na-pratica-1a0p</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Pare de usar string para tudo e comece a expressar suas regras de negócio com clareza e segurança&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Você já se pegou repetindo as mesmas validações de CPF, e-mail ou telefone em várias partes do sistema? Sentiu que seus modelos de domínio estão anêmicos, cheios de getters e setters, mas sem comportamento real? Se sim, é hora de conhecer o verdadeiro poder dos &lt;strong&gt;Objetos de Valor&lt;/strong&gt; &lt;em&gt;(Value Objects)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Neste artigo, vamos mergulhar fundo nesse conceito transformador. Você vai entender por que Objetos de Valor garantem consistência, eliminam duplicação e tornam seu código mais expressivo e seguro. Prepare-se para elevar o nível da sua modelagem de domínio!&lt;/p&gt;

&lt;p&gt;Imagine um CPF: &lt;code&gt;123.456.789-00&lt;/code&gt;. O que importa é o número em si, não uma identidade única que o acompanhe. Se dois CPFs têm o mesmo número, eles são &lt;strong&gt;iguais&lt;/strong&gt; – não importa se foram instanciados em momentos diferentes ou em lugares distintos. Essa é a alma do Objeto de Valor.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Definição:&lt;/strong&gt; Um Objeto de Valor é um tipo de classe que representa um conceito abstrato, sem identidade própria (não possui ID). Ele é definido apenas por suas propriedades, encapsulando dentro de si um ou mais valores e suas respectivas regras de negócio.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Características fundamentais:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Imutável:&lt;/strong&gt; uma vez criado, nunca muda. Para alterar, cria-se uma nova instância.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comparado por atributos:&lt;/strong&gt; dois Value Objects são iguais se todos os seus atributos forem iguais.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-validado:&lt;/strong&gt; ao ser instanciado, já garante que o valor é consistente com as regras do domínio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Exemplos clássicos:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPF, CNPJ, CEP, telefone&lt;/li&gt;
&lt;li&gt;Endereço (composto por logradouro, número, cidade, CEP)&lt;/li&gt;
&lt;li&gt;Email, senha hash, duração de tempo, preço, nome próprio, cor, moeda&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Por que priorizar Objetos de Valor?
&lt;/h2&gt;

&lt;p&gt;Muitos desenvolvedores, quando pensam em DDD, correm imediatamente para as Entidades. Mas o próprio Eric Evans traz uma orientação poderosa:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Devemos nos esforçar para modelar utilizando Objetos de Valor, em vez de Entidades, sempre que possível. Mesmo quando um conceito de domínio precisa ser modelado como uma Entidade, o projeto da Entidade deve favorecer o uso de um contêiner de valores, em vez de um contêiner de Entidades filho.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Isso significa que o primeiro local para armazenar nossas regras de negócio é no Objeto de Valor, e por isso uma Entidade precisa compor Objetos de Valor, evitando ter Entidades dentro de Entidades.&lt;/p&gt;

&lt;p&gt;Os benefícios do Objeto de Valor são enormes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reuso imediato: Um Email ou CPF pode ser usado em qualquer lugar (Usuário, Cliente, Fornecedor) sem repetir regras.&lt;/li&gt;
&lt;li&gt;Código mais expressivo: Em vez de string $email, temos Email $email. O tipo já revela a intenção e as restrições.&lt;/li&gt;
&lt;li&gt;Testabilidade facilitada: Testar as regras de um Value Object isolado é trivial.&lt;/li&gt;
&lt;li&gt;Imutabilidade e segurança: Sem side-effects; objetos podem ser compartilhados sem risco.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mesmo que seu projeto não adote formalmente o DDD (Domain-Driven Design, uma abordagem que coloca o negócio e seu vocabulário no centro do código), usar objetos de valor vale a pena porque eles eliminam a duplicação de validações e garantem consistência em qualquer arquitetura.&lt;/p&gt;

&lt;p&gt;Se até aqui você já aprendeu algo, compartilhe este artigo com quem precisa de mais consistência e menos duplicação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sinal de alerta para extrair um Value Object
&lt;/h2&gt;

&lt;p&gt;Quando você perceber várias classes com os mesmos atributos (ex.: &lt;code&gt;string $cpf&lt;/code&gt;, &lt;code&gt;string $email&lt;/code&gt;, &lt;code&gt;string $telefone&lt;/code&gt;), cada uma validando do seu próprio jeito, é um forte indicativo de que esses atributos merecem se tornar Objetos de Valor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Objetos de Valor vs Entidades: quando usar cada um?
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Entidades
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identidade:&lt;/strong&gt; Possui um ID único que a rastreia ao longo do tempo e o que a distingue de outras entidades.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mutabilidade:&lt;/strong&gt; Mutável (seus atributos podem mudar, mas a identidade permanece).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Igualdade:&lt;/strong&gt; Comparação por identidade (ID)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exemplos de uso:&lt;/strong&gt; Pessoa, Pedido, Conta Bancária, Produto&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Objetos de Valor
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identidade:&lt;/strong&gt; Não tem identificador único; é definido por seus atributos ou por seu valor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mutabilidade:&lt;/strong&gt; Imutável.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Igualdade:&lt;/strong&gt; Comparação estrutural (todos os atributos/valores).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exemplos de uso:&lt;/strong&gt; CPF, Email, Endereço, Cor, Dinheiro&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Construindo um Value Object na Prática
&lt;/h2&gt;

&lt;p&gt;Vamos implementar um &lt;code&gt;Email&lt;/code&gt;, usando uma classe abstrata genérica para reaproveitar o método equals e definir por padrão o $value como readonly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Shared/ValueObject.php&lt;/span&gt;
&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Shared&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * @template TInput
 */&lt;/span&gt;
&lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ValueObject&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * @param  TInput  $value
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;mixed&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @param  self&amp;lt;TInput&amp;gt;  $other
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;self&lt;/span&gt; &lt;span class="nv"&gt;$other&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nv"&gt;$other&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nv"&gt;$other&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @param  self&amp;lt;TInput&amp;gt;  $other
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;notEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;self&lt;/span&gt; &lt;span class="nv"&gt;$other&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$other&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, o Value Object concreto Email:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Domain\Account\User\Domain\ValueObjects&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Domain\Account\User\Domain\Exceptions\InvalidEmailException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Shared\ValueObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * Email value object handles domain validation for emails.
 *
 * @extends ValueObject&amp;lt;string&amp;gt;
 */&lt;/span&gt;
&lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Email&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ValueObject&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$trimmed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;mb_strtolower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;mb_trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;filter_var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$trimmed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;FILTER_VALIDATE_EMAIL&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InvalidEmailException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"The email '&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;' is invalid."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$trimmed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$local&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;explode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$domain&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;explode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Observações importantes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O construtor já valida e normaliza (minúsculas, trim).&lt;/li&gt;
&lt;li&gt;As propriedades $local e $domain são derivadas do valor.&lt;/li&gt;
&lt;li&gt;O objeto é readonly – imutável por design.&lt;/li&gt;
&lt;li&gt;A comparação equals verifica tanto o tipo quanto o valor.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Cuidado:&lt;/strong&gt; a lógica de negócio dentro do Value Object deve ser autossuficiente e baseada apenas no valor recebido, e não deve depender de contexto externo (como banco de dados, por exemplo).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Objetos de Valor em uso
&lt;/h2&gt;

&lt;p&gt;Uma Entidade no DDD deve ser um contêiner de valores, não uma colcha de retalhos de tipos primitivos. Veja como fica uma UserEntity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserEntity&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Entity&lt;/span&gt;  &lt;span class="c1"&gt;// Entity pai fornece $id e clone()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;Name&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;Email&lt;/span&gt; &lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;?HashedPassword&lt;/span&gt; &lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Restante do código: factory methods, comportamentos...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note que &lt;code&gt;$name&lt;/code&gt;, &lt;code&gt;$email&lt;/code&gt; e &lt;code&gt;$password&lt;/code&gt; são Objetos de Valor e cada um carrega suas próprias regras. E a Entidade &lt;code&gt;User&lt;/code&gt; não precisa se preocupar com essas validações – elas já foram resolvidas no momento da criação.&lt;/p&gt;




&lt;h3&gt;
  
  
  Dicas para usar Objetos de Valor
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Comece pelos primitivos obcecados:&lt;/strong&gt; qualquer lugar onde você vê &lt;code&gt;string $cpf&lt;/code&gt;, &lt;code&gt;string $cep&lt;/code&gt;, &lt;code&gt;string $telefone&lt;/code&gt; é candidato a Value Object.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seja imutável:&lt;/strong&gt; depois de construído, nada pode mudar. Para alterar, crie um novo objeto.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Valide no construtor:&lt;/strong&gt; lance exceções específicas do domínio se os dados forem inválidos. Assim, um objeto de valor sempre representa um estado consistente.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implemente equals corretamente:&lt;/strong&gt; compare o valor na classe e todos os atributos relevantes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ao adotar Value Objects, você:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Elimina duplicação de validações.&lt;/li&gt;
&lt;li&gt;Torna o código autodocumentado.&lt;/li&gt;
&lt;li&gt;Previne estados inválidos.&lt;/li&gt;
&lt;li&gt;Facilita a evolução do domínio.&lt;/li&gt;
&lt;/ul&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Desafio:&lt;/strong&gt; &lt;em&gt;Liste 3 atributos do seu sistema atual que são primitivos mas deveriam ser Value Objects e deixe aqui nos comentários. Exemplo: placaVeiculo, numCartaoCredito, intervaloData.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Objetos de Valor &lt;strong&gt;não são&lt;/strong&gt; exclusivos para quem adota o DDD – são uma ferramenta prática para acabar com a bagunça dos tipos primitivos e validações repetidas. Eles transformam regras de negócio escondidas em código limpo, seguro e reutilizável.&lt;/p&gt;

&lt;p&gt;Então lembre-se: todo CPF, e-mail ou telefone no seu sistema é um valor que merece respeito. Trate-os como objetos – e eles tratarão bem o seu domínio.&lt;/p&gt;

&lt;p&gt;Agora vá, identifique um atributo extraia seu primeiro Value Object, e sinta a diferença na consistência. Seu eu do futuro vai agradecer.&lt;/p&gt;

&lt;p&gt;Gostou? Então &lt;strong&gt;não perca os próximos&lt;/strong&gt;. Me siga e receba mais artigos sobre código de qualidade e arquitetura de software de verdade.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔔 Compartilhe com quem ainda valida CPF com if solto no código.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vamos juntos construir softwares mais expressivos e robustos! &lt;strong&gt;Até a próxima, galerinha&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>cleancode</category>
      <category>object</category>
      <category>php</category>
    </item>
    <item>
      <title>Facades no Laravel entregam velocidade, mas cobram o preço em acoplamento</title>
      <dc:creator>Meriéli Manzano</dc:creator>
      <pubDate>Thu, 14 May 2026 15:15:00 +0000</pubDate>
      <link>https://dev.to/merielimanzano/facades-sao-o-cafe-do-laravel-resolvem-rapido-mas-viciam-e-escondem-o-problema-1o8c</link>
      <guid>https://dev.to/merielimanzano/facades-sao-o-cafe-do-laravel-resolvem-rapido-mas-viciam-e-escondem-o-problema-1o8c</guid>
      <description>&lt;p&gt;As Facades do Laravel são algo que o framework disponibiliza e que vejo muitos projetos usando em controllers, services, entities e até mesmo em repositories. Eu pessoalmente já usei e ainda uso Facade, a produtividade inicial é maravilhosa, o código fica enxuto e você entrega valor rápido porque não precisa instanciar, é só usar a Facade direto, é lindo.&lt;/p&gt;

&lt;p&gt;Só que tenho refletido sobre uma coisa que não aparece no curto prazo, especialmente quando a aplicação cresce e a manutenção se estende por anos.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Pense num cenário real:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Você tem uma classe de serviço que usa várias outras Facades internas. Funciona perfeitamente bem, até o dia que você precisar reaproveitar aquela lógica num script isolado fora do Laravel. Ou testar aquela classe sem o framework inteiro carregado.&lt;/p&gt;

&lt;p&gt;Aí você percebe: a classe não diz o que ela precisa. Você só descobre abrindo o código linha por linha. E cada facade é um fio invisível conectado ao Laravel.&lt;/p&gt;

&lt;p&gt;Não é que Facade seja errada. É que elas resolvem um problema (velocidade) e criam outro silencioso (acoplamento implícito). Cada time escolhe seu trade-off. Esse acoplamento forte com o framework vai justamente contra as regras de dependência da Clean Architecture.&lt;/p&gt;

&lt;p&gt;Para entender por que, precisamos saber que Facades do Laravel funcionam como “proxies estáticos” que fornecem acesso a objetos registrados no service container. São uma “ponte” entre uma chamada de método estático e a instância real de um objeto, resolvido em tempo de execução pelo container de injeção de dependência do Laravel.&lt;/p&gt;

&lt;p&gt;Abaixo separei algumas vantagens e desvantagens que vai te ajudar a decidir quando realmente devemos usá-las.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vantagens:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Código mais rápido de escrever e mais fácil de ler, acelerando drasticamente o desenvolvimento e a prototipagem.&lt;/li&gt;
&lt;li&gt;Facilidade para testar usando &lt;code&gt;shouldReceive()&lt;/code&gt; e Fakes para garantir que a lógica real não seja acionada, diferente de métodos estáticos tradicionais. &lt;em&gt;“Obs: Mas já que a IA está criando testes com maestria, será que isso faz realmente a diferença?”&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Tem comportamento Singleton, sendo resolvida uma única vez por requisição.&lt;/li&gt;
&lt;li&gt;Pode ser usada em qualquer lugar, sem a necessidade de passar dependência manualmente pelo construtor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Desvantagens:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Acoplamento que não quebra a testabilidade, mas suja as dependências “ou seja, não é declarada a dependência, ela fica implícita e só é descoberta olhando o corpo dos métodos”. O que dificulta manutenção e reuso.&lt;/li&gt;
&lt;li&gt;Viola a Inversão de Dependência, a classe depende diretamente de uma implementação concreta ou de uma interface resolvida pela Facade, não de uma abstração definida pelo domínio, injetada de fora.&lt;/li&gt;
&lt;li&gt;Lógica acoplada ao Framework, porque Facades só funcionam com o Facade Root inicializado. Se um dia pretender reutilizar aquela classe em um script isolado, pacote PHP puro ou outro framework, precisará reescrever tudo.&lt;/li&gt;
&lt;li&gt;Por serem muito convenientes, facilitam a violação silenciosa do SRP: desenvolvedores adicionam novas responsabilidades indiretas sem que o construtor da classe sinalize o inchaço.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deixo mais dois pontos de atenção que não são necessariamente desvantagens, mas devem ser conhecidos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Embora sejam testáveis, os mocks são aplicados globalmente – afetam todas as chamadas à facade durante o teste, não apenas uma instância específica. Sem uma limpeza explícita (como &lt;code&gt;clearResolvedInstances()&lt;/code&gt; no &lt;code&gt;tearDown&lt;/code&gt;), pode haver vazamento de comportamento entre testes. É um ponto de atenção, mas contornável.&lt;/li&gt;
&lt;li&gt;A facade não é mais rápida que a injeção direta. Cada chamada paga o custo do &lt;code&gt;__callStatic()&lt;/code&gt; e da resolução da chave no container – é tecnicamente mais lenta, mas na prática você nunca vai medir essa diferença.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Facades são ótimas em Controllers, Commands, Jobs (camadas mais próximas da infra). E podem até ser usadas em protótipos e MVPs, são uma excelente escolha para garantir velocidade de entrega.&lt;/p&gt;

&lt;p&gt;Já nas camadas de domínio, serviços de aplicação, objetos de valor, entidades... faz mais sentido injetar uma interface no construtor para desacoplar sua lógica de negócio.&lt;/p&gt;

&lt;p&gt;Tá tudo bem usar Facades. Esse post não é uma regra. É só uma lente que eu peguei dos meus estudos e que, de vez em quando, me faz perguntar: “será que aqui vale a pena declarar a dependência?”&lt;/p&gt;

&lt;p&gt;Fico curiosa pra saber como vocês lidam com isso. Já sentiu alguma dificuldade prática com Facades para testar, evoluir ou reaproveitar lógica? Ou acham que eliminar Facades do Laravel da camada de negócio é uma sofisticação desnecessária?&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>Produtividade com Testes e Vue usando VSCode</title>
      <dc:creator>Meriéli Manzano</dc:creator>
      <pubDate>Mon, 26 Sep 2022 14:18:02 +0000</pubDate>
      <link>https://dev.to/merielimanzano/produtividade-com-testes-e-vue-usando-vscode-593k</link>
      <guid>https://dev.to/merielimanzano/produtividade-com-testes-e-vue-usando-vscode-593k</guid>
      <description>&lt;p&gt;Criar testes bem organizados, separados e com uma boa descrição no Jest ou inserir toda estrutura inicial padrão de um componente Vue, pode ser verboso. Mas configurando o VS Code é possível inserir automaticamente toda pré-estrutura com a escrita de apenas uma palavra.&lt;/p&gt;

&lt;p&gt;Desenvolvendo com o Visual Studio Code você pode turbinar sua produtividade de uma forma muito simples com &lt;strong&gt;Snippets&lt;/strong&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Como funciona?
&lt;/h2&gt;

&lt;p&gt;Os snippets salvos no seu VS Code geram códigos pré-definidos ao digitar uma determinada palavra escolhida na sua configuração.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzlv2019kffldwilqcq87.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzlv2019kffldwilqcq87.gif" alt=" " width="695" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Como criar um snippet
&lt;/h2&gt;

&lt;p&gt;Com o VS Code aberto vá em &lt;strong&gt;File&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Preferences&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Configure User Snippets&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Na paleta de comandos aberta digite a linguagem para qual deseja exibir o snippet, no caso de testes Jest digite &lt;strong&gt;typescript&lt;/strong&gt; se for sua linguagem utilizada.&lt;/p&gt;

&lt;p&gt;Será aberto um arquivo typescript.json com instruções para criar seu snippet.&lt;/p&gt;

&lt;p&gt;Cada snippet tem a seguinte estrutura:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"Nome do Snippet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Palavra&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;que&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;chama&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;snippet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Corpo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;com&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;código&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;gerado&lt;/span&gt;&lt;span class="w"&gt;         
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Descrição&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;com&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;detalhes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;código&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Ao escrever o body, em linhas que houver indentação use &lt;strong&gt;&lt;code&gt;\t&lt;/code&gt;&lt;/strong&gt; para aplicar a tabulação necessária. Cada &lt;code&gt;\t&lt;/code&gt; representa um Tab.&lt;/p&gt;

&lt;p&gt;Para indicar as pausas do Tab para digitação de texto pelo código use &lt;strong&gt;&lt;code&gt;$1&lt;/code&gt;&lt;/strong&gt;, substituindo o número pela ordem de inserção desejada em cada trecho.&lt;/p&gt;

&lt;p&gt;Também é possível indicar o tipo de conteúdo a ser inserido em cada pausa com &lt;strong&gt;&lt;code&gt;${1:conteudo}&lt;/code&gt;&lt;/strong&gt; dando uma ideia do que escrever. E para definir um texto igual a ser usado em várias partes do código use o mesmo número de ID em todas partes que o texto for repetir.&lt;/p&gt;

&lt;p&gt;Abaixo montei um snippet completo para Jest usando BDD que você pode aproveitar nos seus códigos ou adaptar como preferir:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;O snippet de Vue é para uso com composition Api usando Typescript e Sass scoped, mas você pode adaptar como preferir:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;O artigo é para produtividade com Testes e Vue, mas também é possível criar snippets para outras linguagens. &lt;/p&gt;

&lt;p&gt;Espero ter ajudado! 😊&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>braziliandevs</category>
      <category>vue</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
