<?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: Marcelo Mendes</title>
    <description>The latest articles on DEV Community by Marcelo Mendes (@marcelovmendes).</description>
    <link>https://dev.to/marcelovmendes</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%2F1291404%2Fda84842a-04fa-41df-b4db-9e5b1e6fec09.jpeg</url>
      <title>DEV Community: Marcelo Mendes</title>
      <link>https://dev.to/marcelovmendes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/marcelovmendes"/>
    <language>en</language>
    <item>
      <title>De ferramenta individual ao básico de prática de time: estruturando IA no desenvolvimento.</title>
      <dc:creator>Marcelo Mendes</dc:creator>
      <pubDate>Wed, 24 Jun 2026 01:22:04 +0000</pubDate>
      <link>https://dev.to/marcelovmendes/de-ferramenta-individual-ao-basico-de-pratica-de-time-estruturando-ia-no-desenvolvimento-5hjj</link>
      <guid>https://dev.to/marcelovmendes/de-ferramenta-individual-ao-basico-de-pratica-de-time-estruturando-ia-no-desenvolvimento-5hjj</guid>
      <description>&lt;p&gt;A maioria de nós desenvolvedores já escreve código com IA diariamente. O que eu acredito ser mais incomum é um time inteiro usar IA de forma padronizada sem cair em dois extremos: virar muito burocrático e ninguém seguir, ou continuar cada um por si e ninguém saber se está no caminho certo.&lt;/p&gt;

&lt;p&gt;Esse texto é sobre o meio-termo. Não é um tutorial de setup (a documentação oficial faz isso melhor e mais atualizada que qualquer post), e não é um case de sucesso ou com resultados, porque acho que ninguém tem ainda. É a forma como interpretei o problema depois de estudar os materiais que a Anthropic e a Cognition publicaram sobre o assunto, lido pela lente de quem trabalha com desenvolvimento web e sistemas distribuídos.&lt;/p&gt;

&lt;h3&gt;
  
  
  O problema raramente é o prompt
&lt;/h3&gt;

&lt;p&gt;A mudança mais importante de perspectiva é parar de pensar no agente de IA como só "o modelo" e pensar nele como modelo mais o aparato em volta. Esse aparato tem um nome na literatura, chamam de harness. São as ferramentas, as verificações, o contexto que você fornece, os limites que você impõe, o loop de feedback que corrige o modelo quando ele erra.&lt;/p&gt;

&lt;p&gt;Quando uma sessão de IA é ruim, muitas pessoas culpam de cara o modelo ou o prompt. Porém, na minha opinião, muitas vezes o problema está no harness: faltou contexto sobre como o código funciona, não havia testes pra validar se algo quebrou, o modelo não tinha como verificar o próprio trabalho. É o mesmo raciocínio de quando um serviço se comporta mal em produção e a causa não está no código da request, mas sim na ausência de timeout, retry, de métricas que mostrariam o problema antes.&lt;/p&gt;

&lt;p&gt;Guarde essa palavra, harness é a infraestrutura em volta da IA, e quase tudo que vamos abordar aqui é uma forma de construí-la. Vamos começar pela decisão mais prática que ela permite.&lt;/p&gt;

&lt;h3&gt;
  
  
  Autonomia deveria seguir verificabilidade, não dificuldade
&lt;/h3&gt;

&lt;p&gt;O instinto é dar mais autonomia pra IA em tarefas fáceis e menos em tarefas difíceis. Porém acho que o eixo é outro, focado em dar mais autonomia onde o trabalho é verificável, e menos onde não é.&lt;br&gt;
Um serviço com boa cobertura de testes oferece ao agente um loop de feedback objetivo, ele edita, roda o teste, vê se quebrou, corrige. Você pode delegar bastante e revisar o resultado. Já um serviço sem testes não oferece esse loop, e aí a IA pode estar acelerando na direção errada sem que ninguém perceba, porque não há nada dizendo que o comportamento mudou. Nesse caso, o uso mais valioso da IA não é gerar a feature, é gerar os testes que capturam o comportamento atual e, com isso, transformar um serviço nebuloso em algo verificável. Você paga a dívida com a própria ferramenta antes de confiar nela.&lt;/p&gt;

