CTO no Integrar Plus • Publicado em 27 de October de 2026
O custo de gerar sintaxe despencou, mas a fatura de colocar uma funcionalidade em produção continua igual ou mais alta. Essa discrepância expõe o paradoxo de Jevons aplicado ao desenvolvimento: quando uma etapa do processo produtivo fica barata demais, o consumo aumenta desordenadamente e empurra o gargalo para os pontos de atrito seguintes. Quem lida com arquitetura e operação de sistemas percebe isso todo dia na fila de pull requests. Recebemos blocos enormes de código produzidos em segundos, mas a entrega real até o deploy final estagnou.
Duas correntes tentam explicar esse impasse nos debates técnicos recentes. A primeira corrente defende que o problema central é o imposto de revisão. Nessa visão, quando uma pessoa programa manualmente, ela constrói um modelo mental de transições de estado, condições de corrida e casos de borda enquanto digita cada linha. O código final é apenas o subproduto desse raciocínio. Ao pular essa etapa de construção mental com um modelo de linguagem, o revisor humano é forçado a fazer engenharia reversa de centenas de linhas de lógica alheia para tentar descobrir o que a máquina pressupôs.
A segunda corrente argumenta que o buraco fica mais acima, na especificação. Para esse grupo, o código falha porque as instruções fornecidas ignoram o contexto acumulado do sistema legado. Se os requisitos, os limites de domínio e os critérios de aceitação fossem documentados rigidamente antes de chamar qualquer automação, tanto o código gerado quanto o esforço de revisão encolheriam.
Eu discordo do remédio proposto por ambas as visões. Tanto os defensores da revisão exaustiva quanto os entusiastas da hiperespecificação prévia cometem o mesmo equívoco: continuam tratando código como um artefato estático de texto.
A tentativa de resolver o problema escrevendo especificações quilométricas antes de gerar código apenas ressuscita o modelo cascata com uma camada probabilística no meio. Em sistemas vivos, nenhum documento de requisitos cobre o comportamento silencioso de uma tabela que recebe milhares de escritas por segundo ou os efeitos colaterais de uma chave estrangeira sem índice. Por outro lado, confiar que a revisão humana linha a linha vai pegar anomalias em quinhentas linhas geradas é pura ilusão. A atenção humana degrada rápido após a quinquagésima linha lida na tela.
O custo que explodiu nos últimos tempos não foi o da digitação nem o da leitura superficial. O custo real foi transferido para a validação de invariantes em tempo de execução e para o impacto operacional das mudanças.
Quando escrever código custava caro, os desenvolvedores pensavam duas vezes antes de introduzir abstrações desnecessárias, tabelas adicionais ou múltiplos passos em uma requisição HTTP. Havia uma fricção natural que forçava a parcimônia. Com a geração quase instantânea, o incentivo virou despejar classes auxiliares, adaptadores e dezenas de testes de unidade com mocks perfeitos. O conjunto de testes roda em verde no ambiente local, mas mascara o fato de que a transação no banco de dados agora segura locks exclusivos por tempo demais ou consome memória excessiva ao carregar coleções inteiras no processo da aplicação.
Considere uma alteração em um monólito Ruby on Rails com PostgreSQL. Um modelo de linguagem entrega facilmente uma implementação que processa registros em lote, com sintaxe elegante e testes sintéticos impecáveis. No entanto, o modelo frequentemente ignora que aquela operação dispara callbacks encadeados, gera consultas adicionais dependendo do estado prévio dos dados e pode concorrer com rotinas em segundo plano que acessam os mesmos registros.
O teste de unidade isolado passa com louvor porque os dados simulados não refletem o volume real, e o revisor, sobrecarregado pela quantidade de código, foca na legibilidade em vez de simular a concorrência na cabeça. O resultado chega aos servidores de produção na forma de esgotamento de conexões no pool ou travamento de processos do servidor web.
Para conter essa sangria de produtividade, a postura diante de pull requests precisa mudar de foco. Não adianta tentar ler cada instrução de uma alteração gerada esperando enxergar bugs por osmose. O esforço precisa ser deslocado para três frentes práticas:
Primeiro, reduzir o tamanho máximo aceitável de qualquer entrega. Se um assistente gerou quatrocentos arquivos ou quinhentas linhas para resolver um problema, a entrega deve ser rejeitada sumariamente, a menos que se trate de uma migração mecânica e previsível. A facilidade de geração não autoriza o aumento do raio de explosão.
Segundo, transferir a verificação para baterias de testes de integração executados contra instâncias reais do banco de dados, abandonando a dependência excessiva de mocks. Testes de unidade que fingem o comportamento da infraestrutura servem apenas para dar falso conforto a código gerado sem contexto de execução. Se uma rotina altera dados críticos, o teste precisa verificar se a transação faz rollback correto sob erro e se os planos de consulta permanecem eficientes.
Terceiro, orientar a revisão para a pergunta certa. O revisor não deve se preocupar se o código usa o método mais moderno da linguagem, mas sim quais garantias de consistência foram quebradas. Questões como a duração de transações ativas, a criação de índices necessários em tabelas grandes e a idempotência de operações assíncronas devem vir antes de qualquer discussão estética de estilo.
A engenharia de software sempre foi sobre gerenciar complexidade e tomar decisões sob restrições severas. A capacidade de gerar sintaxe sob demanda apenas removeu a etapa mecânica do processo. Se a sua equipe gasta o dobro do tempo depurando sistemas porque confiou cegamente em código abundante e barato, você não ganhou velocidade; apenas acumulou dívida técnica com taxa de juros mais alta. O diferencial de um time sênior continua sendo a disciplina de escrever menos código, cortar caminhos convolutos e proteger a estabilidade do ambiente onde a aplicação realmente roda.
CTO e arquiteto full stack especializado em Ruby on Rails, Vue.js, sistemas multi-tenant e infraestrutura distribuída.