Módulo 10: Paradigmas de Programação & Padrões de Projeto • Bloco 1: Paradigmas e Modelos

🔄 Fechando o Fio Condutor (ver Capítulo 01, Capítulo 02 e Capítulo 03): O Carrinho de Compras encerra sua jornada pelos paradigmas fundacionais. Desta vez não escrevemos passos algorítmicos imperativos nem compomos funções matemáticas: nós declaramos fatos e regras de dedução (Paradigma Lógico), declaramos o resultado desejado (Paradigma Declarativo/SQL) e reagimos a fluxos contínuos de eventos no tempo (Paradigma Reativo).


🗺️ Mapa Conceitual do Capítulo

flowchart TD
    PARADIGMS["Paradigmas Baseados em Declaração, Dedução & Fluxos"]
    
    PARADIGMS --> DECL["1. Paradigma Declarativo Puro<br/>• Foco no 'O QUE' em vez de 'COMO'<br/>• SQL, DSLs, Álgebra Relacional"]
    PARADIGMS --> LOGIC["2. Paradigma Lógico (Prolog)<br/>• Fatos, Regras & Cláusulas de Horn<br/>• Unificação de Robinson & Backtracking"]
    PARADIGMS --> REACT["3. Paradigma Reativo (FRP)<br/>• The Reactive Manifesto<br/>• Observables Push vs Iterators Pull"]
    PARADIGMS --> FLOW["4. Gerenciamento de Contrapressão<br/>• Backpressure: Buffer, Drop, Sample<br/>• Fluxos assíncronos de alta escala"]

    style PARADIGMS fill:#ede7f6,stroke:#673ab7,stroke-width:2px
    style DECL fill:#e1f5fe,stroke:#03a9f4,stroke-width:1.5px
    style LOGIC fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px
    style REACT fill:#fce4ec,stroke:#e91e63,stroke-width:1.5px
    style FLOW fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px

🏛️ 1. O Paradigma Declarativo Puro: A Primazia do “O QUE”

Diferente do paradigma imperativo — que obriga o programador a ditar detalhadamente cada passo de execução, instrução de repetição e mutação de memória —, o paradigma declarativo puro expressa a lógica do cálculo sem descrever explicitamente o seu fluxo de controle operacional:

  • Separação entre Especificação e Execução: O código atua como uma especificação matemática da solução desejada. A decisão de como materializar essa especificação é delegada inteiramente a um mecanismo subjacente (interpretador, compilador ou otimizador de consultas).
  • Álgebra Relacional e SQL: Ao escrever uma consulta relacional, o desenvolvedor não especifica se a busca será feita por índice B-Tree, hash join ou varredura de tabela (full table scan):
-- Expressão puramente declarativa no Fio Condutor do Carrinho
SELECT 
    c.id_carrinho,
    i.produto,
    (i.preco * i.quantidade) AS subtotal
FROM carrinhos c
JOIN itens_carrinho i ON c.id_carrinho = i.id_carrinho
WHERE i.quantidade >= 2
ORDER BY subtotal DESC;
  • Linguagens de Domínio Específico (DSLs): O modelo declarativo domina a infraestrutura e a apresentação moderna:
    • HTML e CSS: Declaram a semântica da página e as propriedades visuais da árvore de nós (DOM), enquanto a GPU e a render engine calculam o layout e a rasterização.
    • Terraform e Kubernetes YAML: Declaram o estado desejado da infraestrutura na nuvem (número de réplicas, sub-redes, portas). Um laço de controle (reconciliation loop) ajusta a realidade física para convergir com o estado declarado.

🧠 2. O Paradigma Lógico: Dedução, Unificação e Busca

O paradigma lógico baseia-se na Lógica de Predicados de Primeira Ordem e no uso de Cláusulas de Horn, introduzido formalmente por Alain Colmerauer e Robert Kowalski no início dos anos 1970 com a criação da linguagem Prolog:

\[\text{Cláusula de Horn:} \quad H \leftarrow B_1 \land B_2 \land \dots \land B_n \quad (\text{Se todos } B_i \text{ forem verdadeiros, então } H \text{ é verdadeiro})\]

