<?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: Vitor Fábio</title>
    <description>The latest articles on DEV Community by Vitor Fábio (@svitorz).</description>
    <link>https://dev.to/svitorz</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1009289%2F9714d9b7-230d-4ad7-9000-50234b4b9567.jpeg</url>
      <title>DEV Community: Vitor Fábio</title>
      <link>https://dev.to/svitorz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/svitorz"/>
    <language>en</language>
    <item>
      <title>Entity, DTO, Repository, Service… afinal, quem faz o quê?</title>
      <dc:creator>Vitor Fábio</dc:creator>
      <pubDate>Mon, 23 Feb 2026 12:58:58 +0000</pubDate>
      <link>https://dev.to/svitorz/entity-dto-repository-service-afinal-quem-faz-o-que-2c71</link>
      <guid>https://dev.to/svitorz/entity-dto-repository-service-afinal-quem-faz-o-que-2c71</guid>
      <description>&lt;h3&gt;
  
  
  Prefácio
&lt;/h3&gt;

&lt;p&gt;Em algum momento da sua jornada como desenvolvedor, você já se perguntou em qual camada deveria colocar a conexão com o banco, se a regra de negócio pertence ao Service ou à Entity, se é aceitável enviar e-mails diretamente do Controller ou se o DTO realmente é necessário quando a Entity já possui os campos?&lt;/p&gt;

&lt;p&gt;Se essas dúvidas já passaram pela sua cabeça, saiba que isso é mais comum do que parece.&lt;/p&gt;

&lt;p&gt;À medida que os projetos deixam de ser apenas CRUDs simples e começam a crescer, a organização do código deixa de ser um detalhe e passa a ser uma preocupação concreta. Misturar responsabilidades pode até funcionar no início, mas, com o tempo, o acoplamento aumenta, as mudanças se tornam mais delicadas e o código passa a exigir um esforço desproporcional para algo que deveria ser simples.&lt;/p&gt;

&lt;p&gt;Este artigo nasce justamente dessa inquietação.&lt;/p&gt;

&lt;p&gt;A proposta é desmistificar alguns dos principais termos que aparecem quando falamos em arquitetura orientada a objetos, Entity, Model, DAO, Repository, DTO, Service, Controller e Action, e esclarecer o papel de cada um dentro de um projeto.&lt;/p&gt;

&lt;p&gt;Mais do que decorar nomes ou seguir padrões por tendência, o objetivo é compreender responsabilidades.&lt;/p&gt;

&lt;p&gt;Arquitetura de software não é sinônimo de complexidade. É, acima de tudo, separação consciente de responsabilidades.&lt;/p&gt;




&lt;h2&gt;
  
  
  De onde vêm esses conceitos?
&lt;/h2&gt;

&lt;p&gt;Essas ideias não surgiram por acaso. Elas são influenciadas por princípios discutidos em livros como &lt;em&gt;Clean Code&lt;/em&gt; e &lt;em&gt;Clean Architecture&lt;/em&gt;, de Robert C. Martin, e &lt;em&gt;Domain-Driven Design&lt;/em&gt;, de Eric Evans.&lt;/p&gt;

&lt;p&gt;Essas obras não apresentam receitas prontas nem estruturas rígidas. O que propõem são princípios como separação de responsabilidades, baixo acoplamento, alta coesão e inversão de dependência.&lt;/p&gt;

&lt;p&gt;Com o tempo, esses fundamentos passaram a influenciar frameworks, arquiteturas modernas e projetos reais. O problema é que, muitas vezes, aprendemos o “como usar” antes de compreender o “por que usar”.&lt;/p&gt;

&lt;p&gt;É exatamente nesse ponto que a confusão começa.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Um ponto de partida: o Controller não é dono da regra
&lt;/h2&gt;

&lt;p&gt;Vamos partir de uma premissa simples: o Controller existe para lidar com o mundo externo.&lt;/p&gt;

&lt;p&gt;Em uma API HTTP, isso significa receber requisições, validar dados de entrada quanto a formato, tipos e obrigatoriedade, converter essas informações para o formato interno da aplicação, delegar a execução da regra de negócio e, por fim, retornar uma resposta HTTP adequada.&lt;/p&gt;

&lt;p&gt;Todas essas responsabilidades estão relacionadas à comunicação. O Controller traduz o mundo externo para algo que a aplicação entende e depois traduz a resposta de volta.&lt;/p&gt;

&lt;p&gt;O que ele não deveria fazer é tomar decisões de negócio, conversar diretamente com o banco, enviar e-mails, consumir APIs externas, executar regras complexas ou controlar transações.&lt;/p&gt;

&lt;p&gt;Quando o Controller passa a assumir esse tipo de responsabilidade, deixa de ser apenas uma camada de entrada e começa a concentrar decisões que não lhe pertencem. As consequências tendem a ser previsíveis: alto acoplamento, dificuldade de testes, maior complexidade para evoluir o código e repetição de lógica em diferentes endpoints.&lt;/p&gt;

&lt;p&gt;O sistema pode continuar funcionando, mas perde organização. E sem organização, a manutenção inevitavelmente se torna mais custosa.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sobre validação
&lt;/h3&gt;

&lt;p&gt;Ao falar em validação no Controller, é importante fazer uma distinção.&lt;/p&gt;

