<?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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1009289%2Ffb8c4215-63cc-44f2-bc18-8e10f2309065.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>Repensando o fluxo de desenvolvimento de software com o aumento da codificação assistida por IA</title>
      <dc:creator>Vitor Fábio</dc:creator>
      <pubDate>Thu, 24 Sep 2026 22:07:58 +0000</pubDate>
      <link>https://dev.to/svitorz/repensando-o-fluxo-de-desenvolvimento-de-software-com-o-aumento-da-codificacao-assistida-por-ia-35ki</link>
      <guid>https://dev.to/svitorz/repensando-o-fluxo-de-desenvolvimento-de-software-com-o-aumento-da-codificacao-assistida-por-ia-35ki</guid>
      <description>&lt;p&gt;A adoção de ferramentas de inteligência artificial no desenvolvimento de software está reduzindo consideravelmente o tempo necessário para implementar muitas tarefas. Atividades que anteriormente exigiam várias horas de investigação, escrita de código e criação de testes podem ser realizadas em períodos menores quando o desenvolvedor utiliza agentes capazes de analisar a base de código, propor implementações e executar parte do trabalho necessário.&lt;/p&gt;

&lt;p&gt;Esse ganho é relevante, mas também começa a produzir algumas mudanças no fluxo de desenvolvimento que merecem atenção. Se um desenvolvedor consegue concluir mais tarefas no mesmo período, a consequência natural é um aumento na quantidade de alterações que precisam passar pelas etapas seguintes do processo, especialmente testes, revisão de código e integração.&lt;/p&gt;

&lt;p&gt;A capacidade de produzir código, portanto, pode crescer mais rapidamente do que a capacidade do time de revisar esse código.&lt;/p&gt;

&lt;p&gt;Na prática, isso pode resultar em um aumento do WIP (&lt;em&gt;Work in Progress&lt;/em&gt;), com mais pull requests aguardando revisão e desenvolvedores precisando alternar com maior frequência entre implementação e análise de mudanças produzidas por outras pessoas.&lt;/p&gt;

&lt;p&gt;O problema não está necessariamente no uso da IA ou no aumento da produtividade individual. O que talvez precise ser revisto é o processo ao redor dessas ferramentas. Se conseguimos aumentar significativamente a velocidade de uma etapa do desenvolvimento, precisamos entender como as demais etapas podem acompanhar essa mudança sem reduzir a qualidade das entregas ou simplesmente transferir o gargalo para outro ponto do fluxo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Small batches como forma de reduzir o custo da revisão
&lt;/h2&gt;

&lt;p&gt;Uma prática que pode ajudar nesse cenário é o desenvolvimento em &lt;em&gt;small batches&lt;/em&gt;, discutido pelo DORA como uma das capacidades associadas à entrega contínua de software.&lt;/p&gt;

&lt;p&gt;A ideia consiste em organizar o trabalho em mudanças menores, independentes e passíveis de validação individual. Em vez de concentrar toda a implementação de uma tarefa em uma alteração extensa, procura-se identificar incrementos menores que possam ser implementados, testados e revisados separadamente.&lt;/p&gt;

&lt;p&gt;Em um primeiro momento, essa abordagem pode parecer contraditória para um time que já está lidando com um volume elevado de pull requests. Dividir uma implementação pode efetivamente aumentar o número absoluto de PRs e, se observarmos apenas essa métrica, o processo poderia parecer ainda mais sobrecarregado.&lt;/p&gt;

&lt;p&gt;Entretanto, quantidade de pull requests e esforço necessário para revisá-los não são necessariamente proporcionais.&lt;/p&gt;

&lt;p&gt;Um PR pequeno, com objetivo bem definido e poucas responsabilidades, tende a exigir menos contexto do reviewer. Também é mais simples compreender o impacto da alteração, identificar possíveis regressões e avaliar se a implementação corresponde ao que foi solicitado.&lt;/p&gt;

&lt;p&gt;Essa característica se torna especialmente importante quando parte significativa do código é produzida com auxílio de IA. Um agente pode modificar muitos arquivos e implementar diferentes aspectos de uma funcionalidade em poucos minutos, mas a velocidade com que essas alterações são produzidas não reduz automaticamente o esforço necessário para que outra pessoa compreenda as decisões tomadas.&lt;/p&gt;