&lt;p&gt;Porém a verificabilidade não cai do céu: ela é parte do harness que você constrói. A forma mais simples é um arquivo na raiz do seu repo, o famoso CLAUDE.md (se você estiver usando os produtos da Anthropic), descrevendo o projeto pro agente, como buildar, como rodar os testes, as convenções, o que não tocar. Algo nessa linha:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# nome-do-serviço&lt;/span&gt;
O que ele faz, em uma frase. Stack principal.

&lt;span class="gu"&gt;## Comandos&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Build, teste do módulo, subir local

&lt;span class="gu"&gt;## Convenções (inegociáveis)&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Tratamento de erro padrão, validação na borda, etc.

&lt;span class="gu"&gt;## Não tocar sem aprovação humana&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Migrations, contratos públicos, fluxo de pagamento
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Parece algo muito simples mas não é. Esse arquivo é insumo de toda sessão futura de IA, e é também documentação de onboarding básica pra gente nova. Porém, ele precisa estar sempre atualizado porque, se não, ele não fica só inútil, como também passa a contaminar o contexto, fazendo a IA gerar código errado com confiança. Documentação deixou de ser cortesia e virou parte da configuração de execução.&lt;/p&gt;

&lt;p&gt;O fluxo que decorre disso é o mesmo de sempre, só esclarecendo:&lt;br&gt;
explorar o código antes de escrever, propor um plano e ter esse plano revisado por um humano antes de gerar a primeira linha, implementar em etapas com verificação a cada passo, revisar o diff completo. O ponto de maior alavancagem é o plano. Errar no plano custa dez vezes mais do que errar numa linha, e é o momento mais barato pra uma pessoa intervir.&lt;/p&gt;

&lt;p&gt;Por fim, os guardrails que não dependem do julgamento do modelo. Um hook que roda formatação e compilação a cada edição transforma "confio que a IA não quebrou o build" em "o build não passa, então não avança":&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="c"&gt;# roda a cada edição; exit != 0 devolve o erro pro agente corrigir&lt;/span&gt;
formatar &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$arquivo&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; compilar &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E uma lista de negação que impede a IA de editar migrations, contratos públicos ou código de pagamento sem aprovação. Repare que isso não é o modelo "decidindo" respeitar a regra, é o modelo sendo impedido. Determinismo onde determinismo importa.&lt;/p&gt;

&lt;h3&gt;
  
  
  O critério não é leitura ou escrita, é independência
&lt;/h3&gt;

&lt;p&gt;Existe uma tentação forte, quando se fala em múltiplos agentes, de montar uma "equipe": um agente arquiteto, um agente QA, um agente revisor, todos decidindo. Parece legal e promissor, mas o problema é que a decisão entre agentes tende a ser uma votação por maioria, não por colaboração, eles convergem pro consenso em vez de pegar os erros uns dos outros. O critério útil não é leitura contra escrita ou nível de dificuldade, é na verdade independência: o trabalho se decompõe em partes que não se conversam, ou é uma cadeia de raciocínio onde cada passo depende do anterior?&lt;/p&gt;

&lt;p&gt;A evidência direta é de um estudo que li recentemente do Google Research (&lt;a href="https://arxiv.org/abs/2512.08296" rel="noopener noreferrer"&gt;Kim et al., "Towards a Science of Scaling Agent Systems"&lt;/a&gt;) mostrando um dado gritante:&lt;br&gt;
Em tarefas separáveis, a coordenação entre agentes melhorou o desempenho em até 81%; já em tarefas estritamente sequenciais, degradou de 39% a 70%, com a complexidade quase idêntica entre os dois grupos. E o mesmo estudo mostra que modelos melhores não fazem diferença nesse caso, quanto mais capaz o agente sozinho, menos sobra pra a coordenação compensar, então a barra pra o multi-agente valer a pena sobe com o tempo, e não o contrário. O subagente serve pra isolar contexto, como você isola um processo, não para dar personalidade a papéis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Como saber se valeu (e a métrica que mente)
&lt;/h3&gt;

&lt;p&gt;Chegamos na parte que mais me incomoda no discurso atual sobre IA em times, e é onde quero ser mais direto.&lt;/p&gt;

&lt;p&gt;A métrica que mais aparece é "percentual de código gerado por IA". Ela parece boa porque é fácil de extrair e cresce rapidamente. E ela mede a coisa errada. Código gerado em volume não é valor entregue, pode até ser exatamente o oposto, código a mais pra revisar, manter e debugar. Otimizar por essa métrica é otimizar pra parecer produtivo.&lt;/p&gt;