&lt;p&gt;Nem toda validação é igual. Existe a validação estrutural, responsável por verificar formato, tipagem e campos obrigatórios, e existe a validação de regra de negócio, que envolve regras do domínio, como e-mail já cadastrado, saldo insuficiente ou limite excedido.&lt;/p&gt;

&lt;p&gt;A validação estrutural faz sentido na camada de entrada, pois está ligada à integridade dos dados recebidos. Já a validação de regra pertence à camada de aplicação ou ao próprio domínio.&lt;/p&gt;

&lt;p&gt;Em alguns frameworks, como o Laravel, essas responsabilidades podem parecer misturadas. Por isso, essa distinção é relevante: quando não diferenciamos esses tipos de validação, o Controller acaba acumulando responsabilidades sem perceber.&lt;/p&gt;

&lt;p&gt;Se o Controller não é responsável pela regra de negócio, surge então uma pergunta natural: onde essa regra deve ficar?&lt;/p&gt;

&lt;p&gt;É nesse momento que a separação de camadas deixa de ser apenas teoria e passa a fazer sentido na prática. A intenção não é adicionar complexidade desnecessária, mas distribuir responsabilidades de maneira clara e coerente.&lt;/p&gt;




&lt;h2&gt;
  
  
  Camadas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  DTO — O contrato com o mundo externo
&lt;/h3&gt;

&lt;p&gt;Se o Controller interage com o mundo externo, ele precisa de uma estrutura que organize essa troca de dados. É aqui que entra o DTO (Data Transfer Object).&lt;/p&gt;

&lt;p&gt;O DTO não representa o domínio da aplicação; ele representa o contrato de entrada ou saída. Um CreateUserRequest, por exemplo, pode conter apenas nome e e-mail, exatamente como esperado pela API.&lt;/p&gt;

&lt;p&gt;Ele não contém regra de negócio, não conhece banco de dados e não depende de infraestrutura. Sua função é transportar dados entre camadas.&lt;/p&gt;

&lt;p&gt;Nesse ponto, surge uma dúvida comum: se a Entity já possui esses campos, por que criar DTO?&lt;/p&gt;

&lt;p&gt;Porque o domínio não deve depender do formato externo da aplicação. O DTO protege a Entity de mudanças na API, evita a exposição de campos sensíveis e impede que detalhes internos vazem para fora. Ele funciona como uma barreira entre o mundo externo e o núcleo da aplicação.&lt;/p&gt;




&lt;h3&gt;
  
  
  Service — Onde a decisão acontece
&lt;/h3&gt;

&lt;p&gt;Se o Controller não deve tomar decisões, alguém precisa assumir essa responsabilidade.&lt;/p&gt;

&lt;p&gt;Essa função costuma ficar no Service — abordagem mais comum — ou, em arquiteturas orientadas a caso de uso, em uma Action.&lt;/p&gt;

&lt;p&gt;O Service é responsável por orquestrar o fluxo da aplicação. É nele que a regra de negócio acontece. Pode aplicar validações de domínio, consultar repositórios, criar ou modificar entidades, coordenar efeitos colaterais como envio de e-mails ou integração com APIs externas e controlar transações quando necessário.&lt;/p&gt;

&lt;p&gt;Diferente do Controller, o Service não sabe nada sobre HTTP. Ele não sabe se a aplicação é uma API, um CLI ou um job agendado. Ele simplesmente executa um fluxo de negócio.&lt;/p&gt;

&lt;p&gt;Essa separação traz um benefício importante: a regra deixa de depender da forma como o sistema é acessado. Se amanhã for necessário expor o mesmo fluxo por meio de fila, CLI ou outro endpoint, o Service continuará o mesmo, o que contribui para escalabilidade e reaproveitamento.&lt;/p&gt;

&lt;p&gt;Vale uma observação: Service não deve existir apenas para repassar chamadas. Se ele apenas invoca &lt;code&gt;repository.save()&lt;/code&gt; sem tomar decisões, talvez não esteja agregando valor real ao fluxo.&lt;/p&gt;




&lt;h3&gt;
  
  
  Entity — O coração do domínio
&lt;/h3&gt;

&lt;p&gt;Se o Service decide o fluxo, a Entity representa o que o sistema é.&lt;/p&gt;

&lt;p&gt;Ela não é apenas uma estrutura de dados com getters e setters, mas a representação de um conceito do domínio. Um Usuário, um Pedido ou uma Fatura são exemplos claros de entidades.&lt;/p&gt;

&lt;p&gt;Uma Entity possui identidade. Mesmo que seus atributos mudem, ela continua sendo a mesma entidade dentro do sistema.&lt;/p&gt;

&lt;p&gt;Dependendo do nível de maturidade arquitetural, pode conter regras relacionadas à sua própria consistência. Um Pedido pode impedir que seja finalizado duas vezes; uma Conta pode impedir saque se o saldo for insuficiente; um Usuário pode normalizar seu próprio e-mail ao ser criado.&lt;/p&gt;

&lt;p&gt;Essas regras dizem respeito à coerência interna do objeto, não ao fluxo da aplicação.&lt;/p&gt;

&lt;p&gt;A Entity não precisa conhecer banco de dados, HTTP, frameworks, envio de e-mails ou execução de queries. Ela representa o domínio, não a infraestrutura. Quando passa a depender de detalhes externos, o domínio perde independência e se torna acoplado à tecnologia.&lt;/p&gt;

