💻 Exemplos: Padrões GRASP Avançados
Módulo 10: Paradigmas & Padrões • Bloco 2: SOLID & GRASP • Demonstrações Práticas
🏛️ Padrões GRASP Avançados na Prática: Demonstrações funcionais dos quatro padrões avançados de Craig Larman. No Exemplo 1, construímos uma arquitetura de pagamentos multimercado utilizando Polymorphism e Protected Variations com suporte a failover dinâmico. No Exemplo 2, aplicamos Pure Fabrication e Indirection para implementar um pipeline corporativo de auditoria de segurança assíncrono.
1. Gateway de Pagamento Multiprovedor: Polymorphism & Protected Variations
Neste exemplo, protegemos o núcleo de checkout contra a instabilidade e volatilidade de APIs de adquirentes terceiros. O cliente depende de uma interface estável (Protected Variations), e as diferentes operadoras respondem via despacho polimórfico (Polymorphism):
# grasp_pv_poly_pagamentos.py
from abc import ABC, abstractmethod
from typing import Dict, Any, List
from dataclasses import dataclass
import time
@dataclass(frozen=True)
class SolicitacaoCobranca:
id_pedido: str
cliente_documento: str
valor: float
moeda: str = "BRL"
@dataclass(frozen=True)
class RespostaCobranca:
sucesso: bool
codigo_autorizacao: str
operadora: str
mensagem: str
# 1. Protected Variations: Interface estável que blinda o negócio contra mudanças
class IAdquirentePagamento(ABC):
@abstractmethod
def autorizar(self, solicitacao: SolicitacaoCobranca) -> RespostaCobranca:
pass
@abstractmethod
def obter_nome_provedor(self) -> str:
pass
# 2. Polymorphism: Cada operadora encapsula suas particularidades de comunicação
class StripeGatewayAdapter(IAdquirentePagamento):
def autorizar(self, solicitacao: SolicitacaoCobranca) -> RespostaCobranca:
# Simula chamada à API REST do Stripe
print(f" 🌐 [Stripe REST API] Processando cobrança de R$ {solicitacao.valor:.2f}...")
return RespostaCobranca(
sucesso=True,
codigo_autorizacao="ch_stripe_9921_ok",
operadora="Stripe Global",
mensagem="Transação aprovada com sucesso."
)
def obter_nome_provedor(self) -> str:
return "Stripe v3"
class MercadoPagoAdapter(IAdquirentePagamento):
def autorizar(self, solicitacao: SolicitacaoCobranca) -> RespostaCobranca:
print(f" 🌐 [MercadoPago SDK] Autorizando débito de R$ {solicitacao.valor:.2f}...")
return RespostaCobranca(
sucesso=True,
codigo_autorizacao="mp_auth_883344",
operadora="MercadoPago Latam",
mensagem="Pagamento liquidado instantaneamente."
)
def obter_nome_provedor(self) -> str:
return "MercadoPago API"
class PixBancoCentralAdapter(IAdquirentePagamento):
def autorizar(self, solicitacao: SolicitacaoCobranca) -> RespostaCobranca:
print(f" ⚡ [SPI / BACEN] Gerando payload PIX e validando chave...")
return RespostaCobranca(
sucesso=True,
codigo_autorizacao="E0003816620260928_PIX",
operadora="Bacen SPI",
mensagem="Transferência PIX confirmada em 180ms."
)
def obter_nome_provedor(self) -> str:
return "PIX Instantâneo"
# 3. Núcleo de Negócio com Mecanismo de Failover (Blindagem Completa)
class MotorLiquidacaoVendas:
"""Consome a interface estável sem saber quais operadoras existem fisicamente."""
def __init__(self, adquirentes: List[IAdquirentePagamento]):
if not adquirentes:
raise ValueError("O motor de liquidação requer ao menos um adquirente configurado.")
self.adquirentes = adquirentes
def liquidar(self, solicitacao: SolicitacaoCobranca) -> RespostaCobranca:
print(f"\n[Motor de Liquidação] Iniciando cobrança do pedido #{solicitacao.id_pedido}")
# Tentativa sequencial com tolerância a falhas (Protected Variations)
for adquirente in self.adquirentes:
try:
resposta = adquirente.autorizar(solicitacao)
if resposta.sucesso:
print(f" ✅ Pagamento autorizado via [{adquirente.obter_nome_provedor()}]. Código: {resposta.codigo_autorizacao}")
return resposta
except Exception as erro:
print(f" ⚠️ Provedor [{adquirente.obter_nome_provedor()}] falhou: {erro}. Alternando para fallback...")
raise RuntimeError("Todas as operadoras de pagamento falharam. Operação abortada.")
# Demonstração Prática
if __name__ == "__main__":
cobranca = SolicitacaoCobranca("PED-2026-9901", "123.456.789-00", 750.00)
# Configuração de rota com fallback em tempo de execução
adquirentes_ativos = [
PixBancoCentralAdapter(),
StripeGatewayAdapter(),
MercadoPagoAdapter()
]
motor = MotorLiquidacaoVendas(adquirentes_ativos)
resultado = motor.liquidar(cobranca)
print(f"Status Final: {resultado.mensagem}")
2. Auditoria e Telemetria: Pure Fabrication & Indirection
Neste exemplo, aplicamos Pure Fabrication para conceber classes técnicas artificiais (sem lastro no mundo real dos negócios) e Indirection para interpor um despachante intermediário, isolando totalmente as entidades financeiras:
# grasp_pure_fab_indirection.py
from abc import ABC, abstractmethod
from typing import List, Dict, Any
from datetime import datetime
# Entidade Conceitual do Domínio (Mundo Real)
class TransferenciaPix:
def __init__(self, txid: str, pagador: str, recebedor: str, valor: float):
self.txid = txid
self.pagador = pagador
self.recebedor = recebedor
self.valor = valor
self.status = "PENDENTE"
def efetivar(self):
self.status = "CONCLUIDA"
# 1. Pure Fabrication: Interfaces e classes concebidas puramente para o design
class ICanalAuditoria(ABC):
@abstractmethod
def registrar_evento(self, evento: Dict[str, Any]):
pass
class LogArquivoAuditoria(ICanalAuditoria):
def registrar_evento(self, evento: Dict[str, Any]):
print(f" 📄 [File Sink] [AUDIT_SEC] {evento['tipo']} | TX: {evento['txid']} | TS: {evento['timestamp']}")
class TelemetriaCloudWatch(ICanalAuditoria):
def registrar_evento(self, evento: Dict[str, Any]):
print(f" ☁️ [CloudWatch Metrics] Métrica de negócio 'PIX_SETTLED' incrementada (+1). Valor: R$ {evento['valor']:.2f}")
# 2. Indirection: Mediador intermediário que evita acoplamento direto entre domínio e canais
class DespachanteAuditoriaIndireta:
"""Pure Fabrication + Indirection: Desacopla o domínio das ferramentas de monitoramento."""
def __init__(self):
self._canais: List[ICanalAuditoria] = []
def adicionar_canal(self, canal: ICanalAuditoria):
self._canais.append(canal)
def despachar(self, transferencia: TransferenciaPix, tipo_evento: str):
payload = {
"txid": transferencia.txid,
"pagador": transferencia.pagador,
"recebedor": transferencia.recebedor,
"valor": transferencia.valor,
"tipo": tipo_evento,
"timestamp": datetime.utcnow().isoformat() + "Z"
}
for canal in self._canais:
canal.registrar_evento(payload)
# 3. Serviço de Aplicação Orquestrador
class ServicoTransferenciaBancaria:
def __init__(self, auditoria_mediator: DespachanteAuditoriaIndireta):
self.auditoria = auditoria_mediator
def realizar_pix(self, txid: str, pagador: str, recebedor: str, valor: float) -> TransferenciaPix:
pix = TransferenciaPix(txid, pagador, recebedor, valor)
# Notificação mediada via Indireção
self.auditoria.despachar(pix, "PIX_INICIADO")
pix.efetivar()
self.auditoria.despachar(pix, "PIX_EFETIVADO")
return pix
# Execução Prática
if __name__ == "__main__":
print("\n" + "=" * 65)
print("🏭 DEMONSTRAÇÃO: PURE FABRICATION & INDIRECTION EM AUDITORIA")
print("=" * 65)
# Configuração dos intermediários
mediador_auditoria = DespachanteAuditoriaIndireta()
mediador_auditoria.adicionar_canal(LogArquivoAuditoria())
mediador_auditoria.adicionar_canal(TelemetriaCloudWatch())
servico = ServicoTransferenciaBancaria(mediador_auditoria)
pix_resultado = servico.realizar_pix("TX-88201-BACEN", "João Silva", "Empresa Alpha Ltda", 1850.00)
print(f"\nStatus Final da Transferência: {pix_resultado.status}")
Saída Esperada dos Scripts:
[Motor de Liquidação] Iniciando cobrança do pedido #PED-2026-9901
⚡ [SPI / BACEN] Gerando payload PIX e validando chave...
✅ Pagamento autorizado via [PIX Instantâneo]. Código: E0003816620260928_PIX
Status Final: Transferência PIX confirmada em 180ms.
=================================================================
🏭 DEMONSTRAÇÃO: PURE FABRICATION & INDIRECTION EM AUDITORIA
=================================================================
📄 [File Sink] [AUDIT_SEC] PIX_INICIADO | TX: TX-88201-BACEN | TS: 2026-09-28T14:40:00.000000Z
☁️ [CloudWatch Metrics] Métrica de negócio 'PIX_SETTLED' incrementada (+1). Valor: R$ 1850.00
📄 [File Sink] [AUDIT_SEC] PIX_EFETIVADO | TX: TX-88201-BACEN | TS: 2026-09-28T14:40:00.000000Z
☁️ [CloudWatch Metrics] Métrica de negócio 'PIX_SETTLED' incrementada (+1). Valor: R$ 1850.00
Status Final da Transferência: CONCLUIDA