<?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: Dherick</title>
    <description>The latest articles on DEV Community by Dherick (@xdherick).</description>
    <link>https://dev.to/xdherick</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%2F4123472%2Fa8c6e1c9-81f0-4422-bf9c-04a834c5cf5f.png</url>
      <title>DEV Community: Dherick</title>
      <link>https://dev.to/xdherick</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xdherick"/>
    <language>en</language>
    <item>
      <title>Sobrevivendo ao Caos: Injetando Falhas com o ChaosEngineeringMasterDeck</title>
      <dc:creator>Dherick</dc:creator>
      <pubDate>Sun, 25 Oct 2026 19:25:29 +0000</pubDate>
      <link>https://dev.to/xdherick/sobrevivendo-ao-caos-injetando-falhas-com-o-chaosengineeringmasterdeck-3bi0</link>
      <guid>https://dev.to/xdherick/sobrevivendo-ao-caos-injetando-falhas-com-o-chaosengineeringmasterdeck-3bi0</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Se o seu sistema só funciona quando nada dá errado, ele não está pronto para produção. Está só com sorte."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Às 2h17 da manhã, o alerta de &lt;em&gt;latência alta&lt;/em&gt; dispara. O serviço de pagamentos de um parceiro começou a responder em 8 segundos. Em poucos minutos, as threads do nosso backend estão todas presas esperando uma resposta que não vem, o checkout para de funcionar e o time de plantão acorda.&lt;/p&gt;

&lt;p&gt;Eu já vivi essa história, e o pior não foi a falha em si. O pior foi descobrir &lt;strong&gt;durante o incidente&lt;/strong&gt; que nossa arquitetura não estava preparada para ela.&lt;/p&gt;

&lt;p&gt;Foi por isso que passamos a quebrar coisas de propósito, de forma controlada, e a organizar essa prática em um baralho de experimentos: o &lt;strong&gt;ChaosEngineeringMasterDeck&lt;/strong&gt;. Neste artigo eu explico como ele funciona e mostro um experimento completo, da hipótese ao resultado.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; o cenário e os números deste artigo são didáticos, construídos para ilustrar o método. Os conceitos, as ferramentas e os trechos de código, porém, são reais e aplicáveis.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Sumário
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;O que é Chaos Engineering (e por que quebrar coisas de propósito)&lt;/li&gt;
&lt;li&gt;Dissecando o ChaosEngineeringMasterDeck&lt;/li&gt;
&lt;li&gt;Estudo de caso: a carta "Parceiro Lento"&lt;/li&gt;
&lt;li&gt;Observabilidade e resultados&lt;/li&gt;
&lt;li&gt;Conclusão: o que o caos nos ensinou&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. O que é Chaos Engineering (e por que quebrar coisas de propósito)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Chaos Engineering&lt;/strong&gt; é a disciplina de realizar &lt;strong&gt;experimentos controlados em um sistema&lt;/strong&gt; para ganhar confiança de que ele resiste a condições turbulentas em produção. A prática foi popularizada pela Netflix com o &lt;em&gt;Chaos Monkey&lt;/em&gt;, que desligava instâncias aleatoriamente para forçar os engenheiros a construir serviços tolerantes a falhas.&lt;/p&gt;

&lt;p&gt;Em sistemas distribuídos, a pergunta mudou. Já não é "&lt;strong&gt;será&lt;/strong&gt; que algo vai falhar?", e sim "&lt;strong&gt;quando&lt;/strong&gt; algo vai falhar, e o que acontece com o usuário?". Com dezenas de microsserviços, redes, filas, bancos e dependências de terceiros, falhas parciais são o estado normal da operação.&lt;/p&gt;

&lt;h3&gt;
  
  
  A mudança de mentalidade
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mentalidade tradicional&lt;/th&gt;
&lt;th&gt;Mentalidade de resiliência&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Evitar toda falha&lt;/td&gt;
&lt;td&gt;Assumir que falhas vão acontecer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Foco em &lt;strong&gt;MTBF&lt;/strong&gt; (tempo médio entre falhas)&lt;/td&gt;
&lt;td&gt;Foco em &lt;strong&gt;MTTR&lt;/strong&gt; (tempo médio de recuperação)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Testar só o "caminho feliz"&lt;/td&gt;
&lt;td&gt;Testar também os caminhos de falha&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Descobrir fragilidades em incidentes reais&lt;/td&gt;
&lt;td&gt;Descobrir fragilidades em experimentos planejados&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resiliência como "sorte" ou herói de plantão&lt;/td&gt;
&lt;td&gt;Resiliência como &lt;strong&gt;propriedade verificada&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Por que não bastam os testes tradicionais?
&lt;/h3&gt;

&lt;p&gt;Testes unitários e de integração verificam se o código faz o que &lt;strong&gt;esperamos&lt;/strong&gt;. O caos descobre o que &lt;strong&gt;não esperávamos&lt;/strong&gt;: timeouts mal configurados, &lt;em&gt;retries&lt;/em&gt; que amplificam o problema, filas que enchem, &lt;em&gt;fallbacks&lt;/em&gt; que nunca foram exercitados.&lt;/p&gt;

&lt;h3&gt;
  
  
  Os conceitos-chave
&lt;/h3&gt;

&lt;p&gt;Antes de seguir, vale fixar o vocabulário que vai aparecer no restante do artigo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Estado estável (&lt;em&gt;steady state&lt;/em&gt;):&lt;/strong&gt; o comportamento normal e mensurável do sistema, definido por métricas de negócio e técnicas. Exemplo: &lt;em&gt;"99,5% dos checkouts são concluídos com sucesso, com p95 abaixo de 800 ms"&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hipótese:&lt;/strong&gt; a aposta de que o estado estável &lt;strong&gt;se mantém&lt;/strong&gt; mesmo durante a falha injetada.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Variável (falha injetada):&lt;/strong&gt; o evento que alteramos no ambiente (latência, queda de instância, perda de pacotes, erro de DNS).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blast radius (raio de explosão):&lt;/strong&gt; o limite do impacto possível do experimento. Começamos pequenos de propósito.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observabilidade:&lt;/strong&gt; a capacidade de entender o que acontece dentro do sistema a partir de &lt;strong&gt;métricas, logs e traces&lt;/strong&gt;. Sem ela, o experimento é só uma queda.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Abort conditions (condições de aborto):&lt;/strong&gt; o "botão vermelho". Se uma métrica ultrapassar o limite, o experimento é interrompido automaticamente.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Produção ou staging?
&lt;/h3&gt;