&lt;p&gt;Inicialmente, tive bastante confusão entre Entity e DTO. De maneira simples, posso dizer que a Entity está mais próxima do domínio e, muitas vezes, do mapeamento com o banco ou ORM, enquanto o DTO está relacionado à transferência de dados entre camadas. Isso significa que é perfeitamente normal existir Entities e DTOs no mesmo projeto.&lt;/p&gt;




&lt;h3&gt;
  
  
  Repository — Abstração de persistência
&lt;/h3&gt;

&lt;p&gt;Se a Entity representa o domínio e o Service concentra a decisão, alguém precisa cuidar da persistência.&lt;/p&gt;

&lt;p&gt;O Repository cumpre esse papel. Ele representa um conjunto de operações relacionadas a uma entidade e se comunica na linguagem do domínio, não na linguagem da tabela.&lt;/p&gt;

&lt;p&gt;Em vez de pensar em “tabela users”, o Repository pensa em “Usuários”. Pode oferecer operações como salvar um usuário, buscar por e-mail, listar ativos ou remover por id.&lt;/p&gt;

&lt;p&gt;O ponto central é que o Service não deve conhecer os detalhes da persistência. Ele não precisa saber se está utilizando JPA, SQL puro, MongoDB ou qualquer outra tecnologia. Interage apenas com um contrato.&lt;/p&gt;

&lt;p&gt;Essa separação permite trocar a tecnologia de armazenamento, testar a regra de negócio de forma isolada e reduzir o acoplamento com a infraestrutura.&lt;/p&gt;

&lt;p&gt;O Repository não executa regra de negócio; ele executa persistência.&lt;/p&gt;




&lt;h3&gt;
  
  
  DAO — O aspecto mais técnico da persistência
&lt;/h3&gt;

&lt;p&gt;DAO (Data Access Object) é um padrão mais antigo e mais técnico.&lt;/p&gt;

&lt;p&gt;Enquanto o Repository é orientado ao domínio, o DAO costuma ser mais voltado à infraestrutura. Ele encapsula operações diretas com o banco, como execução de queries, mapeamento de resultados, controle de conexão e manipulação de SQL específico.&lt;/p&gt;

&lt;p&gt;Em projetos simples, DAO e Repository podem acabar desempenhando papéis muito semelhantes. Conceitualmente, porém, existe uma diferença sutil: o DAO fala a linguagem do banco; o Repository fala a linguagem do domínio.&lt;/p&gt;

&lt;p&gt;Essa distinção tende a ficar mais evidente conforme o sistema cresce.&lt;/p&gt;




&lt;h2&gt;
  
  
  Reflexões
&lt;/h2&gt;

&lt;p&gt;À medida que aprofundamos a separação de responsabilidades, é natural que surjam variações desses mesmos conceitos em arquiteturas mais estruturadas.&lt;/p&gt;

&lt;p&gt;Em vez de concentrar várias responsabilidades dentro de um único Service com muitos métodos, algumas abordagens preferem trabalhar com Use Cases ou Actions, em que cada fluxo de negócio ganha sua própria classe, como CreateUser ou CancelOrder. Isso tende a reduzir o tamanho das classes e deixa cada comportamento mais explícito, quase como uma narrativa do que o sistema faz.&lt;/p&gt;

&lt;p&gt;Outro conceito que costuma aparecer nesse contexto é o Mapper, responsável por converter DTOs em Entities e vice-versa. Em projetos menores, essa conversão pode permanecer dentro do Service sem grandes problemas. Em sistemas maiores, porém, centralizar essa responsabilidade ajuda a evitar repetição e torna o código mais organizado.&lt;/p&gt;

&lt;p&gt;Também existe o Domain Service, bastante discutido em Domain-Driven Design. Ele entra em cena quando uma regra não pertence claramente a uma única entidade. É um tema que merece um aprofundamento próprio, mas vale a menção para mostrar que a separação de responsabilidades não é estática, ela pode evoluir conforme o domínio se torna mais complexo.&lt;/p&gt;

&lt;p&gt;No fundo, o que estamos fazendo ao organizar essas camadas é aproximar o código do domínio do negócio. E essa é justamente a essência do DDD: estruturar o sistema em torno do que ele representa, e não da tecnologia que o sustenta.&lt;/p&gt;




&lt;h2&gt;
  
  
  Arquitetura é preparação para mudança
&lt;/h2&gt;

&lt;p&gt;Nem todo projeto precisa nascer com todas essas camadas bem definidas. Em aplicações muito pequenas ou sistemas que dificilmente irão evoluir, criar múltiplas abstrações pode gerar mais complexidade do que benefício.&lt;/p&gt;

&lt;p&gt;Por outro lado, quando o sistema começa a crescer, novas regras surgem, integrações são adicionadas e diferentes pontos de entrada aparecem, a ausência de separação passa a cobrar um preço.&lt;/p&gt;

&lt;p&gt;Arquitetura não é formalidade. É preparação para mudança.&lt;/p&gt;

&lt;p&gt;É comum que um sistema comece simples e, com o tempo, passe por refatorações que separem responsabilidades que antes estavam misturadas. Isso não significa que o projeto estava errado no início; significa que ele amadureceu.&lt;/p&gt;

&lt;p&gt;O próprio Clean Code reforça essa ideia de melhoria contínua por meio de refatoração. Separar camadas pode ser apenas mais um passo nessa direção.&lt;/p&gt;




&lt;h2&gt;
  
  
  Arquitetura também evolui
