Todos os artigos
46 artigos · atualizado semanalmente Veja nossas Ferramentas
Todos os artigos
Dicas

Clean Code sem dogmas: o que realmente importa

Clean Code virou religião — e tem fiéis que aplicam os mandamentos sem entender a teologia. O que realmente reduz bugs e custo de manutenção.

COVER · Dicas

Você está numa code review e alguém rejeita o seu PR porque uma função tem mais de vinte linhas. Não porque ela é complexa demais, não porque ela é difícil de testar — só porque tem mais de vinte linhas. A regra foi decorada, o contexto foi ignorado, e agora você vai passar a tarde quebrando uma função perfeitamente legível em três pedaços sem coesão alguma.

Clean Code virou religião. E como toda religião, tem fiéis que aplicam os mandamentos sem entender a teologia.


Por que "Clean Code" ficou dogmático

O livro do Robert Martin é de 2008. Bom livro — tem insights reais sobre nomeação, separação de responsabilidades, estrutura de testes. O problema não é o livro. O problema é que as regras foram descoladas do contexto e vieram parar em PRs, linters e code standards como verdades absolutas.

"Funções devem fazer uma coisa só." Verdade — mas o que é "uma coisa"? Depende do nível de abstração em que você está operando. Uma função processar_pagamento que valida o cartão, debita e envia o e-mail de confirmação pode estar fazendo "uma coisa" — processar um pagamento — dependendo de onde está no sistema.

"Funções devem ter no máximo X linhas." Número arbitrário. Uma função de cinquenta linhas que é uma série de validações sequenciais bem nomeadas é mais legível do que cinco funções de dez linhas que você precisa pular entre si para entender o fluxo.

"Sem comentários — o código deve se autodocumentar." Essa é a mais perigosa. Código autodocumentado é uma meta real, mas há classes de conhecimento que código simplesmente não consegue expressar: decisões de negócio, trade-offs deliberados, contexto regulatório. "Usamos MD5 aqui porque o sistema legado da operadora ainda não suporta SHA-256" é um comentário que salva horas de debug. Apagar isso em nome de código limpo é sabotagem.

O que realmente reduz bugs e manutenção

Quando você olha para o que causa problemas em produção e em manutenção de código ao longo do tempo, os padrões que aparecem consistentemente são outros.

Nomes que mentem. Uma variável chamada data que guarda um objeto de usuário, uma função chamada get_user que também persiste no banco — esses são problemas reais. Nomeação honesta é o princípio de clean code com melhor ROI. Não é sobre nomes longos ou curtos, é sobre nomes que correspondem ao que a coisa faz.

Estado compartilhado sem disciplina. Mais do que tamanho de função, estado mutável espalhado pelo sistema é o que torna código impossível de raciocinar. Uma função pequena que modifica estado global é infinitamente mais perigosa do que uma função grande que opera em dados locais.

Acoplamento implícito. Quando duas partes do sistema dependem uma da outra sem que isso esteja explícito — via constantes mágicas, via convenções que só vivem na cabeça do autor original, via side effects escondidos. Esse tipo de acoplamento é o que faz uma mudança simples explodir em três lugares inesperados.

Ausência de invariantes. Código que permite estados impossíveis — um Order que pode existir sem items, um User com email nulo depois que o sistema ficou ativo há meses. Usar o type system para tornar estados inválidos irrepresentáveis é um dos investimentos mais baratos e mais ignorados em qualidade de código.

As regras que vale seguir de verdade

Não é que todas as diretrizes de clean code são inúteis. Algumas têm fundamentação real e se sustentam mesmo fora do contexto original.

SRP aplicado ao nível correto. Single Responsibility Principle vale — mas no nível de módulo e classe, não necessariamente no nível de função de vinte linhas. Uma classe de serviço que cuida de pagamentos não deveria também enviar e-mails de marketing. Isso é violação real de responsabilidade única, com consequências reais de acoplamento.

Inversão de dependência. Código que depende de abstrações em vez de implementações concretas é genuinamente mais testável e mais flexível. Não porque é bonito — porque você consegue trocar o PostgreSQL por SQLite nos testes sem tocar em lógica de negócio.

Testes como especificação. Não a regra de cobertura de 80%, mas o princípio de que testes bem escritos documentam comportamento esperado. Um teste com um bom nome é documentação executável. Isso tem valor real independente de métrica de coverage.