&lt;p&gt;O que importa medir é se o trabalho está saindo mais rápido sem piorar de qualidade. E aqui há uma vantagem metodológica interessante: como a adoção de IA num time é gradual e voluntária, você naturalmente tem, no mesmo período de tempo, demandas feitas com IA e demandas feitas sem. Isso é um grupo de comparação fácil de validar. Comparar "com IA" contra "sem IA" no mesmo intervalo de tempo é muito mais confiável que comparar "antes" contra "depois", porque elimina as variáveis que mudam ao longo do tempo: composição do time, fase do produto, pressão de prazo.&lt;/p&gt;

&lt;p&gt;Para isso funcionar, basta uma marcação que diferencie as demandas que passaram pela IA das que não passaram. Com essa separação, as métricas que você provavelmente já coleta passam a contar uma história: tempo do início ao fim da demanda, quantidade entregue por período, tempo gasto em revisão, cards que geraram bugs.&lt;/p&gt;

&lt;p&gt;Algo que eu acho que tem que ter cuidado é nunca medir velocidade sozinha. Velocidade sem qualidade é entregar problema mais rápido, repare que bati bastante nessa tecla, qualidade é muito indispensável. Toda métrica de tempo precisa estar emparelhada com uma de qualidade: quanto de retrabalho aquela demanda gerou, quantos bugs apareceram depois de ir pra produção.&lt;/p&gt;

&lt;h3&gt;
  
  
  O que isso é, e o que não é
&lt;/h3&gt;

&lt;p&gt;Não tenho um número pra te vender. Tenho um jeito de raciocinar sobre o problema tratando o agente como modelo mais harness e investindo na infra, não no prompt; dê mais autonomia onde há verificação e construa verificação onde não há; paralelize leitura e serialize decisão; e acima de tudo meça o que importa de forma realista. Num assunto onde sobra empolgação e falta ceticismo, talvez essa última parte seja a mais útil.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Criando service discovery com spring cloud gateway e eureka</title>
      <dc:creator>Marcelo Mendes</dc:creator>
      <pubDate>Mon, 10 Feb 2025 16:31:15 +0000</pubDate>
      <link>https://dev.to/marcelovmendes/criando-service-discovery-com-spring-cloud-gateway-e-eureka-363f</link>
      <guid>https://dev.to/marcelovmendes/criando-service-discovery-com-spring-cloud-gateway-e-eureka-363f</guid>
      <description></description>
      <category>spring</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Como microsserviços se enxergam: Service Discovery com Spring Cloud Gateway e Eureka</title>
      <dc:creator>Marcelo Mendes</dc:creator>
      <pubDate>Mon, 10 Feb 2025 00:41:04 +0000</pubDate>
      <link>https://dev.to/marcelovmendes/criando-service-discovery-com-spring-cloud-gateway-e-eureka-158h</link>
      <guid>https://dev.to/marcelovmendes/criando-service-discovery-com-spring-cloud-gateway-e-eureka-158h</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Nesse artigo, vamos explorar dois patterns amplamente utilizados em arquiteturas de microsserviços: &lt;strong&gt;Service Discovery&lt;/strong&gt; e &lt;strong&gt;API Gateway&lt;/strong&gt;. Veremos suas utilidades, benefícios e como implementá-los utilizando &lt;strong&gt;Spring Cloud Gateway&lt;/strong&gt; e &lt;strong&gt;Eureka Server&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é um Service Discovery?
&lt;/h2&gt;

&lt;p&gt;Em um ambiente de microsserviços, um cliente pode precisar se comunicar com diversas APIs que rodam em diferentes portas e servidores. Mas o cliente geralmente não sabe os endereços exatos dessas APIs.&lt;/p&gt;

&lt;p&gt;Imagine o seguinte cenário:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0u27ncncrxmm1kzrmycr.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%2F0u27ncncrxmm1kzrmycr.png" alt="Diagrama ilustrando um cliente tentando acessar várias APIs sem um Service Discovery" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se não houver alguma forma para descobrir automaticamente os serviços disponíveis, precisaríamos gerenciar manualmente os endereços de cada API. Isso torna a manutenção do sistema mais complexa e suscetível a erros.&lt;/p&gt;