&lt;/h2&gt;

&lt;p&gt;Existe a ideia de que decisões arquiteturais precisam ser perfeitas desde o primeiro dia. Na prática, isso raramente acontece.&lt;/p&gt;

&lt;p&gt;Projetos podem adotar separação de camadas mesmo após anos em produção, e essa reorganização costuma acontecer de forma gradual: primeiro extraindo regras do Controller, depois isolando persistência, depois introduzindo contratos mais claros entre as partes.&lt;/p&gt;

&lt;p&gt;Quando essa organização começa a se repetir em diferentes áreas do sistema, surge algo maior do que apenas camadas. Surgem módulos organizados por contexto, por domínio, por significado.&lt;/p&gt;

&lt;p&gt;Nesse momento, a arquitetura deixa de ser apenas uma divisão técnica e passa a refletir o próprio negócio. E é justamente aí que conceitos do Domain-Driven Design começam a fazer mais sentido.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;No fim das contas, esses padrões não existem para tornar o código mais sofisticado nem para atender a uma formalidade arquitetural. Eles existem para deixar claro quem faz o quê e para manter o domínio no centro da aplicação.&lt;/p&gt;

&lt;p&gt;Quando essa clareza aparece, o sistema deixa de ser apenas funcional e passa a ser sustentável. Sustentável no sentido de poder crescer, mudar e evoluir sem que cada nova alteração gere insegurança ou retrabalho excessivo.&lt;/p&gt;

&lt;p&gt;Arquitetura não é sobre criar barreiras artificiais. É sobre dar espaço para que o domínio respire e para que o sistema acompanhe a complexidade do mundo real sem perder organização.&lt;/p&gt;




&lt;h2&gt;
  
  
  Encerramento
&lt;/h2&gt;

&lt;p&gt;Quando comecei a estudar esses conceitos, a dúvida sempre era muito direta: “em qual camada eu coloco isso?”. Com o tempo, percebi que a pergunta mais importante não era onde colocar o código, mas se aquela responsabilidade realmente pertencia ali.&lt;/p&gt;

&lt;p&gt;Essa mudança de perspectiva transforma a forma como enxergamos arquitetura. Ela deixa de ser um conjunto de nomes complexos e passa a ser um exercício constante de organização.&lt;/p&gt;

&lt;p&gt;Nem todo projeto precisa de todas as camadas desde o primeiro dia. Mas todo projeto que cresce precisa, em algum momento, organizar suas responsabilidades.&lt;/p&gt;

&lt;p&gt;Se este texto conseguir tornar essa distinção um pouco mais clara, então ele já cumpriu seu papel.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>career</category>
      <category>learning</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Entity, DTO, Repository, Service… afinal, quem faz o quê?</title>
      <dc:creator>Vitor Fábio</dc:creator>
      <pubDate>Mon, 23 Feb 2026 11:00:00 +0000</pubDate>
      <link>https://dev.to/svitorz/entity-dto-repository-service-afinal-quem-faz-o-que-34fn</link>
      <guid>https://dev.to/svitorz/entity-dto-repository-service-afinal-quem-faz-o-que-34fn</guid>
      <description>&lt;h3&gt;
  
  
  Prefácio
&lt;/h3&gt;

&lt;p&gt;Em algum momento da sua jornada como desenvolvedor, você já se perguntou em qual camada deveria colocar a conexão com o banco, se a regra de negócio pertence ao Service ou à Entity, se é aceitável enviar e-mails diretamente do Controller ou se o DTO realmente é necessário quando a Entity já possui os campos?&lt;/p&gt;

&lt;p&gt;Se essas dúvidas já passaram pela sua cabeça, saiba que isso é mais comum do que parece.&lt;/p&gt;

&lt;p&gt;À medida que os projetos deixam de ser apenas CRUDs simples e começam a crescer, a organização do código deixa de ser um detalhe e passa a ser uma preocupação concreta. Misturar responsabilidades pode até funcionar no início, mas, com o tempo, o acoplamento aumenta, as mudanças se tornam mais delicadas e o código passa a exigir um esforço desproporcional para algo que deveria ser simples.&lt;/p&gt;

&lt;p&gt;Este artigo nasce justamente dessa inquietação.&lt;/p&gt;

&lt;p&gt;A proposta é desmistificar alguns dos principais termos que aparecem quando falamos em arquitetura orientada a objetos — Entity, Model, DAO, Repository, DTO, Service, Controller e Action — e esclarecer o papel de cada um dentro de um projeto.&lt;/p&gt;

&lt;p&gt;Mais do que decorar nomes ou seguir padrões por tendência, o objetivo é compreender responsabilidades.&lt;/p&gt;

&lt;p&gt;Arquitetura de software não é sinônimo de complexidade. É, acima de tudo, separação consciente de responsabilidades.&lt;/p&gt;




&lt;h2&gt;
  
  
  De onde vêm esses conceitos?
&lt;/h2&gt;

&lt;p&gt;Essas ideias não surgiram por acaso. Elas são influenciadas por princípios discutidos em livros como &lt;em&gt;Clean Code&lt;/em&gt; e &lt;em&gt;Clean Architecture&lt;/em&gt;, de Robert C. Martin, e &lt;em&gt;Domain-Driven Design&lt;/em&gt;, de Eric Evans.&lt;/p&gt;