Revisão pelo custo de leitura, não pela aparência. A pergunta certa não é "esse código parece limpo?" mas "quanto tempo leva para alguém novo entender o que isso faz e por quê?" Essa pergunta tem resposta empírica — você pode medir.

Quando a regra atrapalha mais do que ajuda

Há contextos específicos onde aplicar clean code mecanicamente produz resultado pior.

Código de performance crítica. Às vezes a versão legível é mais lenta por uma ordem de magnitude. Um loop manual com acesso direto a buffer é mais difícil de ler e dezessete vezes mais rápido. Se esse código roda dez milhões de vezes por segundo, a versão legível não é uma opção. Documente o porquê, não refatore para "parecer limpo".

Glue code e scripts de migração. Código que vai rodar uma vez e ser deletado não precisa das mesmas garantias de código que vai ser mantido por anos. Gastar duas horas extraindo helpers em um script de migração que vai ser executado amanhã e descartado é desperdício real.

Protótipos e experimentos. Se você está validando uma hipótese de produto, o código que importa é o que permite iterar rápido, não o que está pronto para produção. O erro é manter esse padrão depois que o experimento vira feature — aí sim vale o investimento.

O que fazer com code reviews dogmáticas

Se você está num time onde as regras são aplicadas mecanicamente, o problema não é técnico — é de comunicação sobre o propósito das regras.

A pergunta que desbloqueou code reviews para mim: "qual problema concreto essa mudança resolve?" Se alguém quer quebrar uma função de trinta linhas, a resposta não pode ser "porque funções devem ter no máximo vinte linhas". A resposta precisa ser "porque esse bloco aqui tem uma responsabilidade separada que vai precisar ser reutilizada" ou "porque esse bloco não pode ser testado de forma isolada do jeito que está".

Se não tem resposta concreta, a regra está sendo aplicada por inércia, não por julgamento.

Num contexto onde você quer um diff limpo antes de submeter o PR — sem comentários de debug esquecidos, sem código morto, sem variáveis mal nomeadas — uso o Comparador de Texto para passar os olhos nas mudanças antes de abrir. Não substitui o julgamento, mas ajuda a ver o que está sendo entregue com mais distância.


Perguntas frequentes

Clean Code ainda vale a pena ler em 2025?

Vale, com contexto. Leia como um livro de princípios com exemplos datados, não como manual de regras. Os capítulos sobre nomeação e testes continuam relevantes. Os exemplos de Java de 2008 e as regras numéricas (X linhas por função) podem ser ignorados sem prejuízo.

SOLID é a mesma coisa que clean code?

SOLID é um conjunto separado de princípios de design orientado a objetos, embora o livro do Uncle Bob trate de ambos. SRP e DIP têm aplicação prática clara. OCP (Open/Closed) e LSP (Liskov) dependem muito de contexto — aplicados mecanicamente em linguagens com duck typing ou em sistemas funcionais, produzem mais burocracia do que benefício.

Como convencer o time a parar de aplicar regras mecanicamente?

Não tente convencer com opinião — mostre com exemplo. Na próxima code review onde uma regra for aplicada sem justificativa concreta, pergunte: "qual problema isso resolve na prática?" A maioria das pessoas não defende regras quando não consegue articular o problema que a regra resolve.

Tem algum linter que aplica essas ideias de forma não-dogmática?

Linters são inerentemente baseados em regras fixas, então têm um teto. O que dá para fazer é configurá-los para o que tem ROI real: nomeação inconsistente, complexidade ciclomática muito alta (não um número mágico, mas um threshold que o time calibrou), dependências circulares. E desabilitar as regras que geram falsos positivos mais do que problemas reais.


Código limpo é legibilidade sob custo de manutenção real

A pergunta que importa não é "esse código segue as regras?" É: "o próximo dev que tocar nisso vai entender o que está acontecendo, por que as decisões foram tomadas, e consegue modificar sem introduzir bugs?"

Se a resposta for sim, o código é suficientemente limpo — independente do número de linhas por função ou da quantidade de comentários. Se a resposta for não, nenhum linter ou metodologia resolve: você precisa de julgamento, não de mais uma regra para decorar.

RD
Autor
Rafael Duarte
Desenvolvedor backend com passagem por fintech e SaaS B2B — trabalhou em times que escalaram APIs de zero a milhões de requisições. Carrega cicatrizes de produção suficientes para ter opiniões fortes sobre ferramentas, padrões e decisões de arquitetura. Não é acadêmico: leu a RFC do UUID quando precisou escolher entre v4 e v7 para uma tabela de alta escrita.
Ver perfil