&lt;p&gt;E pra isso temos o*&lt;em&gt;Service Discovery&lt;/em&gt;&lt;em&gt;. Ele age como uma espécie de banco de registro, onde as aplicações ao subirem, se registram nele permitindo que os clientes descubram automaticamente onde eles estão rodando. No ecossistema do Spring, utilizamos o **Eureka Server&lt;/em&gt;* para essa funcionalidade.&lt;/p&gt;

&lt;p&gt;Quando as aplicações são iniciadas, elas se registram no Eureka Server. Assim, qualquer cliente pode consultar o Eureka e descobrir quais serviços estão disponíveis e onde eles estão rodando.&lt;/p&gt;

&lt;p&gt;Com essa abordagem, um &lt;strong&gt;API Gateway&lt;/strong&gt; pode atuar apenas como um roteador, passando para o Eureka a responsabilidade de gerenciar os registros dos serviços:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2b8l2j64s0nunkhpt10h.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%2F2b8l2j64s0nunkhpt10h.png" alt="Diagrama mostrando como o Service Discovery facilita a comunicação entre serviços" width="800" height="630"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementação
&lt;/h2&gt;

&lt;p&gt;Agora, vamos implementar um Gateway que busca os serviços registrados no Eureka Server. O código completo deste projeto está disponível no repositório no final do artigo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Criando o Eureka Server
&lt;/h3&gt;

&lt;p&gt;O primeiro passo é criar um projeto Spring Boot. Eu utilizei o &lt;strong&gt;Spring Initializr&lt;/strong&gt; mas faça como preferir. Selecionando a dependência &lt;strong&gt;Eureka Server&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7squxkbh2numvf56gt48.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%2F7squxkbh2numvf56gt48.png" alt="Imagem do Spring Initializr configurado para Eureka Server" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Após criar o projeto, abra-o na sua IDE e adicione as seguintes configurações no arquivo &lt;code&gt;application.properties&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;server.port&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;8761&lt;/span&gt;
&lt;span class="py"&gt;eureka.client.register-with-eureka&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;false&lt;/span&gt;
&lt;span class="py"&gt;eureka.client.fetch-registry&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;server.port=8761&lt;/code&gt;: Define a porta padrão do Eureka Server.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eureka.client.register-with-eureka=false&lt;/code&gt;: Como este é o servidor do Eureka, ele não precisa se registrar nele mesmo.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eureka.client.fetch-registry=false&lt;/code&gt;: Ele não precisa buscar registros, apenas fornecer informações aos clientes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agora, no arquivo &lt;code&gt;ServiceDiscoveryApplication&lt;/code&gt;, adicionamos a anotação &lt;code&gt;@EnableEurekaServer&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@SpringBootApplication&lt;/span&gt;
&lt;span class="nd"&gt;@EnableEurekaServer&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ServiceDiscoveryApplication&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;SpringApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ServiceDiscoveryApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, ao rodar o projeto, conseguimos visualizar a interface do Eureka Server acessando &lt;code&gt;http://localhost:8761&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsrp0gqe6smww91gkex5m.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%2Fsrp0gqe6smww91gkex5m.png" alt="Imagem da interface do Eureka Server" width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Por enquanto não temos nenhum serviço no registro porque não subimos nenhuma API no Eureka Server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Criando Serviços Cliente (API-01 e API-02)
&lt;/h3&gt;

&lt;p&gt;Vamos criar duas APIs simples (&lt;code&gt;api-01&lt;/code&gt; e &lt;code&gt;api-02&lt;/code&gt;) que serão registradas no Eureka. Para isso, utilizamos o &lt;strong&gt;Spring Initializr&lt;/strong&gt;, adicionando as dependências:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgefx5lcxqgk7v7m7gjm6.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%2Fgefx5lcxqgk7v7m7gjm6.png" alt="Imagem do Spring Initializr configurado web e Eureka Client" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Eureka Client&lt;/strong&gt; (para registro no Eureka Server)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spring Web&lt;/strong&gt; (para expor endpoints)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Configurações
&lt;/h4&gt;

&lt;p&gt;No &lt;code&gt;application.properties&lt;/code&gt; de cada API, adicionamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;server.port&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;8181  # Ou outra porta para a segunda API&lt;/span&gt;
&lt;span class="py"&gt;eureka.client.service-url.default-zone&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;http://localhost:8761/eureka/&lt;/span&gt;
&lt;span class="py"&gt;eureka.client.register-with-eureka&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;eureka.client.fetch-registry&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Criando um endpoint de teste
&lt;/h4&gt;

&lt;p&gt;Agora, criamos um controlador simples para expor um endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HealthCheckController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/health"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;healthCheck&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"API-01 está saudável!"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso, ao rodarmos as APIs, elas se registrarão automaticamente no Eureka Server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj8xewbaujqp5j6kykukw.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%2Fj8xewbaujqp5j6kykukw.png" alt=" " width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note que na imagem temos o gateway exposto também, ele será implementado no próximo passo.&lt;/p&gt;

&lt;p&gt;Bom, já criamos o Eureka Server, a api-01 e a api-02. Elas já estão rodando, registradas e podem buscar informações no nosso serviço de descoberta. Agora temos algo parecido com um livro de endereços, onde conseguimos acessar as informações das APIs sem precisar lembrar de cada endereço e porta manualmente.&lt;br&gt;
Mas ainda falta algo. A gente não quer que o cliente precise saber os endereços específicos de cada API, certo? Para resolver isso, usamos um gateway. Ele vai consultar o registro de serviços e passar um único ponto de acesso para os clientes, garantindo que todas as requisições entre microsserviços sejam roteadas de forma transparente.&lt;/p&gt;
&lt;h3&gt;
  
  
  Criando o API Gateway
&lt;/h3&gt;

&lt;p&gt;O próximo passo é criar o &lt;strong&gt;Spring Cloud Gateway&lt;/strong&gt;, que será responsável por rotear as requisições para os serviços registrados no Eureka.&lt;/p&gt;

&lt;p&gt;No &lt;strong&gt;Spring Initializr&lt;/strong&gt;, adicionamos as dependências:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Spring Cloud Gateway&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Eureka Client&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Configurações do Gateway
&lt;/h4&gt;

&lt;p&gt;No &lt;code&gt;application.properties&lt;/code&gt;, adicionamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;eureka.client.service-url.default-zone&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;http://localhost:8761/eureka/&lt;/span&gt;
&lt;span class="py"&gt;eureka.client.register-with-eureka&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;eureka.client.fetch-registry&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;

&lt;span class="py"&gt;spring.cloud.gateway.discovery.locator.enabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;spring.cloud.gateway.discovery.locator.lower-case-service-id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;spring.cloud.gateway.discovery.locator.enabled=true&lt;/code&gt;: Permite que o Gateway descubra automaticamente os serviços registrados no Eureka.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;spring.cloud.gateway.discovery.locator.lower-case-service-id=true&lt;/code&gt;: Garante que os nomes das aplicações sejam tratados em letras minúsculas, tornando as requisições mais legíveis.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testando a Comunicação
&lt;/h3&gt;

