Onboarding clean code dogmático: o custo que o PR não pega

TL;DR

O preço do Clean Code dogmático não aparece no PR. Aparece no dia em que o engenheiro novo abre a base pela primeira vez. TTFC elevado, dev produtivo só após 90+ dias, ninguém mediu porque ninguém acompanhou. Três indicadores operacionais mostram onde o dogma está corroendo a base. O trade-off entre função curta e função coesa é local, não absoluto — exige critério de saída, não regra de polegar.

  • O onboarding clean code dogmático troca legibilidade imediata por legibilidade mediada — quem chega depois paga a conta de quem não estava lá.
  • PR review mede o que o dev atual produziu; onboarding mede o que o próximo dev vai enfrentar. As duas métricas divergem em bases com refatoração excessiva.
  • TTFC, arquivos por feature e taxa de perguntas por dev novo nos primeiros 30 dias são os três indicadores que pegam o custo que o PR não pega.
  • Função curta tem valor em casos específicos — cálculo determinístico, mapeamento, utilidade pura — e atrapalha em outros — regra de negócio ramificada, validação com efeito colateral, integração. O trade-off é local, não global.
  • O critério de saída para refatoração exige três condições simultâneas: trecho tocado 3+ vezes em 6 meses, bug recorrente no mesmo bloco, redução de arquivos a abrir — não é “passou de 20 linhas, quebre”.

~ 14 min de leitura · 2345 palavras

O sintoma do onboarding clean code dogmático que só aparece no terceiro mês

A base foi refatorada em 14 funções dentro de 3 arquivos. O PR review aprovou. O linter ficou verde. A complexidade ciclomática por função caiu de 18 para 4. Métricas de qualidade de código melhoraram. O engenheiro sênior fechou o ticket feliz. O engenheiro contratado na semana seguinte abriu o repositório e não fez o primeiro PR de feature não-trivial em três meses.

Esse é o caso sintético mais comum observado em empresas brasileiras de médio porte com base Java entre 100k e 300k linhas. A base não é ruim. Os testes passam. O coverage está acima de 70%. O sonarQube não aponta nada grave. O sintoma é silencioso: o dev novo não reclama de qualidade do código — reclama de não entender por onde começar. Pede ajuda no canal. Abre o mesmo arquivo quatro vezes para responder a uma pergunta. Leva 90 dias para fazer o primeiro commit de feature que não seja trivial. Sai aos 12 meses achando que a base é boa e o time é lento.

O sintoma não aparece no PR porque o PR mede deltas isolados. O engenheiro sênior que revisou o último refactor olhou 14 funções e aprovou cada uma. Olhou a complexidade ciclomática, olhou o coverage, olhou a cobertura por branch. Não abriu a base inteira, não simulou o caminho de quem chega depois. A métrica que o PR captura é local. A dor que aparece três meses depois é global.

Três sinais típicos de base com esse problema, no relatório do primeiro mês do dev novo:

  • A mediana de arquivos abertos por sessão de code review fica acima de 12, e o tempo de review individual passa de 40 minutos por PR.
  • A taxa de perguntas no canal do time, no primeiro mês, ultrapassa 40 perguntas — e a maioria é do tipo “onde mora X” ou “por que X faz Y”.
  • O dev novo pede para sentar ao lado de outro dev para entender um fluxo que não está documentado em lugar nenhum — sintoma claro de código que precisa de guia humano.

Por que o PR não pega

As três métricas de PR mais usadas em revisão — tamanho, complexidade ciclomática, cobertura de testes — avaliam a unidade que o dev submeteu. Avaliam o trecho, não o sistema. Avaliam o agora, não o próximo. A diferença é estrutural: o que o revisor vê é uma janela isolada; o que o dev novo vai enfrentar é o caminho inteiro.

O resultado é uma divergência mensurável entre dois tipos de qualidade. Bases com PR review rigoroso em complexidade ciclomática podem ter TTFC (time to first commit — tempo até o dev novo abrir seu primeiro PR de feature não-trivial) de 60 a 120 dias. Bases com PR review mais frouxo em complexidade, mas com função coesa e caminho de leitura explícito, costumam ter TTFC de 14 a 30 dias. A primeira métrica aparece no sonarQube e no relatório semanal. A segunda só aparece quando alguém novo entra, sai, ou pede ajuda no canal. Por isso a segunda é raramente medida.

PR review otimiza para o dev atual. Onboarding otimiza para o próximo. Os dois critérios não convergem automaticamente — em bases refatoradas dogmaticamente, divergem. A refatoração que melhora a métrica local pode simultaneamente piorar a métrica global. O linter não pega porque a métrica local ficou verde. O code review não pega porque a janela de revisão é pequena. A única métrica que pega é a que ninguém instrumentou.

Quatro consequências operacionais dessa divergência:

  • O time gasta ciclos de pair programming para explicar a base a cada contratação, em vez de gastar para entregar feature.
  • O roadmap atrasa nos dois primeiros trimestres do ano, justamente quando a contratação aconteceu — e a causalidade raramente é atribuída ao dogma.
  • A retenção do dev novo cai porque a frustração de não conseguir entregar é cumulativa.
  • O custo real do dogma é invisível no budget — aparece em salaries, em atrasos, em rescisões, mas a planilha não conecta as linhas.