&lt;p&gt;Por isso, talvez seja útil considerar o tamanho da unidade de revisão como uma restrição independente da capacidade de geração de código.&lt;/p&gt;

&lt;p&gt;Ao dividir uma implementação em mudanças menores, também passamos a receber feedback mais cedo. Uma decisão arquitetural questionada no primeiro batch pode ser corrigida antes que ela seja reproduzida nos próximos. Da mesma forma, um problema identificado em uma primeira implementação pode modificar as instruções fornecidas ao agente nas etapas seguintes.&lt;/p&gt;

&lt;p&gt;Nesse contexto, &lt;em&gt;small batches&lt;/em&gt; não seriam apenas uma forma de facilitar o code review, mas também uma maneira de criar ciclos mais frequentes de aprendizado durante a implementação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Utilizar automação antes de consumir atenção humana
&lt;/h2&gt;

&lt;p&gt;Outro aspecto que merece ser discutido é o momento em que uma alteração passa a consumir tempo de outro desenvolvedor.&lt;/p&gt;

&lt;p&gt;No fluxo tradicional, é comum que o autor conclua uma implementação, abra um pull request e solicite imediatamente uma revisão humana. Durante essa revisão, entretanto, podem surgir problemas relativamente mecânicos, como testes ausentes, inconsistências com padrões conhecidos do projeto, problemas simples de segurança, código duplicado ou situações que poderiam ter sido identificadas por ferramentas automatizadas.&lt;/p&gt;

&lt;p&gt;Com ferramentas modernas de análise e code review assistido por IA, parte dessas verificações pode acontecer antes que o pull request seja considerado pronto para revisão humana.&lt;/p&gt;

&lt;p&gt;A documentação do GitHub sobre o uso do Copilot Code Review ao longo do ciclo de vida de um pull request apresenta um fluxo semelhante. O PR pode permanecer inicialmente como &lt;em&gt;draft&lt;/em&gt;, receber revisões automatizadas e passar por ciclos de correção antes de ser disponibilizado para os demais desenvolvedores.&lt;/p&gt;

&lt;p&gt;Isso permite pensar em um fluxo no qual a implementação passa progressivamente por diferentes níveis de validação:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;implementação → testes → análise estática → verificações de segurança → revisão por IA → correções → revisão humana.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Essa organização não pressupõe que a revisão automatizada substitua o code review realizado por desenvolvedores. O objetivo seria reduzir a quantidade de problemas que chegam até essa etapa, permitindo que o reviewer dedique mais atenção às questões que dependem de conhecimento do produto, experiência arquitetural e compreensão do contexto da mudança.&lt;/p&gt;

&lt;p&gt;Em vez de utilizar parte significativa do tempo apontando problemas que poderiam ser detectados automaticamente, a revisão humana poderia se concentrar em aspectos como adequação da solução ao problema, impacto sobre outras áreas do sistema, complexidade introduzida, decisões arquiteturais e facilidade de manutenção futura.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transformar padrões de desenvolvimento em critérios explícitos
&lt;/h2&gt;

&lt;p&gt;Para que esse processo funcione de maneira consistente, existe uma questão adicional: as ferramentas automatizadas precisam conhecer os padrões que esperamos das implementações.&lt;/p&gt;

&lt;p&gt;Muitas equipes possuem um conjunto considerável de regras que nunca foram formalizadas completamente. Desenvolvedores mais experientes conhecem determinadas convenções porque trabalham no projeto há bastante tempo, participaram de decisões anteriores ou aprenderam esses padrões durante revisões de código.&lt;/p&gt;

&lt;p&gt;Quando passamos a delegar uma parcela maior da implementação para agentes de IA, depender exclusivamente desse conhecimento implícito se torna mais problemático.&lt;/p&gt;

&lt;p&gt;Uma alternativa seria documentar critérios de engenharia de maneira estruturada e, sempre que possível, utilizá-los também como entrada para ferramentas de desenvolvimento e revisão.&lt;/p&gt;

&lt;p&gt;Alguns desses critérios poderiam ser gerais e aplicáveis a praticamente qualquer alteração, como segurança, cobertura adequada de testes, tratamento de erros, compatibilidade com comportamentos existentes, observabilidade quando necessária e aderência aos padrões arquiteturais do projeto.&lt;/p&gt;

