Pular para conteúdo

Aula 19 - Anti-Patterns de Código e Refatoração Segura 🧼

Objetivo Pedagógico

Objetivo: Identificação sistemática de Code Smells e Anti-Patterns arquiteturais (God Class, Anemic Domain, Primitive Obsession) e aplicação do catálogo de refatorações de Martin Fowler com salvaguarda de testes.


📑 1. Fundamentos Teóricos & Análise Técnica

O conceito de Code Smell (Maus Cheiros no Código), cunhado por Kent Beck e popularizado por Martin Fowler, designa sintomas na estrutura do código que indicam problemas arquiteturais mais profundos, degradando a manutenibilidade e aumentando o custo de evolução do software.

Principais Anti-Patterns combatidos na engenharia corporativa: 1. Classe Deus (God Class / Blob): Classes gigantescas que centralizam regras de múltiplos domínios, acumulando milhares de linhas e violando o Princípio da Responsabilidade Única (SRP). 2. Obsessão por Tipos Primitivos (Primitive Obsession): Uso de strings ou números brutos para representar conceitos de domínio ricos (como CPF, CEP, E-mail, Moeda), espalhando validações duplicadas por todo o sistema. A solução é o padrão Value Object (Objeto de Valor). 3. Modelo de Domínio Anêmico (Anemic Domain Model): Entidades que possuem apenas getters e setters vazios, enquanto toda a lógica de negócio fica espalhada em classes de serviço procedurais.

A Refatoração Segura exige uma rede de salvaguarda de testes automatizados e a técnica do Mikado Method ou Strangler Fig Pattern para modificações graduais sem quebrar a produção.

📐 Arquitetura Conceitual & Diagrama de Fluxo

flowchart TD
    Smell["Code Smell: Primitive Obsession (string email, string cpf)"] --> Test["1. Escreve Testes Unitários de Salvaguarda"]
    Test --> Refactor["2. Refatora para Value Objects Imutáveis (EmailVO, CpfVO)"]
    Refactor --> GreenTest["3. Executa Suíte de Testes (Verde!)"]
    GreenTest --> CleanCode["Código Expressivo, Blindado contra Dados Inválidos"]
    style Smell fill:#ffebee,stroke:#c62828
    style Test fill:#e1f5fe,stroke:#01579b
    style Refactor fill:#fff3e0,stroke:#e65100
    style CleanCode fill:#e8f5e9,stroke:#2e7d32

🔍 Pilares e Diretrizes Técnicas

Nesta unidade, aprofundamos os seguintes conceitos fundamentais: - Padrão Value Object: Objetos sem identidade definidos por seus atributos e que validam sua própria integridade no construtor. - Refatoração sob Testes: Nunca refatorar código que não possua cobertura automatizada de testes prévia. - Padrão Strangler Fig: Substituição gradual de subsistemas legados por novos módulos desacoplados. - Lei de Demeter: Princípio do menor conhecimento: um objeto deve falar apenas com seus amigos próximos.


🛠️ 2. Implementação Prática em Qualidade de Código e Refatoração

Abaixo está a implementação técnica de referência, estruturada com padrões de engenharia de software e foco em robustez:

// value_object_refactoring.ts (Eliminando Primitive Obsession com Value Objects)
// Anti-Pattern: Uso de string bruta sem garantia de validação
// function registerUser(email: string) { ... }

// Refatoração com Value Object Autovalidado e Imutável
export class EmailAddress {
  private readonly value: string;

  constructor(candidate: string) {
    if (!candidate || !candidate.includes('@') || !candidate.includes('.')) {
      throw new Error(`E-mail inválido fornecido: ${candidate}`);
    }
    this.value = candidate.trim().toLowerCase();
  }

  getValue(): string {
    return this.value;
  }

  equals(other: EmailAddress): boolean {
    return this.value === other.getValue();
  }
}

// O tipo garante que nenhuma instância de EmailAddress com formato inválido exista no sistema!
const validEmail = new EmailAddress('contato@empresa.com');
console.log('E-mail seguro:', validEmail.getValue());

💡 Análise Passo a Passo do Código

  1. Autovalidação no Construtor: Torna impossível a existência de um objeto EmailAddress em estado inválido na memória.
  2. Normalização Imediata: Aplica .trim().toLowerCase() garantindo formato canônico único para o sistema.
  3. Igualdade Estrutural por Valor: Dois Value Objects são comparados por seu conteúdo (equals), não por sua referência de memória.

🎯 3. Próximos Passos & Sequência Didática