Os três indicadores operacionais

Bases que cobram onboarding alto têm três sinais mensuráveis antes de o dev sair. Os três são operacionais, dependem apenas de log de PR, controle de versão e registro de perguntas — não exigem pesquisa qualitativa, não exigem entrevista, não exigem ferramenta de analytics.

  • TTFC — Time to First Commit. Tempo, em dias corridos, entre a data de contratação do dev e a data do merge do primeiro PR de feature não-trivial (não bug trivial, não ajuste de typo, não mudança de config). Acima de 60 dias em base Java de médio porte é sinal amarelo. Acima de 90 dias é sinal vermelho. Acima de 120 dias com engenheiro de perfil sênior é falha estrutural da base, não do dev. O indicador captura o custo composto: ramp-up técnico, ramp-up de domínio, navegação de código fragmentado.
  • Arquivos por feature. Mediana do número de arquivos únicos abertos em PRs de feature (não bugfix, não chore) nos últimos 90 dias. Em base com função coesa, a mediana costuma ficar entre 4 e 8. Em base com Clean Code dogmático, a mediana sobe para 12-25. Cada arquivo adicional é um ponto de navegação que o dev novo tem que aprender. Acima de 15 em base Java, a fragmentação está corroendo o tempo de entrega de feature mesmo para o time experiente.
  • Taxa de perguntas por dev novo nos primeiros 30 dias. Contagem de perguntas feitas pelo dev recém-chegado no canal de comunicação do time (Slack, Teams, Discord — qualquer canal único do time, sem exceções) durante os primeiros 30 dias corridos. Categorizar em quatro tipos: (a) onde mora X, (b) por que X faz Y, (c) como rodar Z, (d) quem decide W. Tipo (a) e (b) dominam em bases com fragmentação excessiva. Tipo (c) e (d) são ruído operacional tolerável. Acima de 40 perguntas no primeiro mês em time de até 8 pessoas é sinal de base que cobra onboarding pesado.

Os três indicadores são complementares, não redundantes. TTFC mede o resultado final. Arquivos por feature mede a estrutura subjacente. Taxa de perguntas mede o atrito do caminho. Quando os três estão altos simultaneamente, o dogma está corroendo a base de forma mensurável e o problema não é mais “percepção do dev novo” — é custo operacional recorrente que o time paga a cada contratação.

A medição exige instrumentação mínima — três queries em três fontes distintas:

  • git log --author="" --since="" filtrando merge commit de feature, para TTFC.
  • git log --since="90 days ago" --merges --pretty=format: parseando lista de arquivos modificados, para mediana de arquivos por feature.
  • Export do canal de comunicação (Slack export, Teams transcript) com filtro por usuário e janela de 30 dias, para a taxa de perguntas.

Tabela comparativa de três perfis de base

A comparação entre os três perfis é ordem de grandeza, não benchmark controlado. Estimativas baseadas em observação de mercado de empresas brasileiras de médio porte entre 2023 e 2026, em base Java com 100k-300k linhas, com time de 5 a 12 pessoas. Variação entre empresas é alta; a ordem de grandeza é estável.

Perfil de base TTFC mediano (dias) Arquivos por feature (mediana) Perguntas/dev novo/mês Custo anual por contratação
Função coesa (60-120 linhas, baixa fragmentação) 14-30 4-8 10-20 baixo
Clean Code dogmático (8-15 linhas, abstração preventiva) 60-120 12-25 30-50 alto
Legado bem isolado (código antigo encapsulado, novo segue padrão) 21-45 6-12 15-25 médio

A leitura direta da tabela é contraintuitiva para quem defende Clean Code dogmático: a base com legado isolado fica entre os dois extremos. Tem código ruim (o legado), mas tem código novo navegável. O dev novo evita o legado por semanas, foca na parte coesa, faz PR, depois vai integrando o legado aos poucos com cobertura de teste e refatoração dirigida. O onboarding é incremental, não big-bang.

A base com Clean Code dogmático não tem onde pisar com cuidado. Todo lugar parece tão limpo que o dev novo assume que deve estar entendendo errado. Quando percebe que não está, o dano de tempo já foi feito. Atrapalha mais que o legado — porque o legado tem cara de legado, e o dev entra com expectativa baixa. O dogma entra com cara de qualidade, e o dev entra achando que o problema é ele.

O trade-off honesto

Função curta tem valor em casos específicos. Onde o domínio é determinístico — cálculo de imposto, mapeamento de entrada-saída, utilidade pura de transformação de dados — a função curta vence. O domínio cabe em uma tela, a lógica é linear, o teste cobre 100% do branch. A função curta ali é economia cognitiva. O dev novo abre, lê 8 linhas, entende, fecha, segue.

