Pode parecer contraintuitivo eu falar isso num mundo onde JavaScript e Python dominam e onde “IA” virou sinônimo de copiar/colar código rápido. Mas é exatamente por isso que tipagem forte + compilador ficaram ainda mais importantes agora.

LLM adora caminho curto: linguagem dinâmica, script rodando sem build, sobe rápido, “funciona”. Só que esse atalho vem com juros compostos: mais bug bobo, mais bug invisível, mais tempo corrigindo bug que a própria IA gerou… e sim: mais tokens queimados. Vamos por partes.

“Mas tudo vira máquina do mesmo jeito”

Independente da linguagem, o pipeline real é sempre parecido:

código → parser → AST → camadas intermediárias (HIR/MIR/IR) → otimizações → assembly/bytecode → execução

Se roda em VM (tipo Java/Erlang/Elixir), se roda em JIT (JS/Python/Java), ou se gera binário AOT (C++/C#/Rust/Zig), no fim alguém precisa responder perguntas chatas:

  • quanto de memória isso ocupa?

  • qual instrução usar pra somar, comparar, chamar função?

  • qual layout desse objeto?

  • isso aqui é inteiro, float, ponteiro, referência, string?

E aí vem o ponto que muita gente ignora: quando você desce o nível, tipagem vira unanimidade. Linguagem dinâmica também cria “tipos reais” por baixo (mesmo que em runtime). Ela só empurra a decisão pra depois — e o “depois” é quando você tá com produção em chamas.

Tipagem dinâmica é só tipagem adiada

O Number do JavaScript, por exemplo, pode “parecer um número genérico”, mas o motor tá o tempo todo tentando encaixar em representações eficientes (int32, double, etc.), fazendo deopt quando muda o perfil. Isso é poderoso — e instável. O custo aparece como:

  • comportamento diferente sob carga

  • quedas de throughput em “picos aleatórios”

  • bugs que somem no dev e aparecem no prod

  • profiling virando religião

GC resolveu um inferno e trouxe outro

A indústria enfiou Garbage Collector como solução pra uma era onde memory leak e buffer overflow eram rotina (C puro era faroeste). Só que GC não é “de graça”:

  • ele compete por CPU com seu código

  • ele cria pausas (às vezes pequenas, às vezes assassinas)

  • ele muda a previsibilidade do sistema

Em alta concorrência, previsibilidade vale ouro. Por isso você vê o mercado apelando pra:

  • pools de objetos

  • estruturas “flat” e compactas

  • menos alocação por request

  • fuga pro unsafe/ponteiro quando a coisa aperta

E aí você volta pra aquele bingo do terror: stack overflow, access violation, race condition.

Rust acertou o alvo — e o mercado ainda finge que não

Quem entendeu esse trade-off e trouxe uma perspectiva realmente nova foi Rust:

  • sem GC

  • tipagem forte de verdade

  • ownership/borrow checker (regras no compile-time)

  • otimização agressiva e previsível

Resultado: aplicações estáveis, alto desempenho, sem travar do nada, sem “vazamento invisível” como estilo de vida.

O motivo de ainda não ser padrão absoluto é simples e feio: preguiça + custo de aprendizado + cultura de “faz funcionar depois a gente vê”. E sim, a verbosidade incomoda quem só quer “subir endpoint”.

Só que aqui entra o ponto da IA: LLM piora o problema da cultura do atalho, porque ela aumenta a velocidade de produzir código errado.

Compilador é o primeiro agente de qualidade do seu sistema

Pra quem nunca implementou um compilador (ou nunca precisou entender um), parece “mágica”. Mas compilador bom é uma máquina de esmagar classes inteiras de problemas antes de virar bug:

  • checagem de tipos

  • análise de fluxo

  • warnings úteis

  • otimizações que não mudam semântica

  • layout coerente e previsível

E compilador/runtime fazem diferença real. Vários saltos recentes de performance no ecossistema vieram de engenharia pesada no compilador/JIT, sem você tocar no seu código.

O ponto não é “linguagem X é melhor”. O ponto é: um bom pipeline de compilação é um multiplicador de qualidade.

O veneno da ambiguidade: null, any e dados sem contrato

Quem desenvolve há mais tempo sabe: erro de digitação o compilador acha. O problema é o erro complexo, o invisível:

  • variável dinâmica que muda de formato

  • null aparecendo no lugar errado

  • any virando buraco negro

  • JSON vindo torto e ninguém sabe até estourar

  • “funcionava ontem” porque o dado do banco era diferente

Aí entra a treta moderna:

Tipagem dinâmica + banco sem schema = inconsistência inevitável

Quando você junta runtime solto com documento sem validação forte, a inconsistência vira fato estatístico. Você passa mais tempo:

  • tratando exceção

  • escrevendo defensivo

  • entupindo try/catch

  • adicionando validação manual em tudo

E quando você põe IA no meio, piora: a IA gera “o caminho feliz” e ignora os cantos escuros. Você vira o adulto na sala limpando a bagunça.

ORMs e validações ajudam, mas o que resolve de verdade é ter contrato:

  • schema explícito

  • tipos que batem com o contrato

  • validação automática

  • falhar cedo

A virada de chave na era da IA: compilar é parte do prompt

Aqui é onde a galera ainda tá dormindo.

Se você quer usar IA com seriedade, você precisa de um loop curto e brutal de feedback:

  1. IA escreve

  2. compila

  3. testa

  4. falha

  5. IA corrige

  6. repete

Isso transforma o caos em pipeline. E tipagem forte ajuda porque:

  • reduz o espaço de possibilidades (menos ambiguidade)

  • força o modelo a “encaixar” no contrato do sistema

  • deixa refactor seguro (o compilador vira radar)

  • torna o erro explícito e localizável (menos debug místico)

Em linguagem dinâmica, o loop vira:

  1. IA escreve

  2. roda

  3. explode num lugar aleatório

  4. você caça o bug em runtime

  5. descobre que o dado veio diferente

  6. adiciona ifs e try/catch

  7. o código vira um cemitério de exceções

Isso não escala. Nem com humano, nem com IA.

O combo que presta

Compilador é a primeira barreira contra erros básicos.
Tipos reduzem inconsistência de dados e contratos quebrados.
Testes protegem lógica e regressão.
CI garante que nada entra sem passar pelo funil.

E se você tiver um AGENTS decente + CI rodando em commit/PR, você cria um ambiente onde IA vira ferramenta de produção, não brinquedo.

LLM vai quebrar seu código do mesmo jeito. Só que, num setup bem feito, ela quebra e corrige na sequência, porque o sistema não deixa ela “seguir em frente fingindo que tá tudo bem”.

No final, aí sim você escolhe o modelo… e começa a sofrer com brigas forever alone até ficar do jeito que você quer.