&lt;p&gt;Outros critérios poderiam ser ativados dependendo do tipo de alteração realizada.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alterações envolvendo APIs
&lt;/h3&gt;

&lt;p&gt;Uma implementação que cria ou modifica uma API poderia ser analisada considerando, entre outros aspectos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;autenticação e autorização;&lt;/li&gt;
&lt;li&gt;validação e sanitização dos dados recebidos;&lt;/li&gt;
&lt;li&gt;padronização das estruturas de resposta;&lt;/li&gt;
&lt;li&gt;utilização adequada dos códigos HTTP;&lt;/li&gt;
&lt;li&gt;escolha dos métodos HTTP;&lt;/li&gt;
&lt;li&gt;tratamento consistente de erros;&lt;/li&gt;
&lt;li&gt;idempotência quando aplicável;&lt;/li&gt;
&lt;li&gt;rate limiting quando necessário;&lt;/li&gt;
&lt;li&gt;compatibilidade com consumidores existentes;&lt;/li&gt;
&lt;li&gt;testes dos cenários de sucesso, erro e autorização.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Alterações envolvendo interfaces
&lt;/h3&gt;

&lt;p&gt;Para mudanças relacionadas à interface, os critérios poderiam considerar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;consistência com os componentes e padrões visuais existentes;&lt;/li&gt;
&lt;li&gt;responsividade;&lt;/li&gt;
&lt;li&gt;acessibilidade;&lt;/li&gt;
&lt;li&gt;comportamento durante carregamento;&lt;/li&gt;
&lt;li&gt;estados vazios e situações de erro;&lt;/li&gt;
&lt;li&gt;compatibilidade entre temas, quando aplicável;&lt;/li&gt;
&lt;li&gt;experiência de uso;&lt;/li&gt;
&lt;li&gt;SEO para páginas em que isso seja relevante;&lt;/li&gt;
&lt;li&gt;compatibilidade com os navegadores suportados;&lt;/li&gt;
&lt;li&gt;cobertura dos principais fluxos por testes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Alterações envolvendo persistência de dados
&lt;/h3&gt;

&lt;p&gt;Mudanças relacionadas ao banco de dados poderiam possuir outro conjunto de critérios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;impacto sobre dados existentes;&lt;/li&gt;
&lt;li&gt;estratégia de migration e rollback;&lt;/li&gt;
&lt;li&gt;índices necessários;&lt;/li&gt;
&lt;li&gt;integridade dos dados;&lt;/li&gt;
&lt;li&gt;privacidade e exposição de informações;&lt;/li&gt;
&lt;li&gt;impacto de performance;&lt;/li&gt;
&lt;li&gt;compatibilidade durante o processo de deploy;&lt;/li&gt;
&lt;li&gt;comportamento durante atualizações graduais da aplicação.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A mesma lógica poderia ser aplicada a integrações externas, autenticação, processamento assíncrono, infraestrutura, billing e outras áreas relevantes para cada projeto.&lt;/p&gt;

&lt;p&gt;Naturalmente, nem todos esses critérios deveriam se transformar em regras rígidas. Alguns podem ser verificados objetivamente por testes ou ferramentas de análise, enquanto outros funcionam melhor como perguntas que orientam a revisão.&lt;/p&gt;

&lt;p&gt;O ponto importante é reduzir a dependência de conhecimento exclusivamente tácito e criar uma referência comum para desenvolvedores, agentes de implementação e ferramentas de revisão.&lt;/p&gt;

&lt;h2&gt;
  
  
  Um possível fluxo de desenvolvimento assistido por IA
&lt;/h2&gt;