&lt;p&gt;O ideal é a produção, porque só lá existem o tráfego, os dados e as interações reais. Mas ninguém começa por lá. O caminho seguro é:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Local/Dev  →  Staging  →  Produção (canário, baixo tráfego)  →  Produção (ampliado)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cada degrau só é subido quando o experimento anterior já passou sem surpresas.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Dissecando o ChaosEngineeringMasterDeck
&lt;/h2&gt;

&lt;h3&gt;
  
  
  O que é o Master Deck?
&lt;/h3&gt;

&lt;p&gt;O &lt;strong&gt;ChaosEngineeringMasterDeck&lt;/strong&gt; é o nosso &lt;strong&gt;catálogo gamificado de experimentos de caos&lt;/strong&gt;. Em vez de uma planilha confusa de "testes de resiliência", cada experimento vira uma &lt;strong&gt;carta&lt;/strong&gt; padronizada. O baralho inteiro vive em um repositório Git, com uma carta por arquivo, e é usado em dois momentos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Game Days:&lt;/strong&gt; sessões em que o time "compra" uma carta, executa o experimento e discute o resultado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regressão de resiliência:&lt;/strong&gt; as cartas mais maduras são automatizadas e rodam periodicamente em staging.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A gamificação tem um objetivo prático: tirar o medo. Quando quebrar o sistema vira uma dinâmica de equipe com regras claras, e não um ato isolado e arriscado, mais gente participa e mais fragilidades aparecem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Anatomia de uma carta
&lt;/h3&gt;

&lt;p&gt;Toda carta segue a mesma estrutura, que reflete o método científico do Chaos Engineering:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Campo&lt;/th&gt;
&lt;th&gt;Pergunta que responde&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Nome / Naipe&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Que tipo de falha é esta?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Nível de risco&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Quão perigosa é (🟢 baixo, 🟡 médio, 🔴 alto)?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Estado estável&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;O que é "normal" para este sistema?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hipótese&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;O que acreditamos que vai acontecer?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Variável injetada&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;O que vamos quebrar, e como?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Blast radius&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Até onde o impacto pode chegar?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Métricas de controle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;O que vamos observar?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Condição de aborto&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Quando interrompemos?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Padrões esperados&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Quais mecanismos de resiliência devem agir?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Os naipes do baralho
&lt;/h3&gt;

&lt;p&gt;Organizamos as cartas por tipo de falha:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;♠️ &lt;strong&gt;Infraestrutura:&lt;/strong&gt; queda de instância, de zona de disponibilidade (AZ), esgotamento de CPU/memória.&lt;/li&gt;
&lt;li&gt;♥️ &lt;strong&gt;Rede:&lt;/strong&gt; latência, perda de pacotes, partição de rede, falha de DNS.&lt;/li&gt;
&lt;li&gt;♦️ &lt;strong&gt;Dependências:&lt;/strong&gt; banco indisponível, API de terceiros lenta, fila cheia, cache fora do ar.&lt;/li&gt;
&lt;li&gt;♣️ &lt;strong&gt;Aplicação:&lt;/strong&gt; &lt;em&gt;memory leak&lt;/em&gt;, deploy defeituoso, &lt;em&gt;feature flag&lt;/em&gt; quebrada, dados corrompidos.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Exemplo de carta em YAML
&lt;/h3&gt;

&lt;p&gt;Guardar a carta como código permite versionar, revisar em &lt;em&gt;pull request&lt;/em&gt; e até automatizar a execução:&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="c1"&gt;# cards/dependencias/parceiro-lento.yaml&lt;/span&gt;
&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DEP-007&lt;/span&gt;
&lt;span class="na"&gt;nome&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Parceiro&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Lento"&lt;/span&gt;
&lt;span class="na"&gt;naipe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dependencias&lt;/span&gt;
&lt;span class="na"&gt;risco&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;medio&lt;/span&gt;

&lt;span class="na"&gt;estado_estavel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;descricao&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Checkout&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;saudável&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;sob&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;carga&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;normal"&lt;/span&gt;
  &lt;span class="na"&gt;metricas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;taxa&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;de&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;sucesso&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;do&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;checkout&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;99,5%"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latência&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;p95&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;do&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;/checkout&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;800ms"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;taxa&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;de&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;erros&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;5xx&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;0,5%"&lt;/span&gt;

&lt;span class="na"&gt;hipotese&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="s"&gt;Se o serviço de pagamentos do parceiro passar a responder com 3s de&lt;/span&gt;
  &lt;span class="s"&gt;latência adicional, o Circuit Breaker abrirá em até 30s e o checkout&lt;/span&gt;
  &lt;span class="s"&gt;continuará aceitando pedidos em modo degradado (pagamento pendente),&lt;/span&gt;
  &lt;span class="s"&gt;mantendo a taxa de sucesso acima de 95%.&lt;/span&gt;

&lt;span class="na"&gt;variavel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;tipo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;latencia&lt;/span&gt;
  &lt;span class="na"&gt;alvo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;payment-gateway&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(via&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;proxy&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Toxiproxy)"&lt;/span&gt;
  &lt;span class="na"&gt;valor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+3000ms,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;jitter&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;500ms"&lt;/span&gt;
  &lt;span class="na"&gt;duracao&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;10&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;minutos"&lt;/span&gt;

&lt;span class="na"&gt;blast_radius&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ambiente&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;staging&lt;/span&gt;
  &lt;span class="na"&gt;escopo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;somente&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;chamadas&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;do&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;order-service&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ao&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;payment-gateway"&lt;/span&gt;
  &lt;span class="na"&gt;trafego_afetado&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;100%&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;do&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tráfego&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;sintético;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;0%&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;de&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;usuários&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;reais"&lt;/span&gt;