&lt;p&gt;Essas obras não apresentam receitas prontas nem estruturas rígidas. O que propõem são princípios como separação de responsabilidades, baixo acoplamento, alta coesão e inversão de dependência.&lt;/p&gt;

&lt;p&gt;Com o tempo, esses fundamentos passaram a influenciar frameworks, arquiteturas modernas e projetos reais. O problema é que, muitas vezes, aprendemos o “como usar” antes de compreender o “por que usar”.&lt;/p&gt;

&lt;p&gt;É exatamente nesse ponto que a confusão começa.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Um ponto de partida: o Controller não é dono da regra
&lt;/h2&gt;

&lt;p&gt;Vamos partir de uma premissa simples: o Controller existe para lidar com o mundo externo.&lt;/p&gt;

&lt;p&gt;Em uma API HTTP, isso significa receber requisições, validar dados de entrada quanto a formato, tipos e obrigatoriedade, converter essas informações para o formato interno da aplicação, delegar a execução da regra de negócio e, por fim, retornar uma resposta HTTP adequada.&lt;/p&gt;

&lt;p&gt;Todas essas responsabilidades estão relacionadas à comunicação. O Controller traduz o mundo externo para algo que a aplicação entende e depois traduz a resposta de volta.&lt;/p&gt;

&lt;p&gt;O que ele não deveria fazer é tomar decisões de negócio, conversar diretamente com o banco, enviar e-mails, consumir APIs externas, executar regras complexas ou controlar transações.&lt;/p&gt;

&lt;p&gt;Quando o Controller passa a assumir esse tipo de responsabilidade, deixa de ser apenas uma camada de entrada e começa a concentrar decisões que não lhe pertencem. As consequências tendem a ser previsíveis: alto acoplamento, dificuldade de testes, maior complexidade para evoluir o código e repetição de lógica em diferentes endpoints.&lt;/p&gt;

&lt;p&gt;O sistema pode continuar funcionando, mas perde organização. E sem organização, a manutenção inevitavelmente se torna mais custosa.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sobre validação
&lt;/h3&gt;

&lt;p&gt;Ao falar em validação no Controller, é importante fazer uma distinção.&lt;/p&gt;

&lt;p&gt;Nem toda validação é igual. Existe a validação estrutural, responsável por verificar formato, tipagem e campos obrigatórios, e existe a validação de regra de negócio, que envolve regras do domínio, como e-mail já cadastrado, saldo insuficiente ou limite excedido.&lt;/p&gt;

&lt;p&gt;A validação estrutural faz sentido na camada de entrada, pois está ligada à integridade dos dados recebidos. Já a validação de regra pertence à camada de aplicação ou ao próprio domínio.&lt;/p&gt;

&lt;p&gt;Em alguns frameworks, como o Laravel, essas responsabilidades podem parecer misturadas. Por isso, essa distinção é relevante: quando não diferenciamos esses tipos de validação, o Controller acaba acumulando responsabilidades sem perceber.&lt;/p&gt;

&lt;p&gt;Se o Controller não é responsável pela regra de negócio, surge então uma pergunta natural: onde essa regra deve ficar?&lt;/p&gt;

&lt;p&gt;É nesse momento que a separação de camadas deixa de ser apenas teoria e passa a fazer sentido na prática. A intenção não é adicionar complexidade desnecessária, mas distribuir responsabilidades de maneira clara e coerente.&lt;/p&gt;




&lt;h2&gt;
  
  
  Camadas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  DTO — O contrato com o mundo externo
&lt;/h3&gt;

&lt;p&gt;Se o Controller interage com o mundo externo, ele precisa de uma estrutura que organize essa troca de dados. É aqui que entra o DTO (Data Transfer Object).&lt;/p&gt;

&lt;p&gt;O DTO não representa o domínio da aplicação; ele representa o contrato de entrada ou saída. Um CreateUserRequest, por exemplo, pode conter apenas nome e e-mail, exatamente como esperado pela API.&lt;/p&gt;

&lt;p&gt;Ele não contém regra de negócio, não conhece banco de dados e não depende de infraestrutura. Sua função é transportar dados entre camadas.&lt;/p&gt;

&lt;p&gt;Nesse ponto, surge uma dúvida comum: se a Entity já possui esses campos, por que criar DTO?&lt;/p&gt;

&lt;p&gt;Porque o domínio não deve depender do formato externo da aplicação. O DTO protege a Entity de mudanças na API, evita a exposição de campos sensíveis e impede que detalhes internos vazem para fora. Ele funciona como uma barreira entre o mundo externo e o núcleo da aplicação.&lt;/p&gt;




&lt;h3&gt;
  
  
  Service — Onde a decisão acontece
&lt;/h3&gt;

&lt;p&gt;Se o Controller não deve tomar decisões, alguém precisa assumir essa responsabilidade.&lt;/p&gt;

&lt;p&gt;Essa função costuma ficar no Service — abordagem mais comum — ou, em arquiteturas orientadas a caso de uso, em uma Action.&lt;/p&gt;

&lt;p&gt;O Service é responsável por orquestrar o fluxo da aplicação. É nele que a regra de negócio acontece. Pode aplicar validações de domínio, consultar repositórios, criar ou modificar entidades, coordenar efeitos colaterais como envio de e-mails ou integração com APIs externas e controlar transações quando necessário.&lt;/p&gt;

&lt;p&gt;Diferente do Controller, o Service não sabe nada sobre HTTP. Ele não sabe se a aplicação é uma API, um CLI ou um job agendado. Ele simplesmente executa um fluxo de negócio.&lt;/p&gt;