&lt;p&gt;Combinando essas práticas, poderíamos experimentar um processo no qual uma tarefa passa pelas seguintes etapas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;entendimento do problema e definição do escopo;&lt;/li&gt;
&lt;li&gt;identificação de batches pequenos e independentes;&lt;/li&gt;
&lt;li&gt;implementação de um batch;&lt;/li&gt;
&lt;li&gt;execução dos testes automatizados;&lt;/li&gt;
&lt;li&gt;execução de linters, análise estática e verificações de segurança;&lt;/li&gt;
&lt;li&gt;revisão do código por IA utilizando os padrões definidos pelo projeto;&lt;/li&gt;
&lt;li&gt;correção ou avaliação dos apontamentos encontrados;&lt;/li&gt;
&lt;li&gt;disponibilização do pull request para revisão humana;&lt;/li&gt;
&lt;li&gt;revisão, aprovação e merge;&lt;/li&gt;
&lt;li&gt;observação do comportamento após a entrega.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Esse fluxo também cria uma separação mais clara entre o que esperamos da automação e o que esperamos das pessoas envolvidas no processo.&lt;/p&gt;

&lt;p&gt;Ferramentas automatizadas são particularmente adequadas para verificações repetitivas, comparação com padrões conhecidos e análise sistemática de grandes quantidades de código. Desenvolvedores, por outro lado, continuam sendo fundamentais para avaliar decisões que dependem de contexto, experiência, conhecimento do produto e compreensão das consequências de longo prazo de uma implementação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Small batches sem controle de WIP não resolvem o problema
&lt;/h2&gt;

&lt;p&gt;Existe uma ressalva importante nessa proposta.&lt;/p&gt;

&lt;p&gt;Dividir uma tarefa em cinco pull requests menores não necessariamente melhora o fluxo se os cinco forem produzidos imediatamente e colocados simultaneamente na fila de revisão. Nesse cenário, apenas substituímos uma alteração grande por várias alterações menores acumuladas no mesmo ponto do processo.&lt;/p&gt;

&lt;p&gt;Por esse motivo, acredito que a discussão sobre &lt;em&gt;small batches&lt;/em&gt; precisa estar associada ao controle de WIP.&lt;/p&gt;

&lt;p&gt;Se o desenvolvimento assistido por IA permite produzir código mais rapidamente do que conseguimos revisar, talvez não seja desejável utilizar toda essa capacidade simplesmente para iniciar mais trabalho.&lt;/p&gt;

&lt;p&gt;Uma alternativa seria utilizar parte desse ganho de produtividade para concluir completamente uma quantidade menor de mudanças antes de iniciar outras.&lt;/p&gt;

&lt;p&gt;Isso pode significar que um desenvolvedor, enquanto aguarda uma revisão, dedique tempo à melhoria de testes, investigação de outros aspectos da mesma tarefa, documentação ou revisão de PRs de outros membros do time, em vez de iniciar imediatamente diversas novas implementações.&lt;/p&gt;

&lt;p&gt;Nesse modelo, o objetivo não seria maximizar a utilização individual de cada desenvolvedor, mas melhorar o fluxo do trabalho através do sistema como um todo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como validar se essa abordagem realmente funciona
&lt;/h2&gt;

&lt;p&gt;Apesar de essas práticas possuírem fundamentos conhecidos na engenharia de software, acredito que seria precipitado assumir que essa combinação necessariamente funcionará para qualquer equipe ou projeto.&lt;/p&gt;

&lt;p&gt;O impacto da codificação assistida por IA ainda está sendo compreendido, e diferentes times possuem características bastante distintas em relação a tamanho, arquitetura, processo de revisão e frequência de deploy.&lt;/p&gt;

&lt;p&gt;Por isso, talvez a melhor forma de avaliar essa proposta seja tratá-la como um experimento.&lt;/p&gt;

&lt;p&gt;Durante algumas semanas, uma equipe poderia estabelecer algumas regras simples: limitar o tamanho das mudanças, controlar a quantidade de trabalho simultaneamente em revisão, manter pull requests inicialmente como &lt;em&gt;draft&lt;/em&gt; e executar as verificações automatizadas e revisões por IA antes de solicitar uma revisão humana.&lt;/p&gt;

&lt;p&gt;A partir daí, poderíamos observar algumas métricas, como tempo entre abertura do PR e primeira revisão, tempo total até o merge, tamanho médio das alterações, quantidade de ciclos de revisão, número de problemas encontrados antes da revisão humana, quantidade de problemas encontrados depois do merge e tempo dedicado pelos desenvolvedores a code review.&lt;/p&gt;