&lt;span class="na"&gt;condicao_de_aborto&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;taxa&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;de&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;erros&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;5xx&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;10%&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;por&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;minutos"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pool&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;de&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;threads&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;do&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;order-service&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;90%&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;por&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;minuto"&lt;/span&gt;

&lt;span class="na"&gt;padroes_esperados&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Timeout agressivo&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Circuit Breaker&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Fallback (pedido com pagamento pendente)&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Bulkhead (isolamento de threads)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Estudo de caso: a carta "Parceiro Lento"
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A arquitetura sob teste
&lt;/h3&gt;

&lt;p&gt;Nosso sistema de e-commerce roda na AWS. Resumindo o que importa para este experimento:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    ┌──────────────────────┐
   Usuário ───────► │  Application Load    │
                    │  Balancer (ALB)      │
                    └──────────┬───────────┘
                               │
              ┌────────────────┴────────────────┐
              │   Auto Scaling Group (2 AZs)    │
              │  ┌───────────┐   ┌───────────┐  │
              │  │ order-svc │   │ order-svc │  │   Spring Boot
              │  │   (AZ-a)  │   │   (AZ-b)  │  │
              │  └─────┬─────┘   └─────┬─────┘  │
              └────────┼───────────────┼────────┘
                       │               │
           ┌───────────┴──┐     ┌──────┴──────────┐
           │ RDS Postgres │     │ payment-gateway │
           │  (Multi-AZ)  │     │  (API externa)  │
           └──────────────┘     └─────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;order-service:&lt;/strong&gt; backend em &lt;strong&gt;Spring Boot&lt;/strong&gt; que recebe o checkout, grava o pedido e cobra o pagamento.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;payment-gateway:&lt;/strong&gt; API de um parceiro. É a dependência que não controlamos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RDS PostgreSQL Multi-AZ&lt;/strong&gt; e &lt;strong&gt;Auto Scaling Group&lt;/strong&gt; distribuído em duas zonas de disponibilidade.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  A carta sorteada
&lt;/h3&gt;

&lt;p&gt;No Game Day, o time comprou &lt;strong&gt;DEP-007 — Parceiro Lento (🟡 risco médio)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Estado estável:&lt;/strong&gt; 99,5% de sucesso no checkout e p95 abaixo de 800 ms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hipótese:&lt;/strong&gt; &lt;em&gt;"Mesmo com +3s de latência no gateway, o Circuit Breaker abre em até 30s e o checkout segue funcionando em modo degradado, com taxa de sucesso acima de 95%."&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Definindo o blast radius
&lt;/h3&gt;

&lt;p&gt;Esta é a etapa que separa um experimento sério de uma irresponsabilidade. Nosso raio de explosão foi deliberadamente pequeno:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ambiente:&lt;/strong&gt; staging, com tráfego sintético gerado por k6.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escopo:&lt;/strong&gt; apenas a chamada &lt;code&gt;order-service → payment-gateway&lt;/code&gt;. O banco, o ALB e as demais rotas não foram tocados.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duração:&lt;/strong&gt; 10 minutos, com a condição de aborto sempre vigiada.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rollback:&lt;/strong&gt; remover a "toxic" do proxy, uma operação de segundos.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Injetando a falha
&lt;/h3&gt;

&lt;p&gt;Usamos o &lt;strong&gt;Toxiproxy&lt;/strong&gt; como proxy entre o &lt;code&gt;order-service&lt;/code&gt; e o gateway, o que permite injetar latência sem alterar o código da aplicação:&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;# Cria o proxy para o gateway (o order-service passa a apontar para ele)&lt;/span&gt;
toxiproxy-cli create payment_gateway &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--listen&lt;/span&gt; 0.0.0.0:8474 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--upstream&lt;/span&gt; payment-gateway.staging.internal:443

&lt;span class="c"&gt;# Injeta 3000ms de latência com 500ms de jitter (a "carta" em ação)&lt;/span&gt;
toxiproxy-cli toxic add payment_gateway &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--type&lt;/span&gt; latency &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--attribute&lt;/span&gt; &lt;span class="nv"&gt;latency&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3000 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--attribute&lt;/span&gt; &lt;span class="nv"&gt;jitter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;500

&lt;span class="c"&gt;# Rollback imediato (botão vermelho)&lt;/span&gt;
toxiproxy-cli toxic remove payment_gateway &lt;span class="nt"&gt;--toxicName&lt;/span&gt; latency_downstream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  O que o código precisava ter (e a hipótese testava)
&lt;/h3&gt;