A função curta atrapalha em casos opostos. Onde a regra de negócio é ramificada — validação com efeito colateral, integração com sistema externo, regra de cálculo que muda por tipo de cliente, regra fiscal que depende de combinação de parâmetros — a função curta multiplica o custo de leitura. O dev abre uma função, pula para a próxima, para a próxima, para a próxima, monta o fluxo mental em rascunho. A função curta ali é overhead que ninguém pediu. O Clean Code foi escrito para reduzir custo cognitivo. Aqui aumenta.

A heurística simples de “função maior que 20 linhas, quebre” não distingue os dois casos. É a mesma regra aplicada em domínios opostos. O trade-off exige leitura do código, identificação do tipo de domínio, decisão local. Não escala como regra geral — escala como critério aplicado caso a caso. Quem aplica a regra de 20 linhas globalmente está transferindo custo do presente (code review mais simples) para o futuro (caminho de leitura mais longo, que pagam os próximos).

A regra de polegar sobre “uma responsabilidade por classe” cai na mesma armadilha. Uma classe de validação fiscal pode ter três responsabilidades conexas (validar, calcular efeito, registrar log) que são parte do mesmo fluxo de domínio. Separar em três classes introduziu um caminho de leitura que não precisava existir. O SRP foi pensado para casos em que as responsabilidades realmente divergem — não para multiplicar classes como fim em si.

Resumo do trade-off por tipo de domínio:

  • Cálculo determinístico (cálculo de imposto, conversão de unidades, hash utilitário) — função curta vence. Sem efeito colateral, sem dependência de contexto, leitura linear basta.
  • Mapeamento entrada-saída (DTO mapper, serialização pura, transformação entre formatos) — função curta vence. O domínio cabe em uma tela e o teste é unitário puro.
  • Validação com efeito colateral (regra fiscal que dispara log + notificação + cache invalidation) — função coesa vence. O efeito colateral coordenado precisa estar visível junto.
  • Integração com sistema externo (gateway de pagamento, API reguladora, SEFAZ) — função coesa vence. O fluxo de retry, fallback e auditoria precisa estar visível junto.
  • Regra de negócio ramificada (cálculo de preço com tipo de cliente + região + cupom + promoção) — função coesa vence. A ramificação precisa estar visível, não distribuída.

Critério de saída para refatoração

Três condições simultâneas, não uma heurística. A refatoração só vale a pena quando as três estão presentes.

  • O mesmo trecho foi tocado 3+ vezes em 6 meses. Medir via git log --format=oneline --since="6 months ago" -- caminho/arquivo.java e contar commits que tocam o arquivo. Se o arquivo foi tocado 3 ou mais vezes em janela de 6 meses por motivos não triviais (não rename, não import, não format), o trecho tem atrito real — vale refatorar. Se foi tocado 1 vez, mesmo que a função tenha 200 linhas, o atrito ainda não se materializou. Refatorar preventivamente aqui é dogma.
  • O bug recorrente vive no mesmo bloco. Achar pelo menos 1 bug que voltou para o mesmo trecho após fix anterior, ou 2 bugs distintos no mesmo bloco em 6 meses. Esse é o sinal de que o domínio está subrepresentado pela estrutura atual — o código não está dizendo o que faz. Aqui a refatoração tem alvo concreto: tornar o domínio explícito.
  • A refatoração proposta reduz arquivos a abrir, não aumenta. O efeito de uma boa refatoração é oposto ao dogma. Em vez de fragmentar 1 arquivo em 4, ela consolida 3 arquivos em 1 quando eles carregam o mesmo fluxo. A contagem final de arquivos deve cair ou ficar igual. Se a refatoração proposta aumentar o número de arquivos ou funções, a refatoração provavelmente está aplicando Clean Code onde não cabe.

As três condições juntas definem o que vale refatorar. Qualquer condição ausente é sinal de que a refatoração é cosmética ou dogmática. O critério é operacional, não ideológico — pode ser revisado em PR review por outro engenheiro sem precisar defender tese sobre Uncle Bob.

# Comando para a condição 1 — trecho tocado 3+ vezes em 6 meses
git log --format=oneline --since="6 months ago" -- caminho/arquivo.java \
  | wc -l
# Saída esperada: número >= 3

Conclusão como critério de decisão

A pergunta que decide se uma refatoração proposta deve ser aprovada não é “o código está limpo”. É: se um engenheiro pleno for contratado amanhã, ele faz o primeiro PR de feature não-trivial em quanto tempo — com a refatoração ou sem ela? Se a refatoração aumenta o TTFC, ela não é refatoração — é custo transferido para quem não estava na sala quando foi feita. Se a refatoração reduz o TTFC, é refatoração de verdade.

O critério de decisão é local, numérico, auditável em PR review. Não exige concordância com framework. Não exige defesa de tese. Exige resposta a uma pergunta operacional. A base que tem engenheiro entrando todo trimestre vai cobrar a conta do onboarding clean code dogmático todo trimestre — em produtividade, em retenção, em ramp-up que ninguém colocou no roadmap.

Leitura relacionada

Posts Similares

2 Comentários

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *