💡 Key Takeaways
- Rule I Follow #1: Functions Should Do One Thing (But That Thing Can Be Bigger Than You Think)
- Rule I Follow #2: Names Should Reveal Intent (Even If They're Long)
- Rule I Follow #3: Comments Explain Why, Not What (But Use More Than You Think)
- Rule I Follow #4: Fail Fast and Fail Loud
Eu tenho analisado o código de outras pessoas há 14 anos como arquiteto de software sênior em uma empresa fintech que processa US$ 2,3 bilhões em transações mensalmente. Na última terça-feira, revisei um pull request que me fez torcer fisicamente — 847 linhas em uma única função, nomes de variáveis como "data2" e "temp," e comentários que diziam literalmente "// mágica acontece aqui." O desenvolvedor que escreveu isso? Um graduado em CS de Stanford com GPA 3.9.
💡 Principais Conclusões
- Regra que Sigo #1: Funções Devem Fazer Uma Coisa (Mas Essa Coisa Pode Ser Maior Do Que Você Pensa)
- Regra que Sigo #2: Nomes Devem Revelar Intenção (Mesmo Que Sejam Longos)
- Regra que Sigo #3: Comentários Explicam o Porquê, Não o Que (Mas Use Mais Do Que Você Pensa)
- Regra que Sigo #4: Falhe Rápido e Falhe Alto
Foi quando percebi: temos ensinado código limpo da maneira errada.
Todo mundo cita "Código Limpo" do Tio Bob como se fosse uma escritura. Eles memorizam os princípios SOLID, discutem sobre tabulações versus espaços e escrevem funções tão pequenas que precisam de um microscópio para lê-las. Mas aqui está o que ninguém te conta: algumas dessas regras estão ativamente piorando seu código.
Não estou aqui para criticar o trabalho de Robert Martin — é fundamental e importante. Mas depois de revisar mais de 3.000 pull requests, mentorando 47 desenvolvedores e mantendo uma base de código que está em produção desde 2011, aprendi quais regras realmente importam e quais são apenas um teatro de desenvolvedor. Deixe-me mostrar o que quero dizer.
Regra que Sigo #1: Funções Devem Fazer Uma Coisa (Mas Essa Coisa Pode Ser Maior Do Que Você Pensa)
O "princípio da responsabilidade única" para funções é provavelmente a regra mais mal interpretada em código limpo. Vejo desenvolvedores criando funções que têm três linhas, com nomes como "validateUserEmailFormat" que são chamadas por "validateUserEmail" que é chamada por "validateUser." É tartarugas a todo o caminho, e você precisa abrir sete arquivos apenas para entender o que está acontecendo quando um usuário se inscreve.
Aqui está o que eu realmente faço: escrevo funções que realizam uma operação de negócio significativa, não uma operação técnica. Quando escrevo uma função chamada "processPayment," ela pode ter 45 linhas. Ela valida o método de pagamento, verifica se há fraude, cria um registro de transação e envia um e-mail de confirmação. São quatro operações técnicas, mas é uma operação de negócio: processar um pagamento.
A chave é que cada um desses passos está claramente delineado no código. Uso linhas em branco para separar seções lógicas, e adiciono breves comentários que explicam o "porquê" de cada seção. Quando outro desenvolvedor lê "processPayment," ele pode entender todo o fluxo de pagamento sem pular entre doze arquivos diferentes.
Eu medi isso uma vez. Em nossa antiga base de código, onde seguimos religiosamente a regra "as funções devem ser pequenas", o desenvolvedor médio precisava abrir 8,3 arquivos para entender um único fluxo de usuário. Depois que refatorei para usar funções de "operação significativa", esse número caiu para 2,1 arquivos. O tempo de revisão de código diminuiu em 34%. O tempo de correção de bugs caiu em 28%.
A regra não é "faça funções pequenas." A regra é "faça funções compreensíveis." Às vezes isso significa 10 linhas. Às vezes significa 50. O que nunca significa é forçar os desenvolvedores a serem detetives em toda a sua base de código apenas para descobrir como um clique de botão funciona.
Regra que Sigo #2: Nomes Devem Revelar Intenção (Mesmo Que Sejam Longos)
Uma vez trabalhei com um desenvolvedor que insistia que os nomes de variáveis nunca deveriam exceder 15 caracteres porque "isso torna o código mais difícil de ler." Ele escrevia código assim: "const usrPmtMthd = getUserPaymentMethod();" Eu quis jogar meu teclado pela janela.
"O melhor código não é o mais inteligente - é o código que o próximo desenvolvedor pode entender às 2 da manhã quando o sistema está fora do ar e os clientes estão ligando."
Aqui está minha regra: se eu não consigo entender o que uma variável contém lendo seu nome uma vez, o nome está errado. Eu não me importo se tem 40 caracteres de comprimento. Prefiro ler "userSelectedPaymentMethodFromDropdown" do que passar três minutos descobrindo o que "pmtMthd" significa.
Em nosso sistema de processamento de pagamentos, temos uma variável chamada "transactionRequiresAdditionalFraudVerificationBasedOnUserHistory." Tem 71 caracteres. Também é cristalina. Quando você vê essa variável em uma declaração if, sabe exatamente o que está sendo verificado e por quê. Nenhum comentário necessário. Nenhuma tradução mental exigida.
O contra-argumento que sempre ouço é "mas nomes longos fazem as linhas muito longas!" Claro, se você ainda estiver fingindo que estamos escrevendo código em terminais de 80 colunas de 1985. Temos monitores de 27 polegadas agora. Use-os. Eu defini meu limite de comprimento de linha em 120 caracteres e nunca tive problemas com legibilidade.
Aqui está o teste que uso: se um desenvolvedor júnior pode ler o nome da sua variável e imediatamente saber o que contém, que tipo é e aproximadamente para que é usado, você deu o nome correto. Se eles precisam rolar para cima para ver onde foi declarada ou verificar a definição de tipo, você falhou.
Eu vi isso melhorar dramaticamente a qualidade da revisão de código. Quando os nomes são claros, os revisores gastam menos tempo perguntando "o que isso faz?" e mais tempo perguntando "essa é a abordagem certa?" É aí que está o verdadeiro valor.
Regra que Sigo #3: Comentários Explicam o Porquê, Não o Que (Mas Use Mais Do Que Você Pensa)
Os puristas do código limpo dirão que "um bom código não precisa de comentários." Eles estão metade certos. Um bom código não precisa de comentários que explicam o que o código faz. Mas absolutamente precisa de comentários que explicam por que o código existe.
| Regra de Código Limpo | O Que os Livros Dizem | O Que Realmente Funciona | Quando Quebrá-la |
|---|---|---|---|
| Comprimento da Função | Mantenha as funções com menos de 20 linhas | Mantenha as funções abaixo de uma tela (40-60 linhas) | Quando dividir cria mais confusão do que clareza |
| Comentários | O código deve ser auto-documentado | Explique por que, não o que | Algoritmos complexos, regras de negócio ou decisões não óbvias |
| Princípio DRY | Nunca se repita | Não se repita ainda (aguarde a terceira ocorrência) | Quando abstração acopla recursos não relacionados |
| Nomes de Variáveis | Use sempre nomes descritivos | O contexto importa: 'i' é aceitável em loops, 'userAuthenticationToken' em escopos pequenos é exagero | Contadores de loop, abreviações conhecidas no contexto do domínio |
No mês passado, encontrei uma função em nossa base de código que tinha uma solução bizarra: estava adicionando um atraso de 50 milissegundos antes de processar um webhook. Nenhum comentário. Nenhuma explicação. Apenas "await sleep(50);" lá, como uma mina terrestre. Passei duas horas tentando descobrir se era um bug ou intencional. Acontece que era uma solução para uma condição de corrida em uma API de terceiros que descobrimos após três dias de depuração em produção.
Agora esse código tem um comentário: "// atraso de 50 ms necessário: o webhook da Stripe pode chegar antes que sua API reflita o status da cobrança. Descoberto durante o incidente #2847 em 2023-08-15. Remova isso após a Stripe corrigir seu problema de consistência eventual (ticket #45892)."
🛠 Explore Nossos Ferramentas
Esse é um bom comentário. Ele explica por que o código existe, faz referência ao incidente que o causou e até fornece um caminho para removê-lo no futuro. Sem esse comentário, o próximo desenvolvedor teria deletado pensando que era um erro.
Eu adiciono comentários generosamente em três situações: quando estou contornando um bug em uma dependência, quando estou implementando uma regra de negócio não óbvia e quando estou otimizando para desempenho de uma forma que torna o código menos legível. Em cada caso, o comentário explica o contexto que não está visível no próprio código.