2.1 Componentes de um Programa Lógico

  1. Fatos (Facts): Afirmações atômicas e incondicionais sobre o universo do problema:
    no_carrinho(cart_01, mouse_gamer, 150.00, 2).
    no_carrinho(cart_01, teclado_mecanico, 350.00, 1).
    cliente_categoria(cart_01, vip).
    
  2. Regras (Rules): Proposições condicionais que derivam novos fatos a partir de relações existentes:
    elegivel_desconto_vip(Cart, Produto) :-
        cliente_categoria(Cart, vip),
        no_carrinho(Cart, Produto, Preco, _),
        Preco > 100.00.
    
  3. Consultas ou Metas (Queries / Goals): Interrogações feitas ao sistema para deduzir relações desconhecidas:
    ?- elegivel_desconto_vip(cart_01, Produto).
    

2.2 O Motor de Resolução: Unificação e Backtracking

  • Unificação de Robinson (1965): Processo algorítmico que encontra a substituição mais geral de variáveis para tornar duas expressões sintaticamente idênticas.
  • SLD-Resolution com Backtracking: O motor de inferência percorre a árvore de busca lógica em profundidade. Quando uma hipótese falha (um ramo atinge um beco sem saída), o interpretador realiza o retrocesso (backtracking), desfaz as vinculações de variáveis e tenta a próxima alternativa plausível até esgotar a base de conhecimento.
flowchart TD
    START["Consulta: ?- elegivel_frete_gratis(cart_01)"] --> R1{"Regra 1: Total > 300?"}
    R1 -- "Sim (Total = 650.00)" --> OK1["Meta Satisfeita (True)"]
    R1 -- "Não" --> R2{"Regra 2: Cupom VIP?"}
    R2 -- "Não" --> FAIL["Falha / Falso"]
    R2 -- "Sim" --> OK2["Meta Satisfeita (True)"]

    style START fill:#ede7f6,stroke:#673ab7,stroke-width:1.5px
    style R1 fill:#e1f5fe,stroke:#03a9f4,stroke-width:1px
    style R2 fill:#fff3e0,stroke:#ff9800,stroke-width:1px
    style OK1 fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px
    style OK2 fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px
    style FAIL fill:#ffebee,stroke:#f44336,stroke-width:1.5px

⚡ 3. O Paradigma Reativo e Sistemas Orientados a Fluxos

O paradigma reativo foi impulsionado pela necessidade de sistemas hiperconcorrentes, tolerantes a falhas e orientados a eventos, consolidados no The Reactive Manifesto (2014) através de quatro atributos essenciais:

  1. Responsivo: O sistema responde em tempo hábil e previsível.
  2. Resiliente: Permanece responsivo diante de panes através de isolamento e contenção.
  3. Elástico: Modula recursos proporcionalmente à oscilação da carga de trabalho.
  4. Orientado a Mensagens (Message-Driven): Adota comunicação assíncrona desacoplada por passagem de mensagens.

3.1 A Dualidade GoF Iterator (Pull) vs. Reactive Streams (Push)

A computação tradicional baseia-se no modelo Pull (o consumidor solicita o próximo item sob demanda). O modelo reativo inverte essa polaridade para Push (o produtor emite dados assim que eles se tornam disponíveis):

Característica Padrão Iterator GoF (Pull / Síncrono) Padrão Reactive Stream (Push / Assíncrono)
Origem do Controle O Consumidor controla o ritmo chamando next() O Produtor dispara eventos via onNext(item)
Retorno de Dados T next() bloqueia até o dado ser fornecido Callback assíncrono não bloqueante
Tratamento de Falha Lança exceção síncrona throw Exception Envia notificação de erro no canal onError(err)
Encerramento Esgota com booleano hasNext() == false Envia sinal explícito de término onComplete()
   Iterator (Pull):
   Consumidor ──── next() ────► Produtor
   Consumidor ◄─── Retorno ───  Produtor
   
   Reactive Stream (Push):
   Consumidor ──── Assinar ───► Produtor
   Consumidor ◄── onNext(dado)─ Produtor (Disparo contínuo no tempo)
   Consumidor ◄── onNext(dado)─ Produtor
   Consumidor ◄── onComplete()─ Produtor

3.2 O Desafio Crítico da Contrapressão (Backpressure)

Quando a velocidade de emissão do Produtor supera a capacidade de processamento do Consumidor (por exemplo, um surto de 50.000 cliques de compra por segundo durante a abertura de ingressos ou Black Friday), a memória do sistema entra em risco de saturação (OutOfMemoryError). O protocolo Reactive Streams resolve isso através de um canal bidirecional de sinalização onde o Consumidor solicita uma cota: subscription.request(n). Caso o fluxo seja irrestrito, três estratégias clássicas de mitigação são aplicadas:

  • Buffer: Enfileira os eventos temporariamente em uma estrutura de memória delimitada.
  • Drop: Descarta imediatamente os eventos que excederem o limiar de tolerância.
  • Sample / Throttle: Captura apenas uma amostra representativa por janela de tempo (ex.: o último evento a cada 200ms).

🛒 4. O Fio Condutor Integrado: O Carrinho nos 4 Paradigmas

Fechando o ciclo dos quatro capítulos do Bloco 1, contrastamos a mesma operação de liquidação fiscal de um carrinho de compras:

flowchart TD
    subgraph IMPERATIVE["Capítulo 01: Imperativo / Estruturado"]
        I1["for (int i=0; i < total_itens; i++) {<br/>    soma += itens[i].preco * itens[i].qtd;<br/>}"]
    end
    
    subgraph OOP["Capítulo 02: Orientado a Objetos"]
        O1["carrinho.adicionarItem(item);<br/>carrinho.definirEstrategiaFrete(new FreteExpresso());<br/>double total = carrinho.calcularTotalLiquidado();"]
    end
    
    subgraph FP["Capítulo 03: Funcional / Imutável"]
        F1["total = pipe(carrinho,<br/>    filtrar_elegiveis,<br/>    mapear_subtotais,<br/>    reduzir_soma,<br/>    aplicar_impostos)"]
    end
    
    subgraph DECL_REACT["Capítulo 04: Declarativo & Reativo"]
        D1["SELECT SUM(preco * qtd) FROM carrinho WHERE elegivel = TRUE;<br/>-- ou no barramento reativo:<br/>stream.filter(eh_elegivel).scan(somar).subscribe(renderizarUI);"]
    end

    style IMPERATIVE fill:#ffebee,stroke:#f44336,stroke-width:1.5px
    style OOP fill:#e8eaf6,stroke:#3f51b5,stroke-width:1.5px
    style FP fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px
    style DECL_REACT fill:#ede7f6,stroke:#673ab7,stroke-width:1.5px

📊 5. Matriz Comparativa Hexagonal dos 4 Paradigmas

Dimensão de Análise Imperativo (Cap 01) Orientado a Objetos (Cap 02) Funcional (Cap 03) Lógico / Declarativo / Reativo (Cap 04)
Abstração Central Sub-rotinas e Procedimentos Objetos, Classes e Métodos Funções Puras e Tipos Algébricos Relações, Predicados e Streams de Eventos
Modelo Conceitual Máquina de Turing / von Neumann Ontologia do Domínio em Entidades Cálculo Lambda ($\lambda$) Lógica de Horn / Teoria de Filas e Fluxos
Estado e Mutabilidade Mutável explícito em memória Encapsulado dentro do objeto Imutável estrito com persistência Sem estado mutável explícito / Estado derivado de fluxos
Direção do Fluxo Sequencial síncrono passo a passo Troca de mensagens entre grafos Composição de pipelines de funções Inferência dedutiva síncrona / Push assíncrono
Domínio Típico Sistemas operacionais, drivers, C/C++ Aplicações corporativas, GUI, Java/C# Concorrência massiva, finanças, dados Inteligência Artificial simbólica, bancos, Rx