&lt;p&gt;A hipótese dependia de quatro defesas configuradas com &lt;strong&gt;Resilience4j&lt;/strong&gt; no Spring Boot:&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="c1"&gt;# application.yml&lt;/span&gt;
&lt;span class="na"&gt;resilience4j&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;timelimiter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;instances&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;paymentGateway&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;timeout-duration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2s&lt;/span&gt;          &lt;span class="c1"&gt;# não esperamos mais que 2s&lt;/span&gt;

  &lt;span class="na"&gt;circuitbreaker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;instances&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;paymentGateway&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;sliding-window-type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;COUNT_BASED&lt;/span&gt;
        &lt;span class="na"&gt;sliding-window-size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
        &lt;span class="na"&gt;failure-rate-threshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;    &lt;span class="c1"&gt;# abre com 50% de falhas&lt;/span&gt;
        &lt;span class="na"&gt;slow-call-duration-threshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2s&lt;/span&gt;
        &lt;span class="na"&gt;slow-call-rate-threshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;  &lt;span class="c1"&gt;# chamadas lentas também contam!&lt;/span&gt;
        &lt;span class="na"&gt;wait-duration-in-open-state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30s&lt;/span&gt;
        &lt;span class="na"&gt;permitted-number-of-calls-in-half-open-state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;

  &lt;span class="na"&gt;bulkhead&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;instances&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;paymentGateway&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;max-concurrent-calls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;      &lt;span class="c1"&gt;# isola o pool de threads&lt;/span&gt;
        &lt;span class="na"&gt;max-wait-duration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100ms&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&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;PaymentService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LoggerFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getLogger&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PaymentService&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="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;PaymentGatewayClient&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;PaymentService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PaymentGatewayClient&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gateway&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@CircuitBreaker&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"paymentGateway"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fallbackMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"pagamentoPendente"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@Bulkhead&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"paymentGateway"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@TimeLimiter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"paymentGateway"&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;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PaymentResult&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;cobrar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&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="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;supplyAsync&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;gateway&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;charge&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Fallback: não derruba o pedido, apenas agenda a cobrança para depois&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PaymentResult&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;pagamentoPendente&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Gateway indisponível/lento. Pedido {} em modo degradado: {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                 &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;ex&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="na"&gt;getSimpleName&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;completedFuture&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="nc"&gt;PaymentResult&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pending&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;   &lt;span class="c1"&gt;// cobrança reprocessada por fila&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;A ideia do fallback é de negócio, não só técnica: é melhor &lt;strong&gt;aceitar o pedido com pagamento pendente&lt;/strong&gt; e cobrar depois do que perder a venda.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Observabilidade e resultados
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Como monitoramos
&lt;/h3&gt;

&lt;p&gt;Sem observabilidade, o experimento vira um "derrubei e não sei o que aconteceu". Nosso painel (Prometheus + Grafana, com traces no OpenTelemetry) acompanhava, lado a lado:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Negócio:&lt;/strong&gt; taxa de sucesso do checkout e pedidos em modo "pagamento pendente".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aplicação:&lt;/strong&gt; latência p50/p95/p99, taxa de erros 5xx.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resiliência:&lt;/strong&gt; estado do Circuit Breaker (&lt;code&gt;closed&lt;/code&gt;, &lt;code&gt;open&lt;/code&gt;, &lt;code&gt;half_open&lt;/code&gt;) via métricas do Resilience4j no Actuator.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recursos:&lt;/strong&gt; uso do pool de threads, CPU e conexões abertas.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Linha do tempo do experimento
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tempo&lt;/th&gt;
&lt;th&gt;O que aconteceu&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;T+0s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Latência de +3s injetada no gateway&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;T+0–12s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Chamadas começam a estourar o &lt;code&gt;TimeLimiter&lt;/code&gt; (2s); p95 do checkout sobe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;T+12s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Taxa de chamadas lentas passa de 50%: &lt;strong&gt;Circuit Breaker abre&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;T+12s em diante&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fallback assume; pedidos entram como "pagamento pendente" e a latência volta ao normal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;T+42s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Breaker vai para &lt;code&gt;half_open&lt;/code&gt; e testa 5 chamadas; todas ainda lentas, então volta a &lt;code&gt;open&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;T+10min&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Toxic removida. No próximo ciclo &lt;code&gt;half_open&lt;/code&gt;, as chamadas passam e o breaker &lt;strong&gt;fecha&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;T+11min&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Sistema de volta ao estado estável; fila reprocessa os pagamentos pendentes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Resultado: a hipótese se confirmou?
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Métrica&lt;/th&gt;
&lt;th&gt;Estado estável&lt;/th&gt;
&lt;th&gt;Durante a falha&lt;/th&gt;
&lt;th&gt;Hipótese&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sucesso do checkout&lt;/td&gt;
&lt;td&gt;99,7%&lt;/td&gt;
&lt;td&gt;98,9%&lt;/td&gt;
&lt;td&gt;✅ (meta: &amp;gt; 95%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Latência p95&lt;/td&gt;
&lt;td&gt;410 ms&lt;/td&gt;
&lt;td&gt;1,9 s &lt;em&gt;(só nos primeiros 12s)&lt;/em&gt;, depois 520 ms&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Erros 5xx&lt;/td&gt;
&lt;td&gt;0,2%&lt;/td&gt;
&lt;td&gt;1,1% &lt;em&gt;(pico inicial)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tempo até o breaker abrir&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;12 s&lt;/td&gt;
&lt;td&gt;✅ (meta: ≤ 30 s)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pedidos em modo degradado&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;~9%&lt;/td&gt;
&lt;td&gt;✅ esperado&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;A arquitetura sobreviveu.&lt;/strong&gt; Mas o experimento não termina aí: o maior valor está no que &lt;strong&gt;não&lt;/strong&gt; saiu como o planejado.&lt;/p&gt;

&lt;h3&gt;
  
  
  As surpresas (onde o caos paga a conta)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;O pico inicial de latência foi pior que o esperado.&lt;/strong&gt; Nos primeiros 12 segundos, antes de o breaker abrir, o p95 chegou a 1,9 s. Reduzir a janela de deslizamento (&lt;code&gt;sliding-window-size&lt;/code&gt; de 20 para 10) fez o breaker reagir mais rápido, e anotamos essa melhoria para a próxima rodada.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O reprocessamento de pagamentos pendentes não tinha limite de taxa.&lt;/strong&gt; Quando o gateway voltou, a fila disparou todas as cobranças de uma vez, quase criando uma segunda falha. Adicionamos &lt;em&gt;rate limiting&lt;/em&gt; ao consumidor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Um alerta que deveria ter disparado, não disparou.&lt;/strong&gt; A métrica de "breaker aberto" existia no Grafana, mas ninguém era notificado. Criamos o alerta antes de encerrar o Game Day.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Essas três descobertas custaram 30 minutos de experimento e evitaram, com boa probabilidade, um incidente real.&lt;/p&gt;

&lt;h3&gt;
  
  
  Padrões de resiliência que entraram em ação
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;⏱️ &lt;strong&gt;Timeout:&lt;/strong&gt; impediu que threads ficassem presas indefinidamente.&lt;/li&gt;
&lt;li&gt;🔌 &lt;strong&gt;Circuit Breaker:&lt;/strong&gt; parou de bater em um serviço claramente doente e deu a ele espaço para se recuperar.&lt;/li&gt;
&lt;li&gt;🛟 &lt;strong&gt;Fallback:&lt;/strong&gt; transformou uma falha técnica em degradação controlada do negócio.&lt;/li&gt;
&lt;li&gt;🧱 &lt;strong&gt;Bulkhead:&lt;/strong&gt; garantiu que a lentidão do gateway não consumisse todas as threads e derrubasse rotas que nada têm a ver com pagamento.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. Conclusão: o que o caos nos ensinou
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Lições aprendidas
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Resiliência é uma hipótese até ser testada.&lt;/strong&gt; Ter Circuit Breaker configurado não prova que ele funciona como você imagina.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comece pequeno.&lt;/strong&gt; Um blast radius reduzido permite errar barato e aprender rápido.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observabilidade vem primeiro.&lt;/strong&gt; Se você não consegue ver o efeito da falha, não consegue aprender com ela.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Falhas de negócio importam tanto quanto as técnicas.&lt;/strong&gt; O fallback "pagamento pendente" só existe porque o time de produto participou da conversa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O valor está nas surpresas.&lt;/strong&gt; Um experimento em que tudo funciona como previsto é bom. Um que revela uma fragilidade escondida é ótimo.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  O impacto na cultura DevOps
&lt;/h3&gt;

&lt;p&gt;O maior efeito do Master Deck não foi técnico, foi &lt;strong&gt;cultural&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Menos culpa, mais curiosidade.&lt;/strong&gt; Falhar em um experimento é aprendizado, não erro de alguém.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Desenvolvimento e operações na mesma mesa.&lt;/strong&gt; O Game Day junta quem escreve o código e quem o opera, quebrando o clássico "problema do outro time".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resiliência como requisito, não como favor.&lt;/strong&gt; Novas funcionalidades passaram a vir acompanhadas de uma pergunta: &lt;em&gt;"qual carta do baralho testaria isso?"&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confiança para evoluir.&lt;/strong&gt; Times que sabem como o sistema se comporta sob falha fazem deploys com menos medo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Próximos passos
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Automatizar as cartas maduras no pipeline de CI/CD (regressão de resiliência).&lt;/li&gt;
&lt;li&gt;Evoluir para experimentos em produção com tráfego canário.&lt;/li&gt;
&lt;li&gt;Criar cartas de maior risco, como &lt;strong&gt;queda de uma AZ inteira&lt;/strong&gt;, usando o &lt;strong&gt;AWS Fault Injection Service&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Quer começar hoje?
&lt;/h3&gt;

&lt;p&gt;Você não precisa de uma plataforma sofisticada. Faça assim:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Escolha &lt;strong&gt;um&lt;/strong&gt; serviço crítico e defina seu estado estável.&lt;/li&gt;
&lt;li&gt;Escreva &lt;strong&gt;uma&lt;/strong&gt; carta com hipótese, blast radius e condição de aborto.&lt;/li&gt;
&lt;li&gt;Execute em staging com um grupo pequeno, com o painel de métricas aberto.&lt;/li&gt;
&lt;li&gt;Documente o que aprendeu e &lt;strong&gt;corrija&lt;/strong&gt; o que falhou.&lt;/li&gt;
&lt;li&gt;Repita, sempre com uma carta nova.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quebre as coisas com cuidado, para que elas não quebrem sozinhas na hora errada.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Referências e ferramentas
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://principlesofchaos.org/" rel="noopener noreferrer"&gt;Principles of Chaos Engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://resilience4j.readme.io/" rel="noopener noreferrer"&gt;Resilience4j&lt;/a&gt; — Circuit Breaker, Bulkhead, TimeLimiter para Java/Spring&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Shopify/toxiproxy" rel="noopener noreferrer"&gt;Toxiproxy&lt;/a&gt; — simulação de condições de rede&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codecentric.github.io/chaos-monkey-spring-boot/" rel="noopener noreferrer"&gt;Chaos Monkey for Spring Boot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/fis/" rel="noopener noreferrer"&gt;AWS Fault Injection Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://k6.io/" rel="noopener noreferrer"&gt;k6&lt;/a&gt; — geração de carga para os experimentos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Gostou? Deixe nos comentários qual carta você colocaria no seu baralho.&lt;/em&gt; 🃏&lt;/p&gt;

</description>
      <category>software</category>
      <category>architecture</category>
      <category>tools</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Construindo um Pipeline de Processamento de Pedidos com o Padrão Chain of Responsibility em Java</title>
      <dc:creator>Dherick</dc:creator>
      <pubDate>Sun, 13 Sep 2026 20:51:39 +0000</pubDate>
      <link>https://dev.to/xdherick/construindo-um-pipeline-de-processamento-de-pedidos-com-o-padrao-chain-of-responsibility-em-java-510g</link>
      <guid>https://dev.to/xdherick/construindo-um-pipeline-de-processamento-de-pedidos-com-o-padrao-chain-of-responsibility-em-java-510g</guid>
      <description>&lt;h2&gt;
  
  
  1. Base Fundamental
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Introdução
&lt;/h3&gt;

&lt;p&gt;O &lt;strong&gt;Chain of Responsibility&lt;/strong&gt; (Cadeia de Responsabilidade) é um padrão de projeto da categoria &lt;strong&gt;Comportamental&lt;/strong&gt;, catalogado pela Gang of Four (GoF).&lt;/p&gt;

&lt;p&gt;Ele permite que uma solicitação percorra uma &lt;strong&gt;cadeia de handlers&lt;/strong&gt;, onde cada um decide se processa a solicitação, a repassa para o próximo handler ou interrompe o fluxo.&lt;/p&gt;

&lt;p&gt;Na prática, o padrão é muito útil para representar &lt;strong&gt;pipelines de processamento em etapas&lt;/strong&gt;, nos quais uma operação precisa passar por várias regras antes de ser concluída.&lt;/p&gt;

&lt;h3&gt;
  
  
  O Problema
&lt;/h3&gt;

&lt;p&gt;Sistemas que processam uma entrada por múltiplas etapas sequenciais — validação, transformação, enriquecimento e persistência — podem acabar concentrando todas essas responsabilidades em um único método.&lt;/p&gt;

&lt;p&gt;Um exemplo seria um método &lt;code&gt;processarPedido()&lt;/code&gt; responsável por:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;validar estoque;&lt;/li&gt;
&lt;li&gt;validar pagamento;&lt;/li&gt;
&lt;li&gt;calcular frete;&lt;/li&gt;
&lt;li&gt;confirmar o pedido;&lt;/li&gt;
&lt;li&gt;persistir os dados;&lt;/li&gt;
&lt;li&gt;publicar eventos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Com o crescimento da aplicação, esse método pode ficar cheio de &lt;code&gt;if/else&lt;/code&gt; e assumir responsabilidades demais.&lt;/p&gt;

&lt;p&gt;Isso traz alguns problemas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Baixa coesão:&lt;/strong&gt; um único método concentra responsabilidades diferentes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dificuldade de manutenção:&lt;/strong&gt; alterar uma etapa pode exigir mudanças em um bloco grande de código.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dificuldade de reordenar etapas:&lt;/strong&gt; mudar a sequência do processamento fica mais trabalhoso.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pouco reaproveitamento:&lt;/strong&gt; uma etapa específica fica difícil de utilizar de forma isolada.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O Chain of Responsibility resolve esse problema dividindo o fluxo em &lt;strong&gt;handlers independentes&lt;/strong&gt;, cada um responsável por uma etapa específica.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conceito
&lt;/h3&gt;

&lt;p&gt;Uma forma simples de entender o padrão é imaginar uma linha de produção.&lt;/p&gt;

&lt;p&gt;A peça passa pela estação de montagem, depois pela pintura e, por fim, pela inspeção de qualidade. Cada estação realiza apenas o seu trabalho e passa a peça para a próxima.&lt;/p&gt;

&lt;p&gt;Se uma estação encontrar um problema que impeça o processo de continuar, a linha pode ser interrompida naquele ponto.&lt;/p&gt;

&lt;p&gt;No software, cada estação representa um &lt;strong&gt;Handler&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;O handler executa sua responsabilidade e, caso tudo esteja correto, encaminha a solicitação para o próximo elemento da cadeia.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Desenvolvimento
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Cenário do Mundo Real
&lt;/h3&gt;

&lt;p&gt;Um cenário clássico para aplicar o padrão é o &lt;strong&gt;pipeline de processamento de um pedido em um e-commerce&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Quando um cliente finaliza uma compra, o pedido precisa passar por algumas etapas antes de ser confirmado:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Validação de estoque&lt;/strong&gt; — os itens estão disponíveis?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validação de pagamento&lt;/strong&gt; — o pagamento foi aprovado?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cálculo de frete&lt;/strong&gt; — qual será o custo do envio?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confirmação do pedido&lt;/strong&gt; — persistir o pedido e publicar o evento de confirmação.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Se qualquer etapa falhar, o pipeline deve &lt;strong&gt;parar imediatamente&lt;/strong&gt; e impedir que as próximas etapas sejam executadas.&lt;/p&gt;




&lt;h2&gt;
  
  
  Representação Visual
&lt;/h2&gt;

&lt;p&gt;Para visualizar o padrão, podemos separar a representação em duas partes: o &lt;strong&gt;diagrama de classes&lt;/strong&gt;, que mostra a estrutura dos handlers, e o &lt;strong&gt;desenho da arquitetura&lt;/strong&gt;, que mostra como o pedido percorre o sistema.&lt;/p&gt;

&lt;h3&gt;
  
  
  Diagrama de Classes (UML)
&lt;/h3&gt;

&lt;p&gt;O &lt;code&gt;PedidoHandler&lt;/code&gt; é a classe abstrata que define o comportamento comum da cadeia. Os handlers concretos herdam dessa classe e implementam cada etapa do processamento.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                         ┌──────────────────────────────┐
                         │       PedidoHandler          │
                         │          «abstract»          │
                         ├──────────────────────────────┤
                         │ - proximo : PedidoHandler    │
                         ├──────────────────────────────┤
                         │ + definirProximo()           │
                         │ + processar(Pedido)          │
                         │ # continuar(Pedido)          │
                         └───────────────┬──────────────┘
                                         │
                 ┌───────────────────────┼───────────────────────┐
                 │                       │                       │
                 ▼                       ▼                       ▼
    ┌─────────────────────┐  ┌─────────────────────┐  ┌─────────────────────┐
    │ ValidacaoEstoque    │  │ ValidacaoPagamento  │  │ CalculoFrete        │
    │      Handler        │  │       Handler       │  │      Handler         │
    ├─────────────────────┤  ├─────────────────────┤  ├─────────────────────┤
    │ + processar()       │  │ + processar()       │  │ + processar()       │
    └─────────────────────┘  └─────────────────────┘  └─────────────────────┘
                                         │
                                         ▼
                              ┌─────────────────────┐
                              │ ConfirmacaoPedido   │
                              │       Handler       │
                              ├─────────────────────┤
                              │ + processar()       │
                              └─────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cada handler representa uma responsabilidade específica dentro do pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PedidoHandler
     │
     ├── ValidacaoEstoqueHandler
     │
     ├── ValidacaoPagamentoHandler
     │
     ├── CalculoFreteHandler
     │
     └── ConfirmacaoPedidoHandler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A referência para o próximo handler é utilizada durante a execução da cadeia. Assim, cada etapa pode concluir seu processamento e encaminhar o pedido para a próxima.&lt;/p&gt;




&lt;h2&gt;
  
  
  Desenho da Arquitetura
&lt;/h2&gt;

&lt;p&gt;O desenho arquitetural apresenta uma visão simplificada do sistema e mostra como o pedido entra na aplicação, percorre o pipeline e interage com os serviços necessários.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                         ┌──────────────┐
                         │    Cliente   │
                         └──────┬───────┘
                                │
                                ▼
                      ┌──────────────────┐
                      │ API de Pedidos   │
                      └────────┬─────────┘
                               │
                               ▼
                  ┌──────────────────────────┐
                  │ Validação de Estoque     │
                  └────────────┬─────────────┘
                               │
                               ▼
                  ┌──────────────────────────┐
                  │ Validação de Pagamento   │
                  └────────────┬─────────────┘
                               │
                               ▼
                  ┌──────────────────────────┐
                  │ Cálculo de Frete         │
                  └────────────┬─────────────┘
                               │
                               ▼
                  ┌──────────────────────────┐
                  │ Confirmação do Pedido    │
                  └────────────┬─────────────┘
                               │
                    ┌──────────┴──────────┐
                    ▼                     ▼
             ┌──────────────┐     ┌──────────────────┐
             │ Banco de     │     │ Evento: Pedido   │
             │ Pedidos      │     │ Confirmado       │
             └──────────────┘     └──────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Integrações externas
&lt;/h3&gt;

&lt;p&gt;Durante o processamento, cada etapa pode consultar o serviço necessário para realizar sua responsabilidade:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────────────────┐
│ Validação de Estoque     │
└────────────┬─────────────┘
             │
             ▼
┌──────────────────────────┐
│ Serviço de Estoque       │
└──────────────────────────┘


┌──────────────────────────┐
│ Validação de Pagamento   │
└────────────┬─────────────┘
             │
             ▼
┌──────────────────────────┐
│ Gateway de Pagamento     │
└──────────────────────────┘


┌──────────────────────────┐
│ Cálculo de Frete         │
└────────────┬─────────────┘
             │
             ▼
┌──────────────────────────┐
│ Serviço de Frete         │
└──────────────────────────┘


┌──────────────────────────┐
│ Confirmação do Pedido    │
└────────────┬─────────────┘
             │
             ├──────────────► Banco de Pedidos
             │
             └──────────────► Evento Pedido Confirmado
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O ponto principal da arquitetura é que a &lt;code&gt;API de Pedidos&lt;/code&gt; inicia o pipeline, enquanto cada handler fica responsável apenas pela sua própria etapa.&lt;/p&gt;

&lt;h3&gt;
  
  
  Funcionamento do Pipeline
&lt;/h3&gt;

&lt;p&gt;Em um cenário de sucesso, o pedido percorre todas as etapas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cliente
   │
   ▼
API de Pedidos
   │
   ▼
Estoque
   │
   ▼
Pagamento
   │
   ▼
Frete
   │
   ▼
Confirmação
   │
   ▼
Pedido confirmado
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se uma etapa falhar, o processamento pode ser interrompido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cliente
   │
   ▼
API de Pedidos
   │
   ▼
Estoque
   │
   ▼
Pagamento
   │
   ✕
   │
   ▼
Pedido rejeitado
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse caso, as etapas seguintes não precisam ser executadas. Essa interrupção antecipada é uma das principais vantagens do Chain of Responsibility aplicado a pipelines de processamento.&lt;/p&gt;




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

&lt;h3&gt;
  
  
  Handler abstrato
&lt;/h3&gt;

&lt;p&gt;O &lt;code&gt;PedidoHandler&lt;/code&gt; representa a estrutura base de todos os elementos da cadeia.&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;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PedidoHandler&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="nc"&gt;PedidoHandler&lt;/span&gt; &lt;span class="n"&gt;proximo&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;PedidoHandler&lt;/span&gt; &lt;span class="nf"&gt;definirProximo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PedidoHandler&lt;/span&gt; &lt;span class="n"&gt;proximo&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;proximo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;proximo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;proximo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;continuar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Pedido&lt;/span&gt; &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;proximo&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;proximo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;processar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Pedido&lt;/span&gt; &lt;span class="n"&gt;pedido&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;O atributo &lt;code&gt;proximo&lt;/code&gt; guarda a referência para o próximo handler.&lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;continuar()&lt;/code&gt; verifica se existe uma próxima etapa e, caso exista, encaminha o pedido para ela.&lt;/p&gt;

&lt;h3&gt;
  
  
  Classe Pedido
&lt;/h3&gt;

&lt;p&gt;A classe &lt;code&gt;Pedido&lt;/code&gt; representa o objeto que percorre toda a cadeia.&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.util.List&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;Pedido&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;itens&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;valorTotal&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;status&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Pedido&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;itens&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;valorTotal&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;itens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;itens&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valorTotal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;valorTotal&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"RECEBIDO"&lt;/span&gt;&lt;span class="o"&gt;;&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;getId&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="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&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;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getItens&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="n"&gt;itens&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;getValorTotal&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="n"&gt;valorTotal&lt;/span&gt;&lt;span class="o"&gt;;&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;getStatus&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="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setStatus&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;status&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;h3&gt;
  
  
  Handler de validação de estoque
&lt;/h3&gt;

&lt;p&gt;O primeiro handler verifica se todos os itens do pedido estão disponíveis.&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;ValidacaoEstoqueHandler&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PedidoHandler&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;EstoqueService&lt;/span&gt; &lt;span class="n"&gt;estoqueService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ValidacaoEstoqueHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;EstoqueService&lt;/span&gt; &lt;span class="n"&gt;estoqueService&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;estoqueService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;estoqueService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Pedido&lt;/span&gt; &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;)&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;String&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getItens&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;estoqueService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;temEstoque&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

                &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setStatus&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"REJEITADO_SEM_ESTOQUE"&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;printf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="s"&gt;"[Estoque] Pedido %s rejeitado: item %s indisponivel%n"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
                    &lt;span class="n"&gt;item&lt;/span&gt;
                &lt;span class="o"&gt;);&lt;/span&gt;

                &lt;span class="k"&gt;return&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="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;printf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"[Estoque] Pedido %s: estoque validado%n"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;continuar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido&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;Caso algum item não esteja disponível, o método utiliza &lt;code&gt;return&lt;/code&gt; e &lt;strong&gt;interrompe a cadeia&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Caso contrário, &lt;code&gt;continuar(pedido)&lt;/code&gt; encaminha o pedido para o próximo handler.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handler de validação de pagamento
