<?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: bruno candido salles</title>
    <description>The latest articles on DEV Community by bruno candido salles (@bruno_candidosalles_5a2d).</description>
    <link>https://dev.to/bruno_candidosalles_5a2d</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%2F4123728%2F3cb54d7e-b417-4882-af7f-a931ef058e08.jpg</url>
      <title>DEV Community: bruno candido salles</title>
      <link>https://dev.to/bruno_candidosalles_5a2d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bruno_candidosalles_5a2d"/>
    <language>en</language>
    <item>
      <title>Chain of Responsibility em Java: como transformamos um if de 600 linhas em um pipeline de autorização de pagamentos</title>
      <dc:creator>bruno candido salles</dc:creator>
      <pubDate>Mon, 14 Sep 2026 01:14:45 +0000</pubDate>
      <link>https://dev.to/bruno_candidosalles_5a2d/chain-of-responsibility-em-java-como-transformamos-um-if-de-600-linhas-em-um-pipeline-de-501g</link>
      <guid>https://dev.to/bruno_candidosalles_5a2d/chain-of-responsibility-em-java-como-transformamos-um-if-de-600-linhas-em-um-pipeline-de-501g</guid>
      <description>&lt;h1&gt;
  
  
  Chain of Responsibility em Java: como transformamos um &lt;code&gt;if&lt;/code&gt; de 600 linhas em um pipeline de autorização de pagamentos
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Padrão comportamental · Java 21 · Spring Boot&lt;/p&gt;
&lt;/blockquote&gt;




&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; (Corrente de Responsabilidade) é um padrão &lt;strong&gt;comportamental&lt;/strong&gt; do catálogo GoF. Padrões comportamentais tratam de &lt;em&gt;como objetos se comunicam e distribuem responsabilidades entre si&lt;/em&gt; — diferente dos criacionais (como objetos nascem) e dos estruturais (como objetos se compõem).&lt;/p&gt;

&lt;p&gt;A ideia central é simples: em vez de um único objeto decidir tudo, você monta uma &lt;strong&gt;fila de tratadores independentes&lt;/strong&gt;. Cada um recebe a requisição, decide se consegue resolvê-la e, se não conseguir, &lt;strong&gt;passa adiante&lt;/strong&gt; para o próximo. Quem chama não sabe — e não precisa saber — qual elo da corrente vai efetivamente responder.&lt;/p&gt;

&lt;p&gt;Se você já escreveu um &lt;code&gt;Filter&lt;/code&gt; de Servlet, configurou o &lt;code&gt;SecurityFilterChain&lt;/code&gt; do Spring Security ou usou middleware em Express/ASP.NET, você já usou Chain of Responsibility. É um dos padrões mais presentes em frameworks de produção e um dos menos aplicados conscientemente em código de aplicação.&lt;/p&gt;

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

&lt;p&gt;O padrão ataca uma dor específica e muito comum: &lt;strong&gt;um único método concentra uma sequência de decisões condicionais que cresce indefinidamente&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;O sintoma clássico é o método que começou com 20 linhas e hoje tem 600:&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="nc"&gt;Resultado&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;Transacao&lt;/span&gt; &lt;span class="n"&gt;t&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;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getValor&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&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="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;moedasSuportadas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMoeda&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="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blacklistRepo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;existe&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getClienteId&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="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;antifraudeClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;consultar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// 400ms, API paga&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;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;80&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="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;50&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="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPais&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DE"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getValor&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;30&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="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="cm"&gt;/* mais 14 condições */&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;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Os problemas que isso gera não são estéticos:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Sintoma&lt;/th&gt;
&lt;th&gt;Consequência prática&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Toda regra nova altera a mesma classe&lt;/td&gt;
&lt;td&gt;Violação do Open/Closed Principle; conflito de merge em todo sprint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Regras acopladas dentro de um único método&lt;/td&gt;
&lt;td&gt;Impossível testar a regra de blacklist sem instanciar todo o resto&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ordem de execução implícita no aninhamento&lt;/td&gt;
&lt;td&gt;Ninguém sabe dizer, olhando de fora, o que roda antes do quê&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chamadas caras executadas cedo demais&lt;/td&gt;
&lt;td&gt;Latência e custo pagos mesmo quando uma regra barata já teria negado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decisão anônima&lt;/td&gt;
&lt;td&gt;O log diz "transação negada", mas não diz &lt;strong&gt;qual&lt;/strong&gt; regra negou&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;O último ponto é o que costuma virar incidente às três da manhã. O penúltimo é o que vira fatura no fim do mês.&lt;/p&gt;

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