&lt;p&gt;Essa separação traz um benefício importante: a regra deixa de depender da forma como o sistema é acessado. Se amanhã for necessário expor o mesmo fluxo por meio de fila, CLI ou outro endpoint, o Service continuará o mesmo, o que contribui para escalabilidade e reaproveitamento.&lt;/p&gt;

&lt;p&gt;Vale uma observação: Service não deve existir apenas para repassar chamadas. Se ele apenas invoca repository.save() sem tomar decisões, talvez não esteja agregando valor real ao fluxo.&lt;/p&gt;




&lt;h3&gt;
  
  
  Entity — O coração do domínio
&lt;/h3&gt;

&lt;p&gt;Se o Service decide o fluxo, a Entity representa o que o sistema é.&lt;/p&gt;

&lt;p&gt;Ela não é apenas uma estrutura de dados com getters e setters, mas a representação de um conceito do domínio. Um Usuário, um Pedido ou uma Fatura são exemplos claros de entidades.&lt;/p&gt;

&lt;p&gt;Uma Entity possui identidade. Mesmo que seus atributos mudem, ela continua sendo a mesma entidade dentro do sistema.&lt;/p&gt;

&lt;p&gt;Dependendo do nível de maturidade arquitetural, pode conter regras relacionadas à sua própria consistência. Um Pedido pode impedir que seja finalizado duas vezes; uma Conta pode impedir saque se o saldo for insuficiente; um Usuário pode normalizar seu próprio e-mail ao ser criado.&lt;/p&gt;

&lt;p&gt;Essas regras dizem respeito à coerência interna do objeto, não ao fluxo da aplicação.&lt;/p&gt;

&lt;p&gt;A Entity não precisa conhecer banco de dados, HTTP, frameworks, envio de e-mails ou execução de queries. Ela representa o domínio, não a infraestrutura. Quando passa a depender de detalhes externos, o domínio perde independência e se torna acoplado à tecnologia.&lt;/p&gt;

&lt;p&gt;Inicialmente, tive bastante confusão entre Entity e DTO. De maneira simples, posso dizer que a Entity está mais próxima do domínio e, muitas vezes, do mapeamento com o banco ou ORM, enquanto o DTO está relacionado à transferência de dados entre camadas. Isso significa que é perfeitamente normal existir Entities e DTOs no mesmo projeto.&lt;/p&gt;




&lt;h3&gt;
  
  
  Repository — Abstração de persistência
&lt;/h3&gt;

&lt;p&gt;Se a Entity representa o domínio e o Service concentra a decisão, alguém precisa cuidar da persistência.&lt;/p&gt;

&lt;p&gt;O Repository cumpre esse papel. Ele representa um conjunto de operações relacionadas a uma entidade e se comunica na linguagem do domínio, não na linguagem da tabela.&lt;/p&gt;

&lt;p&gt;Em vez de pensar em “tabela users”, o Repository pensa em “Usuários”. Pode oferecer operações como salvar um usuário, buscar por e-mail, listar ativos ou remover por id.&lt;/p&gt;

&lt;p&gt;O ponto central é que o Service não deve conhecer os detalhes da persistência. Ele não precisa saber se está utilizando JPA, SQL puro, MongoDB ou qualquer outra tecnologia. Interage apenas com um contrato.&lt;/p&gt;

&lt;p&gt;Essa separação permite trocar a tecnologia de armazenamento, testar a regra de negócio de forma isolada e reduzir o acoplamento com a infraestrutura.&lt;/p&gt;

&lt;p&gt;O Repository não executa regra de negócio; ele executa persistência.&lt;/p&gt;




&lt;h3&gt;
  
  
  DAO — O aspecto mais técnico da persistência
&lt;/h3&gt;

&lt;p&gt;DAO (Data Access Object) é um padrão mais antigo e mais técnico.&lt;/p&gt;

&lt;p&gt;Enquanto o Repository é orientado ao domínio, o DAO costuma ser mais voltado à infraestrutura. Ele encapsula operações diretas com o banco, como execução de queries, mapeamento de resultados, controle de conexão e manipulação de SQL específico.&lt;/p&gt;

&lt;p&gt;Em projetos simples, DAO e Repository podem acabar desempenhando papéis muito semelhantes. Conceitualmente, porém, existe uma diferença sutil: o DAO fala a linguagem do banco; o Repository fala a linguagem do domínio.&lt;/p&gt;

&lt;p&gt;Essa distinção tende a ficar mais evidente conforme o sistema cresce.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusões
&lt;/h2&gt;

&lt;p&gt;À medida que aprofundamos a separação de responsabilidades, é comum encontrar variações desses conceitos em arquiteturas mais estruturadas.&lt;/p&gt;

&lt;p&gt;Em vez de um Service com vários métodos, algumas abordagens adotam o conceito de Use Case ou Action, em que cada fluxo de negócio é representado por uma classe específica, como CreateUser ou CancelOrder. Isso reduz o tamanho das classes e torna cada comportamento mais explícito.&lt;/p&gt;

&lt;p&gt;Outro conceito recorrente é o Mapper, responsável por converter DTOs em Entities e vice-versa. Em projetos menores, essa conversão pode permanecer no Service sem grandes problemas; em sistemas maiores, centralizá-la tende a melhorar a organização e evitar repetições.&lt;/p&gt;