&lt;/h3&gt;

&lt;p&gt;O segundo handler verifica se o pagamento pode ser autorizado.&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;ValidacaoPagamentoHandler&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PedidoHandler&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;GatewayPagamento&lt;/span&gt; &lt;span class="n"&gt;gatewayPagamento&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ValidacaoPagamentoHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;GatewayPagamento&lt;/span&gt; &lt;span class="n"&gt;gatewayPagamento&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gatewayPagamento&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gatewayPagamento&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Pedido&lt;/span&gt; &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;aprovado&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="n"&gt;gatewayPagamento&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;autorizar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getValorTotal&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;aprovado&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

            &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setStatus&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"REJEITADO_PAGAMENTO"&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;printf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"[Pagamento] Pedido %s rejeitado: pagamento nao autorizado%n"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&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="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;printf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"[Pagamento] Pedido %s: pagamento aprovado%n"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;continuar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido&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;Se o pagamento for recusado, a cadeia é interrompida.&lt;/p&gt;

&lt;p&gt;Se for aprovado, o pedido segue para o cálculo de frete.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handler de cálculo de frete
&lt;/h3&gt;

&lt;p&gt;O terceiro handler calcula o frete do pedido.&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;CalculoFreteHandler&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PedidoHandler&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ServicoFrete&lt;/span&gt; &lt;span class="n"&gt;servicoFrete&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;CalculoFreteHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ServicoFrete&lt;/span&gt; &lt;span class="n"&gt;servicoFrete&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;servicoFrete&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;servicoFrete&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Pedido&lt;/span&gt; &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;frete&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;servicoFrete&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;calcular&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido&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;printf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"[Frete] Pedido %s: frete calculado em R$ %.2f%n"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;frete&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;continuar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido&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;Depois do cálculo, o pedido é encaminhado para a etapa final.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handler de confirmação
&lt;/h3&gt;

&lt;p&gt;O último handler confirma o pedido.&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;ConfirmacaoPedidoHandler&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PedidoHandler&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Pedido&lt;/span&gt; &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setStatus&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CONFIRMADO"&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;printf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"[Confirmacao] Pedido %s confirmado com sucesso%n"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;continuar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido&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;Como esse é o último elemento da cadeia, não existe outro handler para executar depois dele.&lt;/p&gt;




&lt;h2&gt;
  
  
  Montando a cadeia
&lt;/h2&gt;

&lt;p&gt;Agora precisamos criar os handlers e definir a ordem de execução.&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.util.List&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;Main&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;Pedido&lt;/span&gt; &lt;span class="n"&gt;pedido&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;Pedido&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"PED-501"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Teclado"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Mouse"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
            &lt;span class="mf"&gt;349.90&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;PedidoHandler&lt;/span&gt; &lt;span class="n"&gt;estoque&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ValidacaoEstoqueHandler&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;EstoqueService&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="nc"&gt;PedidoHandler&lt;/span&gt; &lt;span class="n"&gt;pagamento&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ValidacaoPagamentoHandler&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;GatewayPagamento&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="nc"&gt;PedidoHandler&lt;/span&gt; &lt;span class="n"&gt;frete&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CalculoFreteHandler&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;ServicoFrete&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="nc"&gt;PedidoHandler&lt;/span&gt; &lt;span class="n"&gt;confirmacao&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ConfirmacaoPedidoHandler&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;estoque&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;definirProximo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pagamento&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;pagamento&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;definirProximo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frete&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;frete&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;definirProximo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;confirmacao&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;estoque&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;processar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido&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;"Status final: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getStatus&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;A cadeia criada pelo código é:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;estoque
   ↓