&lt;p&gt;A analogia mais próxima do dia a dia de software é o &lt;strong&gt;pipeline de filtros de um servidor web&lt;/strong&gt;. Uma requisição HTTP entra e atravessa uma sequência: filtro de CORS, filtro de autenticação, filtro de autorização, filtro de rate limit. Cada filtro tem duas opções — &lt;strong&gt;interromper&lt;/strong&gt; a requisição ali mesmo (401, 429) ou &lt;strong&gt;deixar passar&lt;/strong&gt; para o próximo. Nenhum filtro conhece a existência do controller no fim da linha, e nenhum filtro precisa conhecer os outros filtros.&lt;/p&gt;

&lt;p&gt;Traduzindo para as peças do padrão:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Handler (Tratador)&lt;/strong&gt;: a interface ou classe abstrata que define o contrato &lt;code&gt;trate(requisição)&lt;/code&gt; e guarda a referência para o próximo elo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ConcreteHandler&lt;/strong&gt;: cada tratador específico. Implementa &lt;em&gt;uma&lt;/em&gt; regra e decide entre resolver ou delegar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client&lt;/strong&gt;: quem monta a corrente e dispara a requisição na primeira ponta.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Duas propriedades merecem destaque porque são o motivo de o padrão existir:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Desacoplamento entre emissor e receptor.&lt;/strong&gt; O cliente chama &lt;code&gt;corrente.autorizar(t)&lt;/code&gt; e recebe uma resposta. Não sabe quantos elos existem nem qual respondeu.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A ordem vira dado, não código.&lt;/strong&gt; A sequência deixa de estar enterrada em aninhamento de &lt;code&gt;if&lt;/code&gt; e passa a ser uma linha explícita e versionada em um arquivo de configuração. Reordenar a corrente é mudar uma linha — e, como veremos, reordenar é exatamente o que resolve o gargalo.&lt;/li&gt;
&lt;/ol&gt;




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

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

&lt;p&gt;O contexto é o microsserviço &lt;code&gt;ms-pagamentos&lt;/code&gt; de uma plataforma de e-commerce que opera no Brasil e na Europa. Antes de enviar qualquer transação ao adquirente (PSP), o serviço precisa tomar uma decisão de autorização: &lt;strong&gt;APROVAR&lt;/strong&gt;, &lt;strong&gt;NEGAR&lt;/strong&gt; ou mandar para &lt;strong&gt;REVISÃO&lt;/strong&gt; manual.&lt;/p&gt;

&lt;p&gt;Cinco regras compõem essa decisão, com custos de execução radicalmente diferentes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Regra&lt;/th&gt;
&lt;th&gt;O que faz&lt;/th&gt;
&lt;th&gt;Custo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Dados cadastrais&lt;/td&gt;
&lt;td&gt;Valor positivo, moeda suportada&lt;/td&gt;
&lt;td&gt;~0 ms (memória)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Lista restritiva&lt;/td&gt;
&lt;td&gt;Cliente bloqueado por chargeback anterior&lt;/td&gt;
&lt;td&gt;~2 ms (Redis)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Velocidade transacional&lt;/td&gt;
&lt;td&gt;Mais de 5 tentativas em 10 minutos&lt;/td&gt;
&lt;td&gt;~3 ms (Redis)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Autenticação forte (SCA/3DS)&lt;/td&gt;
&lt;td&gt;Emissor na UE e valor acima da isenção&lt;/td&gt;
&lt;td&gt;~0 ms (memória)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Score antifraude&lt;/td&gt;
&lt;td&gt;Consulta a bureau externo&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~400 ms, cobrado por consulta&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No código legado, as cinco regras viviam em um único método de &lt;code&gt;PagamentoService&lt;/code&gt;, e o score antifraude era consultado &lt;strong&gt;antes&lt;/strong&gt; das validações baratas — herança de uma implementação em que o score era a única regra existente.&lt;/p&gt;

&lt;p&gt;O resultado: &lt;strong&gt;100% das transações pagavam 400 ms e uma consulta faturada&lt;/strong&gt;, inclusive aquelas com valor negativo ou de clientes já na lista restritiva, que seriam negadas de qualquer forma. O p95 do endpoint de checkout estava em 1,2 s, e a linha do bureau antifraude era a maior despesa variável do time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota de transparência:&lt;/strong&gt; os números deste estudo de caso são ilustrativos, construídos para representar uma situação realista de engenharia. Se você for reproduzir o experimento, meça os seus.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O objetivo da refatoração tinha dois lados:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Arquitetural:&lt;/strong&gt; permitir adicionar, remover ou desligar regras sem tocar nas existentes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;De performance/custo:&lt;/strong&gt; executar as regras da mais barata para a mais cara, com curto-circuito na primeira decisão.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Chain of Responsibility resolve os dois com a mesma estrutura, e é por isso que ele foi o padrão escolhido em vez de Strategy — Strategy trocaria &lt;em&gt;qual&lt;/em&gt; algoritmo roda, mas não resolveria a &lt;em&gt;sequência&lt;/em&gt; nem o curto-circuito.&lt;/p&gt;

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

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

&lt;p&gt;Estrutura do padrão aplicada exatamente ao código apresentado na próxima seção.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;classDiagram
    direction LR

    class AutorizacaoService {
        -RegraAutorizacao correnteDeAutorizacao
        -TransacaoRepository transacaoRepository
        +autorizar(Transacao) ResultadoAutorizacao
    }

    class RegraAutorizacao {
        &amp;lt;&amp;lt;abstract&amp;gt;&amp;gt;
        -RegraAutorizacao proxima
        +encadear(RegraAutorizacao) RegraAutorizacao
        +autorizar(Transacao) ResultadoAutorizacao
        #avaliar(Transacao) Optional~ResultadoAutorizacao~
    }

    class RegraDadosCadastrais {
        #avaliar(Transacao) Optional~ResultadoAutorizacao~
    }
    class RegraListaRestritiva {
        -ListaRestritivaRepository repositorio
        #avaliar(Transacao) Optional~ResultadoAutorizacao~
    }
    class RegraVelocidadeTransacional {
        -ContadorTentativas contador
        #avaliar(Transacao) Optional~ResultadoAutorizacao~
    }
    class RegraAutenticacaoForte {
        #avaliar(Transacao) Optional~ResultadoAutorizacao~
    }
    class RegraScoreAntifraude {
        -ClienteAntifraude clienteAntifraude
        #avaliar(Transacao) Optional~ResultadoAutorizacao~
    }

    class Transacao {
        &amp;lt;&amp;lt;record&amp;gt;&amp;gt;
        +String id
        +String clienteId
        +BigDecimal valor
        +String moeda
        +String paisEmissor
    }

    class ResultadoAutorizacao {
        &amp;lt;&amp;lt;record&amp;gt;&amp;gt;
        +Decisao decisao
        +String regra
        +String motivo
    }

    class Decisao {
        &amp;lt;&amp;lt;enumeration&amp;gt;&amp;gt;
        APROVAR
        REVISAR
        NEGAR
    }

    class ListaRestritivaRepository {
        &amp;lt;&amp;lt;interface&amp;gt;&amp;gt;
        +contemCliente(String) boolean
    }
    class ClienteAntifraude {
        &amp;lt;&amp;lt;interface&amp;gt;&amp;gt;
        +consultarScore(Transacao) int
    }

    RegraAutorizacao o-- RegraAutorizacao : proxima
    RegraAutorizacao &amp;lt;|-- RegraDadosCadastrais
    RegraAutorizacao &amp;lt;|-- RegraListaRestritiva
    RegraAutorizacao &amp;lt;|-- RegraVelocidadeTransacional
    RegraAutorizacao &amp;lt;|-- RegraAutenticacaoForte
    RegraAutorizacao &amp;lt;|-- RegraScoreAntifraude

    AutorizacaoService --&amp;gt; RegraAutorizacao : dispara
    RegraAutorizacao ..&amp;gt; Transacao : recebe
    RegraAutorizacao ..&amp;gt; ResultadoAutorizacao : produz
    ResultadoAutorizacao --&amp;gt; Decisao
    RegraListaRestritiva --&amp;gt; ListaRestritivaRepository
    RegraScoreAntifraude --&amp;gt; ClienteAntifraude&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;O ponto mais importante do diagrama é a &lt;strong&gt;auto-associação&lt;/strong&gt; &lt;code&gt;RegraAutorizacao o-- RegraAutorizacao&lt;/code&gt;. É ela que caracteriza o padrão: o tratador conhece um tratador do mesmo tipo, o que permite montar uma corrente de tamanho arbitrário sem que nenhuma classe concreta conheça outra.&lt;/p&gt;

&lt;h4&gt;
  
  
  Arquitetura de Software (alto nível)
&lt;/h4&gt;

&lt;p&gt;Onde a corrente se encaixa no ecossistema.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TB
    subgraph canais["Canais"]
        WEB["Checkout Web"]
        APP["App Mobile"]
    end

    GW["API Gateway"]

    subgraph pagamentos["ms-pagamentos - Spring Boot"]
        CTRL["PagamentoController"]
        SVC["AutorizacaoService"]
        subgraph corrente["Corrente de Autorizacao"]
            direction TB
            R1["1 - Dados Cadastrais&amp;lt;br/&amp;gt;custo ~0ms"]
            R2["2 - Lista Restritiva&amp;lt;br/&amp;gt;custo ~2ms"]
            R3["3 - Velocidade&amp;lt;br/&amp;gt;custo ~3ms"]
            R4["4 - Autenticacao Forte&amp;lt;br/&amp;gt;custo ~0ms"]
            R5["5 - Score Antifraude&amp;lt;br/&amp;gt;custo ~400ms - pago"]
            R1 --&amp;gt;|"nao decidiu"| R2
            R2 --&amp;gt;|"nao decidiu"| R3
            R3 --&amp;gt;|"nao decidiu"| R4
            R4 --&amp;gt;|"nao decidiu"| R5
        end
    end

    REDIS[("Redis&amp;lt;br/&amp;gt;lista restritiva + contadores")]
    PG[("PostgreSQL&amp;lt;br/&amp;gt;transacoes e decisoes")]
    FRAUDE["API Antifraude&amp;lt;br/&amp;gt;bureau externo"]
    PSP["Adquirente / PSP"]
    KAFKA["Kafka&amp;lt;br/&amp;gt;topico decisoes-autorizacao"]
    NOTIF["ms-notificacoes"]
    BI["Data Lake / BI"]

    WEB --&amp;gt; GW
    APP --&amp;gt; GW
    GW --&amp;gt; CTRL
    CTRL --&amp;gt; SVC
    SVC --&amp;gt; R1
    R2 -.-&amp;gt; REDIS
    R3 -.-&amp;gt; REDIS
    R5 -.-&amp;gt; FRAUDE
    SVC --&amp;gt; PG
    SVC --&amp;gt;|"decisao APROVAR"| PSP
    SVC --&amp;gt; KAFKA
    KAFKA --&amp;gt; NOTIF
    KAFKA --&amp;gt; BI&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Observe o efeito de custo: uma transação negada no elo 1 ou 2 &lt;strong&gt;nunca chega&lt;/strong&gt; ao bureau externo. As setas pontilhadas representam I/O — e é justamente por serem I/O que essas regras ficam no fim da corrente.&lt;/p&gt;

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

&lt;h4&gt;
  
  
  Contratos de domínio
&lt;/h4&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="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Transacao&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;String&lt;/span&gt; &lt;span class="n"&gt;clienteId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="n"&gt;valor&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;moeda&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;paisEmissor&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;Instant&lt;/span&gt; &lt;span class="n"&gt;criadaEm&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;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;enum&lt;/span&gt; &lt;span class="nc"&gt;Decisao&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="no"&gt;APROVAR&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;REVISAR&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;NEGAR&lt;/span&gt; &lt;span class="o"&gt;}&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="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Decisao&lt;/span&gt; &lt;span class="n"&gt;decisao&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;regra&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;motivo&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;static&lt;/span&gt; &lt;span class="nc"&gt;ResultadoAutorizacao&lt;/span&gt; &lt;span class="nf"&gt;aprovar&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="nc"&gt;Decisao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;APROVAR&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"CORRENTE_COMPLETA"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Nenhuma regra bloqueou a transacao"&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;static&lt;/span&gt; &lt;span class="nc"&gt;ResultadoAutorizacao&lt;/span&gt; &lt;span class="nf"&gt;negar&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;regra&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;motivo&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Decisao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NEGAR&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;regra&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;motivo&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;static&lt;/span&gt; &lt;span class="nc"&gt;ResultadoAutorizacao&lt;/span&gt; &lt;span class="nf"&gt;revisar&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;regra&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;motivo&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Decisao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;REVISAR&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;regra&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;motivo&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;O campo &lt;code&gt;regra&lt;/code&gt; no resultado resolve o problema de observabilidade citado lá no começo: toda decisão carrega o nome de quem a tomou.&lt;/p&gt;

&lt;h4&gt;
  
  
  O Handler abstrato — o coração do padrão
&lt;/h4&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;RegraAutorizacao&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;RegraAutorizacao&lt;/span&gt; &lt;span class="n"&gt;proxima&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/** Encadeia e devolve o proximo elo, permitindo montagem fluente. */&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;RegraAutorizacao&lt;/span&gt; &lt;span class="nf"&gt;encadear&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RegraAutorizacao&lt;/span&gt; &lt;span class="n"&gt;proxima&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;proxima&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;proxima&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;proxima&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/** Template Method: fixa o fluxo de delegacao para todas as subclasses. */&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ResultadoAutorizacao&lt;/span&gt; &lt;span class="nf"&gt;autorizar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Transacao&lt;/span&gt; &lt;span class="n"&gt;transacao&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="nf"&gt;avaliar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transacao&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orElseGet&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;proxima&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="nc"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;aprovar&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                        &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;proxima&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;transacao&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * Optional vazio = "nao tenho opiniao, passe adiante".
     * Optional preenchido = "eu decido aqui, a corrente para".
     */&lt;/span&gt;
    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;avaliar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Transacao&lt;/span&gt; &lt;span class="n"&gt;transacao&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;Duas decisões de design valem comentário:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;autorizar&lt;/code&gt; é &lt;strong&gt;&lt;code&gt;final&lt;/code&gt;&lt;/strong&gt;. A mecânica de delegação é responsabilidade da classe base, não das subclasses. Isso é um Template Method dentro do Chain of Responsibility — a subclasse só implementa a regra, jamais o fluxo.&lt;/li&gt;
&lt;li&gt;O retorno é &lt;strong&gt;&lt;code&gt;Optional&lt;/code&gt;&lt;/strong&gt; em vez de &lt;code&gt;null&lt;/code&gt;. Torna explícito no tipo o contrato "não decidi", que é o que faz a corrente andar.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Os elos concretos
&lt;/h4&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;RegraDadosCadastrais&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RegraAutorizacao&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;Set&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="no"&gt;MOEDAS_SUPORTADAS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Set&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;"BRL"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"USD"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"EUR"&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;protected&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;avaliar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Transacao&lt;/span&gt; &lt;span class="n"&gt;t&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;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valor&lt;/span&gt;&lt;span class="o"&gt;()&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="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valor&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;compareTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ZERO&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&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;Optional&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="nc"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;negar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="s"&gt;"DADOS_CADASTRAIS"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Valor invalido"&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="no"&gt;MOEDAS_SUPORTADAS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;moeda&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;Optional&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="nc"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;negar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="s"&gt;"DADOS_CADASTRAIS"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Moeda nao suportada: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;moeda&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;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;empty&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;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;RegraListaRestritiva&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RegraAutorizacao&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;ListaRestritivaRepository&lt;/span&gt; &lt;span class="n"&gt;repositorio&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;RegraListaRestritiva&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ListaRestritivaRepository&lt;/span&gt; &lt;span class="n"&gt;repositorio&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;repositorio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repositorio&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;protected&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;avaliar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Transacao&lt;/span&gt; &lt;span class="n"&gt;t&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;repositorio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contemCliente&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;clienteId&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;Optional&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="nc"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;negar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="s"&gt;"LISTA_RESTRITIVA"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Cliente bloqueado por historico de chargeback"&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;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;empty&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;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;RegraVelocidadeTransacional&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RegraAutorizacao&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="kt"&gt;int&lt;/span&gt; &lt;span class="no"&gt;LIMITE_TENTATIVAS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&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;Duration&lt;/span&gt; &lt;span class="no"&gt;JANELA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofMinutes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&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;ContadorTentativas&lt;/span&gt; &lt;span class="n"&gt;contador&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;RegraVelocidadeTransacional&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ContadorTentativas&lt;/span&gt; &lt;span class="n"&gt;contador&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;contador&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;contador&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;protected&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;avaliar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Transacao&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;tentativas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;contador&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;tentativasRecentes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;clienteId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="no"&gt;JANELA&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;tentativas&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;LIMITE_TENTATIVAS&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;Optional&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="nc"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;revisar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="s"&gt;"VELOCIDADE"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Excesso de tentativas na janela: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;tentativas&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;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;empty&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;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;RegraAutenticacaoForte&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RegraAutorizacao&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;Set&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="no"&gt;PAISES_SCA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Set&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;"DE"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"FR"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ES"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"PT"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"IT"&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;BigDecimal&lt;/span&gt; &lt;span class="no"&gt;LIMITE_ISENCAO&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;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"30.00"&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;protected&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;avaliar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Transacao&lt;/span&gt; &lt;span class="n"&gt;t&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="no"&gt;PAISES_SCA&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;paisEmissor&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valor&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;compareTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;LIMITE_ISENCAO&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&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;Optional&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="nc"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;revisar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="s"&gt;"AUTENTICACAO_FORTE"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Transacao exige desafio 3DS"&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;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;empty&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;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;RegraScoreAntifraude&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RegraAutorizacao&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="kt"&gt;int&lt;/span&gt; &lt;span class="no"&gt;SCORE_BLOQUEIO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&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="kt"&gt;int&lt;/span&gt; &lt;span class="no"&gt;SCORE_REVISAO&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&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;ClienteAntifraude&lt;/span&gt; &lt;span class="n"&gt;clienteAntifraude&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;RegraScoreAntifraude&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ClienteAntifraude&lt;/span&gt; &lt;span class="n"&gt;clienteAntifraude&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;clienteAntifraude&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clienteAntifraude&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;protected&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;avaliar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Transacao&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clienteAntifraude&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;consultarScore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// ~400ms, cobrado&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;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="no"&gt;SCORE_BLOQUEIO&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;Optional&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="nc"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;negar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="s"&gt;"SCORE_ANTIFRAUDE"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Score de risco: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;score&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;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="no"&gt;SCORE_REVISAO&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;Optional&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="nc"&gt;ResultadoAutorizacao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;revisar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="s"&gt;"SCORE_ANTIFRAUDE"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Score intermediario: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;score&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;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;empty&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;h4&gt;
  
  
  Montagem da corrente
&lt;/h4&gt;

&lt;p&gt;Aqui está o ganho arquitetural mais concreto: a ordem de execução de todo o motor de autorização cabe em cinco linhas, em um único arquivo versionado.&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;@Configuration&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;CorrenteAutorizacaoConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;RegraAutorizacao&lt;/span&gt; &lt;span class="nf"&gt;correnteDeAutorizacao&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="nc"&gt;ListaRestritivaRepository&lt;/span&gt; &lt;span class="n"&gt;listaRestritivaRepository&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="nc"&gt;ContadorTentativas&lt;/span&gt; &lt;span class="n"&gt;contadorTentativas&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="nc"&gt;ClienteAntifraude&lt;/span&gt; &lt;span class="n"&gt;clienteAntifraude&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;RegraAutorizacao&lt;/span&gt; &lt;span class="n"&gt;inicio&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;RegraDadosCadastrais&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;inicio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;encadear&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;RegraListaRestritiva&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listaRestritivaRepository&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
              &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;encadear&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;RegraVelocidadeTransacional&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contadorTentativas&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
              &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;encadear&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;RegraAutenticacaoForte&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
              &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;encadear&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;RegraScoreAntifraude&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clienteAntifraude&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;inicio&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// devolve a ponta da corrente&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;Repare que as regras &lt;strong&gt;não&lt;/strong&gt; são anotadas com &lt;code&gt;@Component&lt;/code&gt;. Elas são instanciadas aqui de propósito: como o elo guarda estado mutável (&lt;code&gt;proxima&lt;/code&gt;), transformá-las em singletons gerenciados pelo contêiner criaria uma armadilha no dia em que o sistema precisar de duas correntes diferentes — ambas escreveriam no mesmo objeto.&lt;/p&gt;

&lt;h4&gt;
  
  
  Ponto de entrada
&lt;/h4&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;AutorizacaoService&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;RegraAutorizacao&lt;/span&gt; &lt;span class="n"&gt;correnteDeAutorizacao&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;TransacaoRepository&lt;/span&gt; &lt;span class="n"&gt;transacaoRepository&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;PublicadorDeEventos&lt;/span&gt; &lt;span class="n"&gt;publicador&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;AutorizacaoService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RegraAutorizacao&lt;/span&gt; &lt;span class="n"&gt;correnteDeAutorizacao&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                              &lt;span class="nc"&gt;TransacaoRepository&lt;/span&gt; &lt;span class="n"&gt;transacaoRepository&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                              &lt;span class="nc"&gt;PublicadorDeEventos&lt;/span&gt; &lt;span class="n"&gt;publicador&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;correnteDeAutorizacao&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;correnteDeAutorizacao&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;transacaoRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transacaoRepository&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;publicador&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;publicador&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;ResultadoAutorizacao&lt;/span&gt; &lt;span class="nf"&gt;autorizar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Transacao&lt;/span&gt; &lt;span class="n"&gt;transacao&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;ResultadoAutorizacao&lt;/span&gt; &lt;span class="n"&gt;resultado&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;correnteDeAutorizacao&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;transacao&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;transacaoRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;registrarDecisao&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transacao&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resultado&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;publicador&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;publicar&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;DecisaoTomada&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transacao&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;resultado&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;resultado&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;O serviço tem &lt;strong&gt;uma&lt;/strong&gt; linha de regra de negócio e não conhece nenhuma regra concreta. Adicionar uma sexta regra amanhã não toca neste arquivo.&lt;/p&gt;

&lt;h4&gt;
  
  
  Testabilidade
&lt;/h4&gt;

