O Melhor Desenvolvedor Não Escreve Mais Código: Ele Reduz Incerteza
Hatched by Felipe Soares Barbosa Silveira (Felipebros)
Aug 15, 2026
11 min read
1 views
86%
A pergunta mais importante sobre um desenvolvedor talvez não seja “quanto código ele consegue escrever?”, mas esta: quantas mudanças ele consegue introduzir sem perder a capacidade de entender o sistema?
Em projetos reais, quase todo problema técnico nasce de uma combinação perigosa: trabalho demais em andamento, hipóteses não verificadas e mudanças cujo efeito ninguém consegue explicar com precisão. Um bug aparece, uma correção é feita às pressas, uma implantação altera o comportamento em produção e, logo depois, a equipe começa a operar no escuro. O código continua se movendo, mas o entendimento do sistema diminui.
Essa é a conexão pouco óbvia entre práticas de desenvolvimento, correção de bugs, operações, aprendizagem contínua e até a construção de consultas ao banco de dados: programar bem é controlar a distância entre intenção e efeito.
Uma consulta bem construída reduz a ambiguidade entre “quero estes dados” e “o banco retornará isto”. Um fluxo de trabalho bem administrado reduz a ambiguidade entre “estamos avançando” e “estamos apenas acumulando tarefas”. Um processo de debugging rigoroso reduz a distância entre “algo está errado” e “sabemos por que está errado”. Em todos esses casos, a excelência depende menos de velocidade bruta e mais de feedback confiável.
O inimigo invisível: trabalho que ainda não terminou
Imagine uma equipe com quinze tarefas abertas. Algumas estão codificadas, mas não testadas. Outras foram revisadas, mas ainda não implantadas. Uma terceira categoria está “praticamente pronta”, embora dependa de uma decisão de produto. Cada item parece pequeno isoladamente. O conjunto, porém, produz uma espécie de neblina operacional.
Esse é o problema do trabalho em andamento. Uma tarefa aberta não é necessariamente progresso. Ela representa uma promessa, uma hipótese ou uma fonte adicional de complexidade. Quanto mais promessas simultâneas, maior a quantidade de contexto que o desenvolvedor precisa manter na cabeça e maior a probabilidade de que uma mudança interfira em outra.
O custo não aparece apenas em horas de programação. Ele surge como troca de contexto, espera, retrabalho, conflitos de merge, testes incompletos e decisões esquecidas. Uma tarefa interrompida não fica congelada no ponto em que foi abandonada. Ela continua ocupando memória mental e continua criando incerteza para quem depende dela.
Há uma analogia útil com consultas a banco de dados. Pedir todos os registros, todas as colunas e todos os relacionamentos parece conveniente no início. Mas uma consulta ampla demais transfere o custo para a aplicação, para a rede, para o banco e, finalmente, para quem precisa interpretar o resultado. O sistema fica mais difícil de compreender porque trouxe informação demais, não porque trouxe informação de menos.
O mesmo ocorre com o trabalho. Limitar o que está em andamento é uma forma de selecionar informação relevante. Em vez de perguntar “o que mais podemos começar?”, a equipe pergunta “o que precisa ser concluído para que possamos aprender alguma coisa?”.
Na prática, isso significa estabelecer limites explícitos. Um quadro pode ter, por exemplo, no máximo duas tarefas em desenvolvimento e duas aguardando revisão. Quando o limite é atingido, ninguém inicia outra atividade sem terminar ou cancelar uma das atuais. Essa regra parece restritiva, mas cria uma pressão saudável: o sistema recompensa conclusão, não acumulação.
A métrica muda. Em vez de celebrar o número de itens iniciados, observa-se o tempo que uma tarefa leva para atravessar o sistema. Uma equipe que inicia vinte mudanças e conclui três não está necessariamente mais produtiva que uma equipe que inicia cinco e conclui quatro. A segunda talvez esteja aprendendo mais rápido, entregando com menos risco e acumulando menos dívida cognitiva.
A produtividade de uma equipe não é a quantidade de trabalho que ela consegue carregar, mas a quantidade de incerteza que consegue remover.
Debugging não é caça ao culpado, é redução de hipóteses
Quando surge um bug, a reação mais comum é procurar imediatamente um ponto para alterar. Alguém encontra uma linha suspeita, aplica uma condição, adiciona um if e executa novamente. Se o erro desaparece, a equipe sente alívio. Mas desaparecer não é o mesmo que ser compreendido.
Uma correção sem diagnóstico pode ser comparada a modificar uma consulta até que ela retorne o resultado esperado para um caso específico, sem descobrir por que os outros casos falhavam. Talvez o filtro tenha sido ajustado corretamente. Talvez apenas tenha escondido registros relevantes. Talvez o problema esteja nos dados, no relacionamento entre tabelas ou na interpretação do resultado.
O debugging confiável começa com a transformação de uma suspeita em uma hipótese testável. “O sistema está lento” é uma observação vaga. “A busca de pedidos demora quando o usuário não fornece um intervalo de datas porque a consulta examina registros demais” é uma hipótese. A segunda pode ser testada, refutada e refinada.
Um processo disciplinado pode seguir cinco movimentos:
- Descrever o comportamento observado, sem explicar ainda sua causa.
- Construir um caso mínimo reproduzível, removendo detalhes que não influenciam o erro.
- Formular hipóteses concorrentes, em vez de se apaixonar pela primeira explicação.
- Coletar evidências, como logs, métricas, dados de entrada, plano de execução e histórico de mudanças.
- Aplicar a menor correção capaz de testar a causa, acompanhada de um teste que impeça a regressão.
A expressão “menor correção” é importante. Em sistemas complexos, uma mudança grande pode solucionar o sintoma e introduzir três novos problemas. Se o objetivo é aprender, a intervenção deve ser pequena o bastante para que seus efeitos sejam interpretáveis.
Considere uma busca construída com um query builder. O código pode adicionar condições de forma incremental, conforme filtros opcionais são recebidos. Isso é útil, mas também pode ocultar uma diferença importante: uma consulta sem filtro não é apenas uma versão mais flexível da consulta filtrada. Ela pode ter outro custo, outro plano de execução e outro risco operacional.
Se o desenvolvedor não inspeciona a consulta final, seus parâmetros e a quantidade de dados retornada, ele está programando por intenção, não por efeito. A intenção era “permitir uma busca sem filtros”. O efeito pode ser “fazer uma tabela inteira ser lida a cada solicitação”.
O mesmo princípio vale para qualquer bug. Não basta perguntar “qual linha devo mudar?”. Pergunte: qual evidência distinguiria a hipótese A da hipótese B? Essa pergunta transforma a correção de uma atividade intuitiva em um experimento.
Também é preciso saber abandonar uma linha de investigação. Persistir em uma hipótese depois que os dados a enfraqueceram não é determinação. É custo irrecuperável. Grandes desenvolvedores não são aqueles que nunca escolhem o caminho errado. São aqueles que percebem cedo quando o caminho deixou de ser promissor e conseguem voltar sem defender o próprio ego.
Implantar é mudar o mundo, não apenas publicar código
Uma implantação não é o momento em que o código deixa o computador do desenvolvedor. É o momento em que uma nova hipótese passa a operar sobre usuários, dados, filas, permissões, integrações e comportamentos humanos.
Por isso, a qualidade da implantação depende tanto da capacidade técnica quanto da capacidade de observar. Uma mudança pequena no código pode ter uma superfície de impacto enorme. Uma alteração na forma de montar uma consulta pode modificar o volume de dados processado. Uma correção em uma rotina de faturamento pode afetar registros já existentes. Um novo índice pode melhorar uma busca e degradar gravações.
A pergunta madura não é apenas “a implementação funciona?”. É também:
- Como saberemos que funcionou em produção?
- Qual comportamento seria um sinal de regressão?
- Podemos desfazer a mudança rapidamente?
- O que acontece com dados parcialmente processados?
- Quem será avisado se a hipótese estiver errada?
Esse conjunto de perguntas transforma operações em parte do desenvolvimento, não em uma etapa posterior. Logs, métricas, alertas e procedimentos de rollback não são burocracia. Eles são instrumentos de conhecimento.
Pense em uma implantação como um experimento controlado. Antes dela, existe uma previsão: “a latência da busca permanecerá abaixo de determinado valor”, “a taxa de erro não aumentará”, “o número de itens retornados seguirá a distribuição esperada”. Depois dela, existem sinais que confirmam ou contradizem a previsão.
Sem essa previsão, qualquer resultado pode ser racionalizado. Se a equipe não definiu o que observar, um sistema silenciosamente degradado pode parecer saudável. A ausência de reclamações não é evidência de sucesso. Às vezes é apenas ausência de visibilidade.
Há ainda uma dimensão humana. Em situações operacionais, a equipe precisa decidir com informação incompleta e sob pressão. Culpar quem tomou uma decisão ruim torna o próximo incidente mais perigoso, porque as pessoas passam a esconder incertezas. Uma cultura forte separa responsabilidade de culpabilização: alguém pode ser responsável por uma ação sem ser tratado como a causa moral de todo o problema.
O objetivo de uma análise pós incidente deve ser melhorar o sistema de decisão. Que sinal não estava disponível? Que etapa permitiu uma mudança sem validação? Que procedimento dependia da memória de uma pessoa? Que alerta chegou tarde demais? Essas perguntas produzem mecanismos. A pergunta “quem fez isso?” geralmente produz silêncio.
Aprender continuamente é reduzir a taxa de repetição
Aprendizagem contínua é frequentemente confundida com consumir mais conteúdo. Ler documentação, acompanhar padrões de código e conhecer novas ferramentas são atividades importantes, mas seu valor depende de como entram no trabalho cotidiano.
O conhecimento técnico se torna realmente útil quando altera decisões. Saber que uma consulta pode ser composta dinamicamente não basta. É preciso entender quando isso favorece clareza, quando cria risco de desempenho e como verificar o resultado final. Conhecer uma convenção de código não basta. É necessário compreender que problema a convenção evita e quando uma exceção é justificável.
Um bom sistema de aprendizagem funciona como um ciclo:
- Observar uma falha ou uma dúvida recorrente.
- Investigar o princípio por trás dela.
- Registrar a descoberta em uma forma reutilizável.
- Aplicá-la em uma situação real.
- Revisar se a prática melhorou o resultado.
O registro pode ser um teste, uma regra de revisão, uma página curta de documentação ou uma melhoria no processo de implantação. O formato importa menos que a capacidade de impedir que a equipe precise reaprender a mesma lição.
Essa é a diferença entre experiência e repetição. Uma pessoa pode enfrentar dez incidentes semelhantes e continuar cometendo o mesmo erro. Outra pode enfrentar um incidente e convertê-lo em uma validação automática, um alerta ou uma mudança de arquitetura. A segunda extrai mais aprendizagem de um único evento.
Diretrizes de codificação também devem ser entendidas como compressão de experiência coletiva. Uma regra como “selecionar apenas as colunas necessárias” não é uma preferência estética. Pode condensar lições sobre desempenho, acoplamento e evolução de interfaces. Uma convenção de nomes pode condensar anos de manutenção dolorosa. Segui-las não significa abandonar o julgamento; significa não reabrir decisões já amadurecidas sem uma razão concreta.
Ao mesmo tempo, regras sem contexto viram ritual. O desenvolvedor que obedece a uma diretriz sem entender seu propósito não consegue reconhecer quando ela entra em conflito com outra necessidade. O objetivo da aprendizagem não é produzir executores de padrões, mas pessoas capazes de explicar quais riscos cada padrão administra.
Um modelo prático: intenção, superfície, evidência e reversibilidade
Podemos reunir tudo isso em um modelo simples para avaliar qualquer mudança técnica. Antes de começar, responda a quatro perguntas.
1. Intenção
Que comportamento estamos tentando produzir? A intenção deve ser específica o bastante para ser observada. “Melhorar a busca” é fraco. “Reduzir o tempo da busca de pedidos filtrada por cliente para menos de trezentos milissegundos” é uma intenção operacional.
2. Superfície
O que pode ser afetado, direta ou indiretamente? Inclua dados, desempenho, permissões, integrações, filas, usuários e rotinas de suporte. Quanto maior a superfície, mais importante se torna limitar o escopo da mudança.
3. Evidência
Que sinais confirmarão ou refutarão a hipótese? Defina testes antes da alteração e métricas antes da implantação. Se a evidência só é escolhida depois que o resultado aparece, existe grande risco de autoengano.
4. Reversibilidade
Como retornaremos ao estado anterior se a hipótese estiver errada? Uma mudança reversível é mais segura não porque nunca falhará, mas porque reduz o custo de descobrir a falha.
Essas quatro dimensões ajudam a conectar decisões aparentemente diferentes. Limitar trabalho em andamento reduz a superfície cognitiva. Construir um caso mínimo melhora a evidência. Fazer implantações pequenas aumenta a reversibilidade. Acompanhar diretrizes transforma experiências passadas em proteção futura.
Aplicado a uma consulta, o modelo poderia resultar em algo assim: a intenção é retornar apenas pedidos ativos de um cliente; a superfície inclui volume de dados e tempo de resposta; a evidência será obtida com testes para filtros presentes e ausentes, além de métricas em produção; a reversibilidade consiste em manter a implementação anterior disponível e implantar gradualmente.
Aplicado a uma tarefa de produto, o raciocínio é o mesmo. Não se começa com “vamos desenvolver o recurso inteiro”. Começa-se com a menor mudança que testa a hipótese principal, define-se como medir o resultado e evita-se abrir novas frentes antes de fechar o ciclo.
Principais aprendizados
- Limite o trabalho em andamento. Defina poucos itens simultâneos e trate a conclusão como a principal medida de progresso.
- Converta sintomas em hipóteses. Antes de alterar o código, escreva uma explicação que possa ser testada e refutada.
- Inspecione o efeito real das abstrações. Verifique a consulta final, os parâmetros, os dados retornados, o desempenho e os efeitos colaterais.
- Projete a implantação para aprender. Estabeleça métricas, sinais de regressão e um caminho claro de reversão antes de publicar.
- Transforme incidentes em mecanismos. Cada falha recorrente deve resultar em um teste, alerta, documentação ou mudança de processo.
O desenvolvedor excelente não é aquele que mantém todas as tarefas abertas, responde a todos os incidentes instantaneamente ou conhece todas as ferramentas. É aquele que constrói um ambiente onde cada mudança pode ser compreendida, observada e, se necessário, desfeita.
No fim, software não é apenas uma coleção de instruções. É um conjunto de apostas sobre o comportamento do mundo. Consultas apostam que certos dados serão encontrados. Correções apostam que uma causa foi identificada. Implantações apostam que o sistema continuará saudável sob novas condições. Aprender é melhorar a qualidade dessas apostas.
A maturidade técnica começa quando deixamos de confundir movimento com progresso. Escrever mais código pode aumentar o número de possibilidades. Reduzir incerteza é o que transforma possibilidades em engenharia.
Sources
Hatch New Ideas with Glasp AI 🐣
Glasp AI allows you to hatch new ideas based on your curated content. Let's curate and create with Glasp AI :)
Start Hatching 🐣