pagamento
   ↓
frete
   ↓
confirmacao
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A execução começa apenas no primeiro handler:&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="n"&gt;estoque&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;processar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A partir daí, cada handler decide se deve ou não chamar o próximo.&lt;/p&gt;

&lt;p&gt;Isso é justamente o comportamento central do &lt;strong&gt;Chain of Responsibility&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prós e Contras
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Vantagens
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Responsabilidade única:&lt;/strong&gt; cada handler cuida de uma etapa específica.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Facilidade de testes:&lt;/strong&gt; cada etapa pode ser testada de forma isolada.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibilidade:&lt;/strong&gt; é possível adicionar, remover ou reordenar etapas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interrupção antecipada:&lt;/strong&gt; o processamento pode parar assim que uma regra falhar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Menor acoplamento:&lt;/strong&gt; cada etapa não precisa conhecer a implementação das outras.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Trade-offs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fluxo distribuído:&lt;/strong&gt; para entender o processamento completo, é necessário observar a montagem da cadeia.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risco de interrupção silenciosa:&lt;/strong&gt; esquecer de chamar &lt;code&gt;continuar(pedido)&lt;/code&gt; pode impedir o restante do pipeline de executar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debug mais trabalhoso:&lt;/strong&gt; acompanhar a execução pode exigir navegar por várias classes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tratamento incompleto:&lt;/strong&gt; é importante definir o que acontece quando uma solicitação chega ao final da cadeia sem ser processada.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;h3&gt;
  
  
  Resumo