&lt;p&gt;Este é o benefício que aparece primeiro no dia a dia. Cada elo é testável sozinho, sem contexto Spring, sem mock de framework:&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;@Test&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;deveNegarQuandoClienteEstaEmListaRestritiva&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;ListaRestritivaRepository&lt;/span&gt; &lt;span class="n"&gt;repositorio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clienteId&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;// lambda, sem Mockito&lt;/span&gt;
    &lt;span class="nc"&gt;RegraAutorizacao&lt;/span&gt; &lt;span class="n"&gt;regra&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;RegraListaRestritiva&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repositorio&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nc"&gt;ResultadoAutorizacao&lt;/span&gt; &lt;span class="n"&gt;resultado&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;regra&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;umaTransacaoValida&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

    &lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Decisao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NEGAR&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resultado&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;decisao&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"LISTA_RESTRITIVA"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resultado&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;regra&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;deveDelegarQuandoClienteNaoEstaEmListaRestritiva&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;RegraAutorizacao&lt;/span&gt; &lt;span class="n"&gt;regra&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;RegraListaRestritiva&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clienteId&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;regra&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;encadear&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;RegraDadosCadastrais&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;   &lt;span class="c1"&gt;// corrente montada no teste&lt;/span&gt;

    &lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Decisao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;APROVAR&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;regra&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;umaTransacaoValida&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;decisao&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;
  
  
  Prós e Contras
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Open/Closed na prática.&lt;/strong&gt; Regra nova é classe nova mais uma linha na configuração. Nenhuma classe existente é editada, o que elimina a categoria de bug "mexi na regra A e quebrei a B".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single Responsibility de verdade.&lt;/strong&gt; Cada classe tem um motivo para mudar. &lt;code&gt;RegraScoreAntifraude&lt;/code&gt; muda quando o bureau muda o contrato; nada mais.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A ordem vira decisão explícita e barata de reverter.&lt;/strong&gt; Foi isso que resolveu o gargalo: mover o elo caro para o fim é mudar a posição de uma linha, não reescrever aninhamento de &lt;code&gt;if&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Curto-circuito reduz latência e custo.&lt;/strong&gt; No cenário descrito, transações negadas por regras baratas param antes do I/O caro.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testabilidade isolada e rápida.&lt;/strong&gt; Testes unitários sem contexto de aplicação, na casa dos milissegundos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observabilidade embutida.&lt;/strong&gt; Toda decisão carrega o nome da regra, o que transforma o log de "negado" em "negado por LISTA_RESTRITIVA".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Desligar uma regra é remover uma linha.&lt;/strong&gt; Combinado com feature flag, permite desativar uma regra problemática em produção sem deploy de código de negócio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Custos e trade-offs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ignorar esta parte é o erro mais comum ao adotar padrões. O Chain of Responsibility cobra:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Explosão de arquivos.&lt;/strong&gt; Cinco regras viraram sete classes mais uma configuração. Se o sistema tem duas regras estáveis que não mudam há dois anos, o padrão é overengineering puro — o &lt;code&gt;if&lt;/code&gt; era melhor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O fluxo some do código.&lt;/strong&gt; Você não consegue mais ler a lógica de autorização de cima para baixo em um arquivo. Precisa abrir a configuração para saber a ordem. Debug exige acompanhar a pilha de delegação, e stack traces ficam mais profundos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nenhuma garantia de tratamento.&lt;/strong&gt; Se nenhum elo decide, a requisição chega ao fim da corrente sem resposta. Aqui isso foi resolvido com um fallback explícito (&lt;code&gt;aprovar()&lt;/code&gt;), mas em muitas implementações o resultado é um &lt;code&gt;null&lt;/code&gt; silencioso — um dos bugs mais caros que o padrão pode gerar. &lt;strong&gt;Sempre defina o comportamento da ponta final.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A ordem vira dependência oculta.&lt;/strong&gt; O ganho de performance depende da ordem estar correta. Alguém que mova o score antifraude para o topo não quebra nenhum teste funcional — só triplica a latência e a fatura. Vale um teste que assegure a ordem, ou pelo menos uma métrica por elo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execução estritamente sequencial.&lt;/strong&gt; Regras independentes poderiam rodar em paralelo, mas o padrão é serial por definição. Se as três regras de I/O fossem obrigatórias e independentes, um &lt;code&gt;CompletableFuture.allOf&lt;/code&gt; seria mais rápido que a corrente.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Não serve quando você precisa de todos os motivos.&lt;/strong&gt; Se o requisito for "retorne todas as regras violadas" em vez de "pare na primeira", o curto-circuito trabalha contra você. Nesse caso, o caminho é um pipeline acumulador de validadores ou o padrão Specification.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sobre &lt;strong&gt;variações de implementação&lt;/strong&gt;: em projetos Spring, é comum ver a corrente expressa como &lt;code&gt;List&amp;lt;RegraAutorizacao&amp;gt;&lt;/code&gt; injetada com &lt;code&gt;@Order&lt;/code&gt;, iterada por um orquestrador. É mais idiomático e dispensa o campo &lt;code&gt;proxima&lt;/code&gt;. Em compensação, deixa de ser uma corrente de verdade — é um laço sobre uma lista, e o elo perde a capacidade de decidir &lt;em&gt;se&lt;/em&gt; e &lt;em&gt;como&lt;/em&gt; invoca o próximo (fazer trabalho depois da delegação, por exemplo, como um filtro HTTP faz ao manipular a resposta na volta). A versão com &lt;code&gt;proxima&lt;/code&gt; apresentada aqui é a canônica e mais flexível; a versão com lista é mais simples. Escolha consciente, não por hábito.&lt;/p&gt;




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

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