&lt;p&gt;Também existe o Domain Service, discutido em Domain-Driven Design, utilizado quando uma regra não pertence claramente a uma única entidade. É um tema que merece aprofundamento próprio, mas sua menção ajuda a mostrar que a separação de responsabilidades pode evoluir conforme o domínio se torna mais complexo.&lt;/p&gt;

&lt;p&gt;Nem sempre precisamos de todas essas camadas. Em projetos muito pequenos ou aplicações que dificilmente irão evoluir, criar múltiplas camadas pode gerar mais complexidade do que benefício.&lt;/p&gt;

&lt;p&gt;Por outro lado, quando o sistema começa a crescer, novas regras surgem, integrações são adicionadas e diferentes pontos de entrada aparecem, a ausência de separação passa a cobrar um preço alto.&lt;/p&gt;

&lt;p&gt;Arquitetura não é formalidade; é preparação para mudança.&lt;/p&gt;

&lt;p&gt;É comum que um sistema comece simples e, com o tempo, passe por refatorações que separem responsabilidades antes misturadas. Isso não significa que o projeto estava errado no início, mas que ele amadureceu.&lt;/p&gt;

&lt;p&gt;O próprio Clean Code reforça a ideia de melhoria contínua por meio de refatoração. Separar camadas pode ser uma dessas melhorias.&lt;/p&gt;

&lt;p&gt;Muitos desenvolvedores acreditam que decisões arquiteturais precisam ser perfeitas desde o primeiro dia. Na prática, raramente isso acontece. Projetos podem adotar separação de camadas mesmo após anos em produção, de forma gradual: primeiro extraindo regras do Controller, depois isolando persistência e, por fim, introduzindo contratos mais claros.&lt;/p&gt;

&lt;p&gt;Arquitetura também evolui.&lt;/p&gt;

&lt;p&gt;E essa evolução nos leva a uma discussão importante: como essas camadas se comportam quando utilizamos ORM, Active Record ou SQL puro?&lt;/p&gt;

&lt;p&gt;Dependendo da tecnologia escolhida, algumas camadas podem assumir papéis diferentes. Em frameworks que utilizam Active Record, como o Eloquent do Laravel, a própria classe Model costuma acumular responsabilidades de entidade e persistência. Isso simplifica o desenvolvimento inicial, mas pode misturar domínio e infraestrutura.&lt;/p&gt;

&lt;p&gt;Em arquiteturas baseadas em ORM mais tradicionais, como JPA no ecossistema Java, é comum que as Entities sejam mapeadas para o banco por meio de anotações, enquanto o acesso aos dados ocorre via Repository.&lt;/p&gt;

&lt;p&gt;Já em projetos que utilizam SQL puro, sem ORM, padrões como DAO fazem ainda mais sentido, pois encapsulam queries, mapeamento de resultados e controle de conexão.&lt;/p&gt;

&lt;p&gt;A tecnologia influencia a forma como esses padrões são aplicados, mas os princípios de separação de responsabilidades permanecem os mesmos.&lt;/p&gt;

&lt;p&gt;Independentemente de usar ORM ou SQL direto, a pergunta continua válida: quem decide, quem representa o domínio e quem persiste?&lt;/p&gt;

&lt;h2&gt;
  
  
  Encerramento
&lt;/h2&gt;

&lt;p&gt;Quando comecei a estudar esses conceitos, a dúvida sempre era muito direta: “em qual camada eu coloco isso?”. Com o tempo, percebi que a pergunta mais importante não era onde colocar o código, mas se aquela responsabilidade realmente pertencia ali.&lt;/p&gt;

&lt;p&gt;Essa mudança de perspectiva transforma a forma como enxergamos arquitetura. Ela deixa de ser um conjunto de nomes complexos e passa a ser um exercício constante de organização.&lt;/p&gt;

&lt;p&gt;Nem todo projeto precisa de todas as camadas desde o primeiro dia. Mas todo projeto que cresce precisa, em algum momento, organizar suas responsabilidades.&lt;/p&gt;

&lt;p&gt;Se este texto conseguir tornar essa distinção um pouco mais clara, então ele já cumpriu seu papel.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>beginners</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Padronizando o Caos: Minha jornada com Dotfiles</title>
      <dc:creator>Vitor Fábio</dc:creator>
      <pubDate>Wed, 30 Apr 2025 15:30:00 +0000</pubDate>
      <link>https://dev.to/svitorz/padronizando-o-caos-minha-jornada-com-dotfiles-2ck9</link>
      <guid>https://dev.to/svitorz/padronizando-o-caos-minha-jornada-com-dotfiles-2ck9</guid>
      <description>&lt;p&gt;Manter consistência em ambientes de desenvolvimento sempre foi um desafio para mim. Cada novo sistema Linux instalado, seja no desktop pessoal ou em servidores, exigia uma nova "dança" de configurações de shell, editores, atalhos, temas e programas. Foi então que decidi iniciar meu próprio repositório de dotfiles: &lt;a href="https://github.com/svitorz/dotfiles" rel="noopener noreferrer"&gt;svitorz/dotfiles&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A ideia
&lt;/h2&gt;