&lt;/h3&gt;

&lt;p&gt;O &lt;strong&gt;Chain of Responsibility&lt;/strong&gt; transforma um fluxo de processamento que poderia acabar concentrado em um método cheio de condicionais em uma cadeia de handlers independentes.&lt;/p&gt;

&lt;p&gt;No exemplo apresentado, cada etapa possui uma responsabilidade clara:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Estoque
   ↓
Pagamento
   ↓
Frete
   ↓
Confirmação
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa separação permite evoluir cada parte do processo sem precisar concentrar todas as regras em uma única classe.&lt;/p&gt;

&lt;p&gt;Além disso, o pipeline pode ser interrompido assim que uma etapa identificar um problema, evitando processamento desnecessário.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visão Pessoal
&lt;/h3&gt;

&lt;p&gt;O que mais me chamou atenção ao trabalhar com esse padrão foi como ele torna o &lt;strong&gt;fluxo de negócio explícito no código&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Só de olhar para a montagem da cadeia:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;estoque → pagamento → frete → confirmação
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;já é possível entender a ordem do processo sem precisar conhecer toda a implementação interna de cada etapa.&lt;/p&gt;

&lt;p&gt;Para mim, esse é o principal ponto do Chain of Responsibility: ele não elimina a complexidade do processo, mas &lt;strong&gt;distribui essa complexidade em responsabilidades menores e organizadas&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Quando um pipeline começa a crescer, essa separação pode fazer bastante diferença na manutenção e na evolução do sistema.&lt;/p&gt;

&lt;h3&gt;
  
  
  E você?
&lt;/h3&gt;

&lt;p&gt;Você já teve que lidar com um método gigante que fazia validação, cálculo e persistência tudo junto?&lt;/p&gt;

&lt;p&gt;Como resolveria isso no seu projeto: &lt;strong&gt;Chain of Responsibility ou outra abordagem?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Comenta aí embaixo!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