&lt;p&gt;O Chain of Responsibility resolve um problema que quase todo sistema de médio porte encontra: uma sequência de decisões que cresce sem parar dentro de um único método. Ele quebra essa sequência em tratadores independentes e transforma a ordem de execução — antes implícita no aninhamento de condicionais — em configuração explícita.&lt;/p&gt;

&lt;p&gt;No caso apresentado, o valor entregue não foi apenas código mais limpo. Foi um gargalo concreto atacado: a regra mais cara deixou de ser executada em toda transação porque reordenar a corrente passou a custar uma linha. Esse é o teste que vale a pena aplicar antes de adotar qualquer padrão — &lt;strong&gt;se ele só deixa o código mais bonito, pense duas vezes; se ele muda o que o sistema é capaz de fazer barato, adote.&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Começo por onde deveria começar todo artigo técnico: &lt;strong&gt;não usei este padrão em um sistema de pagamentos em produção.&lt;/strong&gt; Sou estudante de Engenharia de Software e desenvolvedor backend em formação. O cenário deste artigo é um estudo de caso construído para ser realista, e a implementação que apresentei foi escrita e executada por mim justamente para poder falar dela com alguma propriedade. Prefiro dizer isso na cara do que simular experiência que não tenho — o leitor merece saber o peso do que está lendo.&lt;/p&gt;

&lt;p&gt;Dito isso, o que aprendi implementando não foi o que eu esperava aprender.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Primeiro: a mecânica é a parte fácil, e quase não é onde estão as decisões.&lt;/strong&gt; Encadear objetos e delegar é trivial. O que exigiu pensamento foi definir o contrato do elo — o que significa "não tenho opinião sobre esta transação". Minha primeira versão retornava &lt;code&gt;null&lt;/code&gt; para dizer isso, e virou um &lt;code&gt;NullPointerException&lt;/code&gt; em dez minutos. Trocar por &lt;code&gt;Optional&lt;/code&gt; não foi refinamento estético: fez o contrato ficar explícito no tipo, e o erro deixou de ser possível. Foi a primeira vez que senti, na prática, a diferença entre usar &lt;code&gt;Optional&lt;/code&gt; porque leram que é bom e usar porque ele resolve um problema concreto de modelagem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Segundo: descobri que já usava o padrão sem saber o nome dele.&lt;/strong&gt; Todo &lt;code&gt;Filter&lt;/code&gt; de Servlet, todo &lt;code&gt;SecurityFilterChain&lt;/code&gt; que configurei em projetos Spring Boot é exatamente isto — uma corrente de responsabilidade. Estudar o padrão formalmente mudou menos o código que escrevo e mais a minha capacidade de ler o código dos frameworks que uso todo dia. Isso me parece o ganho real de estudar padrões: não é ter mais ferramentas, é parar de olhar para o framework como caixa-preta.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terceiro, e o mais desconfortável: em algum momento eu achei o resultado pior que o &lt;code&gt;if&lt;/code&gt;.&lt;/strong&gt; Depois de quebrar a lógica em sete arquivos, abrir quatro deles para entender um fluxo que antes cabia em uma tela foi frustrante. Levei um tempo para entender que esse desconforto é o preço do padrão, não um sinal de que fiz algo errado — e que ele só compensa quando o número de regras cresce e elas mudam em ritmos diferentes. Com duas ou três regras estáveis, o &lt;code&gt;if&lt;/code&gt; ganha. Isso raramente aparece nos artigos sobre design patterns, e talvez seja a coisa mais útil que eu tenha para dizer aqui.&lt;/p&gt;

&lt;p&gt;Saio deste estudo com menos vontade de aplicar padrões e mais interesse em entender o custo de cada um. Suspeito que seja o sinal de que aprendi alguma coisa.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vamos conversar
&lt;/h3&gt;

&lt;p&gt;E na sua stack, onde a decisão de negócio mora hoje? Um método gigante, um motor de regras, um &lt;code&gt;switch&lt;/code&gt;, ou já um pipeline de tratadores?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Se você já refatorou um bloco de condicionais para Chain of Responsibility, ficou melhor ou você se arrependeu?&lt;/strong&gt; Estou especialmente interessado em casos em que o padrão foi a escolha errada — deixa nos comentários o que te fez voltar atrás.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Escrito por **Bruno Candido Salles&lt;/em&gt;* · Java 21 · Spring Boot 3.x · Diagramas em Mermaid*&lt;/p&gt;

&lt;p&gt;*Estudante de Engenharia de Software na UniEVANGÉLICA · Backend Java/Spring Boot&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>java</category>
      <category>softwareengineering</category>
    </item>
  </channel>
</rss>