&lt;p&gt;Também seria importante coletar informações qualitativas. Um processo pode apresentar métricas melhores e, ainda assim, aumentar a frustração dos desenvolvedores ou criar burocracia desnecessária. Perguntas simples sobre a facilidade de compreender os PRs, qualidade dos comentários automatizados e percepção de carga de revisão ajudariam a complementar os números.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que estamos tentando otimizar?
&lt;/h2&gt;

&lt;p&gt;Talvez uma das discussões mais importantes trazidas pela adoção de IA seja justamente a definição do que entendemos como produtividade no desenvolvimento de software.&lt;/p&gt;

&lt;p&gt;Se avaliarmos produtividade principalmente pela quantidade de código produzido ou pelo número de tarefas implementadas, ferramentas de IA provavelmente apresentarão ganhos expressivos. Entretanto, essas métricas representam apenas uma parte do processo necessário para transformar uma necessidade de produto em software funcionando de maneira confiável em produção.&lt;/p&gt;

&lt;p&gt;Uma tarefa implementada, mas aguardando revisão durante vários dias, ainda representa trabalho em andamento. Da mesma forma, uma grande quantidade de código produzida rapidamente não representa necessariamente uma melhoria se aumentar o custo de revisão, introduzir regressões ou exigir diversas rodadas de correção posteriormente.&lt;/p&gt;

&lt;p&gt;Talvez seja mais útil observar o tempo necessário para que uma mudança percorra todo o fluxo, desde o início da implementação até sua integração e disponibilização, considerando também a qualidade obtida nesse processo.&lt;/p&gt;

&lt;p&gt;Nesse cenário, a principal oportunidade oferecida pela IA não estaria apenas em escrever código mais rapidamente. Ela também pode ser utilizada para antecipar verificações, documentar decisões, aumentar a cobertura de testes e reduzir o trabalho repetitivo realizado durante revisões.&lt;/p&gt;

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

&lt;p&gt;O desenvolvimento assistido por IA está aumentando a capacidade de implementação das equipes, mas esse aumento não necessariamente ocorre na mesma proporção em todas as etapas do processo de engenharia. Revisão, validação, compreensão do impacto das mudanças e tomada de decisões continuam exigindo atenção e contexto.&lt;/p&gt;

&lt;p&gt;Por isso, acredito que existe espaço para experimentar processos que combinem desenvolvimento em pequenos batches, controle de WIP, automação das verificações objetivas e revisão assistida por IA antes da revisão humana.&lt;/p&gt;

&lt;p&gt;A intenção não é criar mais etapas burocráticas nem estabelecer que toda alteração precise passar pelo mesmo conjunto de verificações. Pelo contrário, um bom processo deveria ser capaz de selecionar os critérios relevantes de acordo com o tipo e o risco da mudança.&lt;/p&gt;

&lt;p&gt;O resultado que buscamos também não deveria ser simplesmente produzir mais pull requests ou aumentar a quantidade de código entregue por desenvolvedor. O objetivo seria reduzir o tempo e o esforço necessários para que uma alteração percorra o processo de desenvolvimento com um nível adequado de confiança.&lt;/p&gt;

&lt;p&gt;Essa é a hipótese que considero mais interessante para discussão: &lt;strong&gt;se a IA está aumentando significativamente nossa capacidade de produzir software, como devemos adaptar o restante do processo de engenharia para que esse ganho seja convertido em entregas melhores, e não apenas em mais trabalho aguardando revisão?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A resposta provavelmente dependerá de cada equipe. Justamente por isso, acredito que vale experimentar, medir os resultados e compartilhar o que funcionar — e também o que não funcionar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;p&gt;DORA — &lt;em&gt;Working in small batches&lt;/em&gt;&lt;br&gt;
&lt;a href="https://dora.dev/capabilities/working-in-small-batches/" rel="noopener noreferrer"&gt;https://dora.dev/capabilities/working-in-small-batches/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub Docs — &lt;em&gt;Use GitHub Copilot code review across the pull request lifecycle&lt;/em&gt;&lt;br&gt;
&lt;a href="https://docs.github.com/en/copilot/tutorials/use-copilot-code-review-across-the-pull-request-lifecycle" rel="noopener noreferrer"&gt;https://docs.github.com/en/copilot/tutorials/use-copilot-code-review-across-the-pull-request-lifecycle&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>coding</category>
      <category>productivity</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 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>