&lt;p&gt;Agora que o Gateway e os serviços estão configurados, podemos testar a comunicação.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Rodamos o Eureka Server&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rodamos as APIs (&lt;code&gt;api-01&lt;/code&gt; e &lt;code&gt;api-02&lt;/code&gt;)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rodamos o API Gateway&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verificamos o Eureka Server&lt;/strong&gt; (&lt;code&gt;http://localhost:8761&lt;/code&gt;)

&lt;ul&gt;
&lt;li&gt;As APIs devem aparecer como registradas.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testamos o roteamento&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;http://localhost:8080/api-01/api/health&lt;/code&gt; → Deve retornar: &lt;code&gt;API-01 está saudável!&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;http://localhost:8080/api-02/api/health&lt;/code&gt; → Deve retornar: &lt;code&gt;API-02 está saudável!&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;O Gateway está funcionando corretamente, roteando as requisições para os serviços automaticamente!&lt;/p&gt;

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

&lt;p&gt;Com essa implementação, conseguimos:&lt;/p&gt;

&lt;p&gt;✅ Criar um &lt;strong&gt;Eureka Server&lt;/strong&gt; para gerenciar o registro de serviços.&lt;br&gt;
✅ Criar &lt;strong&gt;APIs clientes&lt;/strong&gt; que se registram automaticamente no Eureka.&lt;br&gt;
✅ Configurar um &lt;strong&gt;API Gateway&lt;/strong&gt; que roteia as requisições sem necessidade de mapear manualmente os endpoints.&lt;/p&gt;

&lt;p&gt;Essa abordagem reduz o acoplamento entre os serviços e facilita a comunicação dinâmica entre microsserviços.&lt;/p&gt;

&lt;p&gt;📌 O código completo do projeto pode ser acessado aqui (&lt;a href="https://github.com/Marcelovmendes/service-discovery" rel="noopener noreferrer"&gt;https://github.com/Marcelovmendes/service-discovery&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Gostou do artigo? Compartilhe e deixe seu comentário! 🚀&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Reflection em Java: quando o código olha para si mesmo</title>
      <dc:creator>Marcelo Mendes</dc:creator>
      <pubDate>Fri, 20 Dec 2024 23:41:05 +0000</pubDate>
      <link>https://dev.to/marcelovmendes/reflections-em-java-uma-ferramenta-poderosa-e-seus-cuidados-4m3m</link>
      <guid>https://dev.to/marcelovmendes/reflections-em-java-uma-ferramenta-poderosa-e-seus-cuidados-4m3m</guid>
      <description>&lt;p&gt;Vamos explorar o que é Reflections, seus usos e cuidados, e como aplicá-lo na prática.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é Reflection?
&lt;/h2&gt;

&lt;p&gt;Normalmente, quando você escreve código em Java, precisa saber de antes com quais classes está lidando. Você chama usuario.getNome() porque sabe que existe uma classe Usuario com esse método.&lt;/p&gt;

&lt;p&gt;Reflection quebra essa regra. Com ela, o código consegue inspecionar e manipular classes, campos, métodos e construtores em tempo de execução, mesmo que você não conheça a classe na hora de compilar, e mesmo que os membros sejam privados.&lt;/p&gt;

&lt;p&gt;É uma ferramenta poderosa para situações dinâmicas, onde você não sabe de antes com o que vai trabalhar. Mas, como veremos mais para frente, é poder que vem com responsabilidade rs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Onde ela aparece?
&lt;/h2&gt;

&lt;p&gt;Você provavelmente já usou Reflection sem perceber, porque ela está por trás de várias ferramentas que usamos todo dia:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frameworks e bibliotecas.&lt;/strong&gt; O JUnit usa Reflection para encontrar e rodar seus métodos de teste automaticamente. É por isso que basta anotar um método com &lt;code&gt;@Test&lt;/code&gt; para ele ser executado, sem você precisar registrar nada manualmente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conversão de objetos.&lt;/strong&gt; Bibliotecas como Jackson e Gson transformam objetos em JSON sem conhecer suas classes. Elas recebem um objeto qualquer, olham os campos dele em tempo de execução e montam o JSON a partir disso.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Carregar coisas dinamicamente.&lt;/strong&gt; Sistemas de plugins, por exemplo, precisam instanciar classes que só são conhecidas quando o programa já está rodando.&lt;/p&gt;

&lt;p&gt;O ponto em comum nesses casos é sempre o mesmo: a ferramenta não sabe de antemão com qual classe vai lidar. É aí que Reflection brilha.&lt;/p&gt;

&lt;h2&gt;
  
  
  Na prática
&lt;/h2&gt;

&lt;p&gt;Vamos fazer algo parecido com o que o Jackson faz: uma função que recebe qualquer objeto e mostra os campos dele com seus valores, sem conhecer a classe.&lt;/p&gt;

&lt;p&gt;Imagine uma classe simples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Usuario&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Marcelo"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;idade&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;ativo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora a função que inspeciona qualquer objeto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.lang.reflect.Field&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Inspetor&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;descrever&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;classe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getClass&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Tipo: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;classe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getSimpleName&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Field&lt;/span&gt; &lt;span class="n"&gt;campo&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;classe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDeclaredFields&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;campo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setAccessible&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// libera o acesso mesmo se o campo for privado&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;valor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;campo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;campo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" = "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;valor&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IllegalAccessException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Não consegui ler o campo "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;campo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chamando assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Inspetor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;descrever&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Usuario&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A saída é:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Tipo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Usuario&lt;/span&gt;
&lt;span class="s"&gt;nome = Marcelo&lt;/span&gt;
&lt;span class="s"&gt;idade = &lt;/span&gt;&lt;span class="m"&gt;27&lt;/span&gt;
&lt;span class="s"&gt;ativo = &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repare que o &lt;code&gt;Inspetor&lt;/code&gt; não sabe nada sobre a classe &lt;code&gt;Usuario&lt;/code&gt;. Ele descobre tudo na hora. Se você passar um &lt;code&gt;Produto&lt;/code&gt;, um &lt;code&gt;Pedido&lt;/code&gt; ou qualquer outra classe, ele funciona do mesmo jeito. Esse é o tipo de problema em que Reflection é a escolha certa: quando a estrutura do objeto é genuinamente desconhecida.&lt;/p&gt;

&lt;h3&gt;
  
  
  Entendendo o fluxo
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;getClass()&lt;/code&gt; devolve um objeto &lt;code&gt;Class&lt;/code&gt;, que é o ponto de partida de quase tudo em Reflection.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getDeclaredFields()&lt;/code&gt; lista os campos declarados na classe.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setAccessible(true)&lt;/code&gt; libera o acesso a campos privados. Sem isso, o Java bloqueia a leitura.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;field.get(obj)&lt;/code&gt; lê o valor daquele campo no objeto que passamos.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Ferramentas principais da classe Reflection
&lt;/h2&gt;

&lt;p&gt;O pacote java.lang.reflect oferece várias classes e métodos que tornam possível manipular dinamicamente os elementos de uma classe. Aqui estão algumas das ferramentas mais importantes:&lt;/p&gt;

&lt;h3&gt;
  
  
  Class: O ponto de partida
&lt;/h3&gt;

&lt;p&gt;A classe Class é usada para obter informações e manipular classes. É frequentemente a porta de entrada para outras operações de Reflection.&lt;/p&gt;

&lt;h4&gt;
  
  
  Métodos úteis:
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;getDeclaredFields()&lt;/code&gt;: Retorna todos os campos declarados na classe.&lt;br&gt;
&lt;code&gt;getDeclaredMethods()&lt;/code&gt;: Retorna todos os métodos declarados na classe.&lt;br&gt;
&lt;code&gt;getDeclaredConstructors()&lt;/code&gt;: Retorna todos os construtores declarados na classe.&lt;br&gt;
&lt;code&gt;getSuperclass()&lt;/code&gt;: Obtém a superclasse da classe.&lt;br&gt;
&lt;code&gt;getInterfaces()&lt;/code&gt;: Retorna as interfaces implementadas pela classe.&lt;/p&gt;




&lt;h2&gt;
  
  
  Os cuidados
&lt;/h2&gt;

&lt;p&gt;Reflection é útil, mas mexe em garantias que o Java normalmente oferece. Por isso, alguns pontos de atenção:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quebra o encapsulamento.&lt;/strong&gt; Você consegue acessar campos e métodos privados, ignorando os modificadores de acesso. Aquele &lt;code&gt;private&lt;/code&gt; que protegia o campo deixa de proteger.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Os erros aparecem só ao rodar.&lt;/strong&gt; Em código normal, se você erra o nome de um método, o compilador avisa na hora. Com Reflection, esses erros só aparecem em tempo de execução, o que torna bugs mais difíceis de pegar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tem custo de desempenho.&lt;/strong&gt; Chamadas via Reflection são mais lentas que chamadas normais. Na maioria dos casos isso é irrelevante, mas em código que roda milhões de vezes pode pesar.&lt;/p&gt;

&lt;p&gt;A regra prática é simples: antes de usar Reflection, pergunte se não existe um jeito mais direto de resolver. Muitas vezes uma interface, um &lt;code&gt;Map&lt;/code&gt; ou um pouco de polimorfismo resolvem o problema sem abrir mão das garantias da linguagem. Reflection é ótima quando você realmente não tem como saber a estrutura de antemão, e é uma má ideia quando você está só contornando uma modelagem que poderia ser mais simples.&lt;/p&gt;

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

&lt;p&gt;Reflection é uma ferramenta poderosa que permite ao código se inspecionar e se manipular em tempo de execução. É o que dá flexibilidade para frameworks, bibliotecas de serialização e sistemas de plugins funcionarem de forma genérica.&lt;/p&gt;

&lt;p&gt;Mas esse poder tem um preço: ela abre mão de garantias importantes que o compilador normalmente oferece. Entender quando ela é a ferramenta certa, e principalmente quando não é, é o que faz a diferença para usá-la bem.&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>java</category>
    </item>
  </channel>
</rss>
