Pular para o conteúdo

Code Smells e SOLID

Code smells são heurísticas — “isto cheira mal, investigue”. SOLID são princípios — “por que cheira mal”. Um é o radar, o outro é a explicação. Quando você aprende a traduzir smell → princípio, o refactoring deixa de ser mecânico e passa a ter direção: você sabe para onde mover o código, porque sabe qual princípio restaurar.

graph LR
    S["Code Smell<br/>(sintoma)"] --> P["Princípio SOLID violado<br/>(diagnóstico)"]
    P --> R["Técnica de Refactoring<br/>(tratamento)"]
    R --> C["Design saudável"]
Code smell Princípio violado Refactoring que cura
Large Class / God Class SRP Extract Class, Move Method
Divergent Change (muda por vários motivos) SRP Extract Class por eixo de mudança
Shotgun Surgery (uma mudança respinga em N lugares) OCP Move Method/Field, consolidar; introduzir abstração
Switch/instanceof sobre “tipo” repetido OCP Replace Conditional with Polymorphism
Refused Bequest (subclasse ignora/rejeita herança) LSP Replace Subclass/Superclass with Delegate (na 1ª ed., Replace Inheritance with Delegation)
UnsupportedOperationException em override LSP + ISP Segregar interface; compor em vez de herdar
Interface “gorda” que força métodos vazios ISP Quebrar em role interfaces menores
Feature Envy (método usa mais dados de outra classe) SRP (coesão) Move Method
new de infraestrutura dentro da regra DIP Introduzir porta + injeção de dependência
Primitive Obsession (String/int para CPF, dinheiro) Coesão de domínio (leva a espalhar regra) Replace Primitive with Object (→ Value Object)

O smell mais relevante para quem estuda DDD: entidades só com getters/setters e toda a regra num service gigante. É um combo de violações — SRP (o service acumula responsabilidades de várias entidades) e baixa coesão. O tratamento é mover comportamento de volta para as Entidades e Agregados, transformando o service anêmico num orquestrador fino. Isso também melhora a testabilidade (ver Testabilidade e Arquitetura): lógica na entidade se testa sem mocks.

O elo que falta: você não sai refatorando sobre código de produção sem rede. A sequência saudável é smell detectado → teste que fixa o comportamento atual → refactoring → teste verde. Por isso Fundamentos de Refactoring depende de testes, e o passo Refactor do TDD é o momento natural de pagar esses smells enquanto a suíte ainda está verde.

  • Caçar smell sem entender o princípio: renomear e extrair no automático pode mover o problema de lugar sem restaurar nenhum princípio. Diagnostique antes.
  • Refatorar sem teste: transforma “mudar estrutura preservando comportamento” em “torcer para não quebrar”. Ver Fundamentos de Refactoring.
  • Aplicar SOLID de forma dogmática: nem todo switch é violação de OCP; nem toda classe grande fere SRP. O smell precisa doer (mudança frequente, bug recorrente) para justificar o custo do refactoring.
  • Confundir Primitive Obsession com over-engineering: criar value object para tudo também é smell. Use onde há regra/invariante.
  1. Por que “Shotgun Surgery” é considerado uma violação de OCP?
Resposta

Porque uma única mudança de requisito obriga a editar muitos pontos espalhados — o oposto de “fechado para modificação”. A cura é consolidar a responsabilidade e introduzir uma abstração que absorva a variação, deixando o sistema aberto para extensão.

  1. Qual smell mapeia para “Replace Conditional with Polymorphism” e por quê?
Resposta

Switch/instanceof sobre um “tipo” repetido pela base. Ele viola OCP porque cada novo tipo exige editar todos os switches. Polimorfismo move cada ramo para uma subclasse/estratégia, tornando a extensão aditiva.

  1. Por que o modelo anêmico é um problema de coesão e de testabilidade ao mesmo tempo?
Resposta

A lógica que deveria estar na entidade migra para um service, que acumula responsabilidades (baixa coesão, fere SRP) e passa a exigir muitos mocks para ser testado. Mover o comportamento de volta à entidade resolve ambos.

  1. Encontrar um smell justifica refatorar imediatamente?
Resposta

Não. Smell é heurística. Só compensa refatorar quando ele dói de fato (mudança frequente, bugs) e há testes cobrindo. Caso contrário pode ser custo sem retorno.