Módulo 10: Paradigmas de Programação & Padrões de Projeto • Bloco 2: SOLID e GRASP

🏛️ A Sofisticação do Design Orientado a Objetos: Após dominar os padrões fundamentais de atribuição básica (Expert, Creator, Controller) e os critérios avaliativos (Low Coupling, High Cohesion), este capítulo explora o quarteto de ouro dos padrões avançados de Craig Larman: Polymorphism, Pure Fabrication, Indirection e o princípio-mãe de toda a engenharia de software sustentável: Protected Variations.


🗺️ Mapa Conceitual do Capítulo

flowchart TD
    GRASP2["Padrões GRASP Avançados (Craig Larman)"]
    
    GRASP2 --> POLY["1. Polymorphism (Polimorfismo)<br/>• Variações de comportamento por tipo delegadas a subclasses<br/>• Eliminação de cadeias if-else e switch de tipos"]
    
    GRASP2 --> FAB["2. Pure Fabrication (Fabricação Pura)<br/>• Criação de classes artificiais sem lastro no mundo real<br/>• Repositórios, Serviços de Domínio, DAOs & Validadores"]
    
    GRASP2 --> IND["3. Indirection (Indireção)<br/>• Inserção de um intermediário mediador<br/>• 'Todo problema se resolve com outro nível de indireção'"]
    
    GRASP2 --> PV["4. Protected Variations (Variações Protegidas)<br/>• Identificação de pontos de instabilidade provável<br/>• Construção de contratos e interfaces blindadas"]

    style GRASP2 fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px
    style POLY fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px
    style FAB fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px
    style IND fill:#fce4ec,stroke:#e91e63,stroke-width:1.5px
    style PV fill:#ede7f6,stroke:#673ab7,stroke-width:1.5px

🎭 1. Polymorphism (Polimorfismo no GRASP)

“When related alternatives or behaviors vary by type (class), assign responsibility for the behavior—using polymorphic operations—to the types for which the behavior varies.” — Craig Larman

1.1 O Fim das Cadeias Condicionais

Em sistemas legados mal projetados, comportamentos que variam conforme o tipo de um registro são frequentemente espalhados em instruções condicionais procedurais:

# ANTI-PADRÃO: Polimorfismo negado via condicionais de tipo
def despachar_pedido(tipo_frete: str, pacote: Pacote):
    if tipo_frete == "PAC":
        ...
    elif tipo_frete == "SEDEX":
        ...
    elif tipo_frete == "DRONE":
        ...

Se uma nova modalidade de entrega for homologada (ex.: entrega por bicicleta elétrica), o desenvolvedor precisa localizar e alterar todos os blocos if/elif espalhados pelo repositório.

O padrão Polymorphism orienta: atribua a responsabilidade à própria abstração polimórfica. Cada tipo concreto de frete (FretePac, FreteSedex, FreteDrone) implementa seu próprio método despachar(pacote).

  • Sinergia: O padrão Polymorphism do GRASP é a técnica direta que viabiliza o Princípio Aberto/Fechado (OCP) do SOLID e o padrão comportamental Strategy do GoF.

🏭 2. Pure Fabrication (Fabricação Pura)

“Assign a highly cohesive set of responsibilities to an artificial or convenience class that does not represent a problem domain concept—something made up or purely fabricated to support high cohesion, low coupling, and reuse.” — Craig Larman

2.1 Decomposição Representacional vs. Decomposição Comportamental

Ao iniciar a modelagem orientada a objetos, os livros recomendam identificar os substantivos do mundo real: Cliente, Conta, Carro, Pedido. Isso é denominado Decomposição Representacional.

No entanto, sistemas de software corporativos possuem necessidades técnicas e algorítmicas que não existem no mundo real:

  • Quem deve ser responsável por salvar um Cliente em uma tabela PostgreSQL?
    • Se atribuirmos a persistência à classe Cliente (seguindo cegamente o Information Expert, já que Cliente tem os dados), transformamos o domínio em uma God Class amarrada a drivers SQL, quebrando a High Cohesion e o Low Coupling.
  • A Resposta: Criamos uma Fabricação Pura (Pure Fabrication), como ClienteRepository ou ClienteDAO.
    • Essa classe não existe no mundo real (um banco de dados físico não anda na rua cumprimentando clientes), mas ela é concebida artificialmente na arquitetura de software para isolar a infraestrutura e manter as classes conceituais limpas.
   Decomposição Representacional (Mundo Real):
   [Cliente] ──── Possui ────► [Contrato]
   
   Decomposição via Fabricação Pura (Design Arquitetural):
   [Cliente] ◄──── Gerenciado por ──── [ClienteRepository] (Pure Fab)
   [Cliente] ◄──── Validado por ────── [ValidadorBiometria] (Pure Fab)
   [Cliente] ◄──── Exportado por ───── [ExportadorJson] (Pure Fab)

2.2 Exemplos Consagrados de Fabricação Pura

  • Padrão Repository & Data Mapper: Classes de persistência desacopladas do modelo de domínio.
  • Domain Services (DDD): Classes que executam operações que envolvem múltiplas entidades sem pertencer conceitualmente a nenhuma delas (ex.: TransferenciaBancariaService).
  • Adapters e Notificadores: TwilioSmsAdapter, KafkaEventPublisher.

🔀 3. Indirection (Indireção)

“Assign the responsibility to an intermediate object to mediate between other components or services so that they are not directly coupled.” — Craig Larman

O aforismo célebre de David Wheeler (pioneiro britânico da computação) sintetiza esse princípio:

“All problems in computer science can be solved by another level of indirection, except for the problem of too many levels of indirection.”

3.1 O Papel do Intermediário

O padrão Indirection preconiza a inserção de um componente intermediário entre um emissor e um receptor para evitar o acoplamento direto ponto a ponto:

flowchart LR
    subgraph DIRECT["Acoplamento Direto Ponto a Ponto (Rígido)"]
        CLI1["Serviço Checkout"] --> G1["Stripe Gateway V1 API"]
    end

    subgraph INDIRECT["Indireção com Intermediário (Desacoplado)"]
        CLI2["Serviço Checkout"] --> ADAPT["Adaptador Intermediário<br/>«IGatewayPagamento»"]
        ADAPT --> G2["Stripe API V3"]
        ADAPT --> G3["MercadoPago API"]
    end

    style DIRECT fill:#ffebee,stroke:#f44336,stroke-width:1.5px
    style INDIRECT fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px
    style ADAPT fill:#fff3e0,stroke:#ff9800,stroke-width:2px

3.2 Padrões GoF que São Manifestações de Indirection

Praticamente metade dos padrões de projeto estruturais e comportamentais do GoF derivam da aplicação de Indireção:

  • Adapter: Interpõe um objeto intermediário para compatibilizar interfaces divergentes.
  • Facade: Interpõe uma interface simplificada unificada à frente de um subsistema complexo.
  • Proxy: Interpõe um substituto intermediário para controlar o acesso a um recurso pesado ou remoto.
  • Mediator: Interpõe um coordenador central para evitar que dezenas de objetos conversem entre si em malha completa (mesh).

🛡️ 4. Protected Variations (Variações Protegidas)

“Identify points of predicted variation or instability; assign responsibilities to create a stable interface around them.” — Craig Larman

O padrão Protected Variations (PV) é considerado por teóricos da arquitetura de software como o princípio fundamental e unificador de todo o design sustentável:

  • Qualquer sistema real sofrerá alterações: novas leis fiscais entrarão em vigor, provedores de nuvem mudarão suas APIs REST, bancos de dados relacionais serão substituídos por NoSQL, novos modelos de hardware surgirão.
  • O engenheiro experiente não tenta impedir a mudança: ele identifica onde a mudança é provável e constrói uma interface estável ao redor desse ponto crítico de instabilidade, blindando o restante do sistema contra o impacto dessas oscilações.
flowchart TD
    CORE["Núcleo de Regras de Negócio<br/>(Imune a mudanças externas)"]
    
    CORE --> CONTRACT["«Interface Blindada»<br/>IProvedorAutorizacaoCartao"]
    
    CONTRACT -.-> IMPL1["Adquirente Cielo (Driver Legado)"]
    CONTRACT -.-> IMPL2["Adquirente Rede (Driver Atual)"]
    CONTRACT -.-> IMPL3["Novo Gateway Cloud 2026"]

    style CORE fill:#e8f5e9,stroke:#4caf50,stroke-width:2px
    style CONTRACT fill:#ede7f6,stroke:#673ab7,stroke-width:2px
    style IMPL1 fill:#f5f5f5,stroke:#9e9e9e,stroke-width:1px
    style IMPL2 fill:#f5f5f5,stroke:#9e9e9e,stroke-width:1px
    style IMPL3 fill:#f5f5f5,stroke:#9e9e9e,stroke-width:1px

4.1 A Relação Ancestral entre PV, OCP e Information Hiding

  • O Princípio de Ocultamento de Informações (Information Hiding) de David Parnas (1972): Cada módulo deve ocultar um segredo de design (geralmente uma decisão técnica volátil).
  • O Princípio Aberto/Fechado (OCP) de Bertrand Meyer (1988): Aberto para extensão, fechado para modificação.
  • O Padrão Protected Variations de Craig Larman (1997): Formaliza como identificar os pontos de instabilidade e atribuir as responsabilidades através de polimorfismo e interfaces.

    4.2 Protected Variations em Nível de Arquitetura de Sistemas

    O padrão Protected Variations não se limita a classes e interfaces no mesmo processo de memória; ele é o fundamento das maiores inovações de arquitetura de sistemas distribuídos:

  • APIs Versionadas (REST / gRPC): A interface pública de um microsserviço atua como a barreira de variações protegidas. Alterações internas no esquema de banco de dados do serviço não quebram clientes externos desde que o contrato HTTP/JSON continue sendo honrado.
  • Tolerância a Falhas e Circuit Breakers: Quando um gateway bancário parceiro fica instável, um componente de indireção protegido intercepta o timeout e aciona um fallback automático sem propagar a pane para o usuário final.
  • Máquinas Virtuais e Bytecode (JVM / .NET CLR): A especificação do bytecode é a interface estável definitiva que protege os desenvolvedores contra as centenas de variações de arquiteturas de processadores e sistemas operacionais subjacentes.

🌉 5. A Ponte Arquitetural: De GRASP para os 23 Padrões GoF

Muitos desenvolvedores aprendem os padrões GoF como receitas isoladas e sofrem para saber quando aplicá-los. Compreender o GRASP esclarece que os padrões GoF são apenas cristalizações técnicas avançadas dos princípios GRASP:

  • GoF Strategy & State: São aplicações diretas de Polymorphism e Protected Variations para encapsular algoritmos ou estados variantes.
  • GoF Adapter & Facade: São aplicações de Indirection e Pure Fabrication para reconciliar interfaces incompatíveis ou unificar subsistemas.
  • GoF Factory Method & Abstract Factory: São especializações de Creator combinadas com Pure Fabrication para desonerar clientes do acoplamento direto com construtores.
  • GoF Observer & Mediator: São refinamentos de Indirection e Low Coupling para viabilizar notificações desacopladas e orquestrações centralizadas.

Ao dominar as 9 diretrizes de Craig Larman, você deixa de memorizar diagramas de classes e passa a enxergar a motivação profunda por trás de cada padrão de software catalogado na indústria.


📊 6. Matriz Holística dos 9 Padrões GRASP

A matriz completa dos 9 padrões propostos por Craig Larman resume a sabedoria da modelagem orientada a objetos:

Padrão GRASP Categoria Finalidade Arquitetural Primária
Information Expert Fundamental / Atribuição Colocar a lógica onde os dados residem, preservando encapsulamento.
Creator Fundamental / Atribuição Delegar a criação de objetos para seus agregadores naturais.
Controller Fundamental / Atribuição Receber eventos da UI e orquestrar fluxos sem misturar apresentação e domínio.
Low Coupling Fundamental / Avaliativo Minimizar a dependência entre módulos e bibliotecas.
High Cohesion Fundamental / Avaliativo Manter classes com responsabilidades estritamente focadas e coesas.
Polymorphism Avançado / Variação Tratar variações de tipo por operações polimórficas, eliminando switch/if.
Pure Fabrication Avançado / Estrutura Criar classes artificiais técnicas (DAOs, Repositories) para manter coesão.
Indirection Avançado / Desacoplamento Adicionar intermediários (Adapters, Mediators) para evitar acoplamento direto.
Protected Variations Avançado / Resiliência Blindar o sistema contra pontos previsíveis de volatilidade técnica ou legal.

Ao dominar conjuntamente os princípios SOLID e as heurísticas GRASP, o arquiteto de software desenvolve um olhar clínico capaz de diagnosticar precocemente sintomas de degradação estrutural, projetando sistemas que acolhem requisitos emergentes com custo marginal decrescente e máxima confiabilidade.