&lt;p&gt;Desde o início da minha jornada como desenvolvedor, sempre me interessei por sistemas Linux, e claro, pelo terminal. Mas a minha inquietação com Linux foi tanta, que troquei de distribuição várias vezes, passando por Debian, Ubuntu 22.04, Ubuntu 24.04, Mint, Pop!_OS e finalmente, a distro que utilizo até hoje: o Arch Linux. Entretanto, entre todas essas trocas de sistema, sempre havia algo muito trabalhoso e repetitivo que causava estresse durante o processo: a configuração de ambiente.&lt;/p&gt;

&lt;h2&gt;
  
  
  O início
&lt;/h2&gt;

&lt;p&gt;Certa vez, aleatoriamente, caí em um repositório de um desconhecido que falava sobre como mantinha suas "personal files". De cara, não entendi exatamente a que ele se referia e, vendo o repositório, mal sabia do que se tratava. Foi quando, em uma busca rápida, entendi que se tratavam de arquivos de configuração pessoais. Ou seja, cada usuário poderia manter os seus da forma que bem desejasse, de acordo com suas ambições dentro da sua distro Linux. E mais: isso tinha o poder de padronizar todas as ferramentas utilizadas no dia a dia, independente de sistema, máquina ou projeto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como mantenho minhas dotfiles?
&lt;/h2&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%2Fb4xrszoisgdckmhicbth.png" 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%2Fb4xrszoisgdckmhicbth.png" alt="My personal github repository for dotfiles" width="800" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para cada aplicação, ferramenta ou framework que utilizo, mantenho uma pasta única e separada para facilitar a busca e interpretação dos comandos. Também mantenho todos os arquivos na linguagem padrão da aplicação: seja Shell Script, no caso do &lt;code&gt;.zshrc&lt;/code&gt;, ou Lua, no caso dos arquivos de configuração do Neovim.&lt;/p&gt;

&lt;h2&gt;
  
  
  Utilização de ShellScript para agilizar o processo
&lt;/h2&gt;

&lt;p&gt;Dentro da pasta &lt;code&gt;/home/user/&lt;/code&gt; da minha máquina, há um arquivo chamado &lt;code&gt;savedotfiles&lt;/code&gt;, que faz uma cópia de todos os arquivos de configuração para o diretório &lt;code&gt;dotfiles&lt;/code&gt;, que é onde está o repositório. Após isso, o mesmo shell script roda o comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Facilitando para que eu apenas faça o commit e o push.&lt;/p&gt;

&lt;h2&gt;
  
  
  Uso do Git para gerenciar o repositório
&lt;/h2&gt;

&lt;p&gt;Utilizo o Git de forma convencional, mas com alguns cuidados:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Commits frequentes&lt;/strong&gt;: toda pequena melhoria ou novo ajuste é versionado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mensagens claras&lt;/strong&gt;: cada commit explica o motivo daquela alteração.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Branches de experimentação&lt;/strong&gt;: quando quero testar uma nova tool ou mudança, crio uma branch separada.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backups regulares&lt;/strong&gt;: mantenho um clone do repositório em mais de um local.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Atualmente, o repositório é público para que outros possam ver como montei meu ambiente, pegar ideias ou sugerir melhorias.&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerações finais
&lt;/h2&gt;

&lt;p&gt;Manter um repositório de dotfiles mudou a forma como lido com ambientes de trabalho. Se você ainda não começou o seu, recomendo demais: é um exercício de organização, automação e consistência.&lt;/p&gt;

&lt;p&gt;Se quiser dar uma olhada ou se inspirar, o repositório está aqui: &lt;a href="https://github.com/svitorz/dotfiles" rel="noopener noreferrer"&gt;github.com/svitorz/dotfiles&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E você? Como gerencia seu ambiente de desenvolvimento? Vamos conversar nos comentários!&lt;/p&gt;

</description>
      <category>dotfiles</category>
      <category>opensource</category>
      <category>tooling</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Tutorial para criação de projetos com Ruby on Rails (sem Ruby localmente)</title>
      <dc:creator>Vitor Fábio</dc:creator>
      <pubDate>Tue, 31 Dec 2024 01:51:07 +0000</pubDate>
      <link>https://dev.to/svitorz/tutorial-para-criacao-de-projetos-com-ruby-on-rails-sem-ruby-localmente-459o</link>
      <guid>https://dev.to/svitorz/tutorial-para-criacao-de-projetos-com-ruby-on-rails-sem-ruby-localmente-459o</guid>
      <description>&lt;p&gt;Primeiramente, crie uma um arquivo chamado "Dockerfile", então insira nele o seguinte conteúdo.&lt;/p&gt;

&lt;p&gt;Dockerfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Use uma imagem oficial do Ruby&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ruby:3.2&lt;/span&gt;

&lt;span class="c"&gt;# Instale dependências do sistema&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="nt"&gt;-qq&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; build-essential libpq-dev nodejs yarn

&lt;span class="c"&gt;# Defina o diretório de trabalho&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Instale bundler e Rails&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;bundler rails

&lt;span class="c"&gt;# Copie o Gemfile e Gemfile.lock (se existir)&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; Gemfile Gemfile.lock /app/&lt;/span&gt;

&lt;span class="c"&gt;# Instale as gems&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;bundle &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Copie o restante da aplicação para dentro do container&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /app&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Insira no seu terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; rails-crud &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após isso, você já poderá criar seu projeto. Entre no diretório que deseja manter seu projeto, e insira no terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;:/app &lt;span class="nt"&gt;-w&lt;/span&gt; /app rails-crud rails new nome-do-projeto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
  </channel>
</rss>
