Teve uma época em que o gargalo do desenvolvimento era digitar código.
Hoje, com ferramentas como OpenAI GPT, Anthropic Claude, Cursor e copilots modernos, o gargalo mudou completamente:
O problema agora não é mais “como escrever código rápido”.
É:
- como impedir a IA de gerar arquitetura ruim;
- como evitar complexidade acidental;
- como manter consistência;
- como garantir que o código continue sustentável daqui a 2 anos.
E é exatamente por isso que times maduros estão começando a investir menos em “gerar código” e mais em:
- quality gates,
- análise estática,
- especificações extremamente detalhadas,
- pipelines automatizados,
- e orquestração inteligente de modelos.
A ironia é interessante:
Quanto melhor a IA ficou em escrever código, mais importante ficou a engenharia de software tradicional.
O problema que quase ninguém fala sobre IA gerando código
A maioria das demos de IA impressiona porque mostram:
- componentes pequenos,
- funções isoladas,
- CRUDs simples,
- ou automações triviais.
Mas sistemas reais possuem:
- acoplamento histórico,
- regras de negócio implícitas,
- débitos técnicos antigos,
- múltiplos times mexendo simultaneamente,
- limitações de infraestrutura,
- requisitos não funcionais,
- performance,
- segurança,
- observabilidade,
- compatibilidade retroativa.
E é exatamente aí que começam os problemas.
Porque a IA consegue escrever código funcional.
Mas frequentemente ela:
- aumenta complexidade sem necessidade;
- cria abstrações prematuras;
- adiciona edge cases irrelevantes;
- duplica lógica;
- ignora padrões internos;
- mistura responsabilidades;
- gera arquitetura inconsistente;
- cria “soluções inteligentes” difíceis de manter.
Ou pior:
gera código aparentemente elegante… mas operacionalmente ruim.
Quality Gates: a defesa contra código “bonito porém perigoso”
Uma das mudanças mais importantes nos fluxos modernos com IA é o fortalecimento dos chamados “quality gates”.
São barreiras automatizadas que impedem que código ruim seja integrado ao projeto.
Na prática, isso significa bloquear PRs que:
- aumentem complexidade ciclomática;
- reduzam cobertura de testes;
- dupliquem código;
- violem padrões arquiteturais;
- aumentem vulnerabilidades;
- quebrem lint;
- ignorem tipagem;
- aumentem acoplamento.
Ferramentas comuns:
O ponto importante aqui:
Antes, essas ferramentas eram “apoio”.
Agora elas viraram mecanismos de contenção contra a IA.
Complexidade ciclomática: o problema invisível
Uma das métricas que mais voltou a ganhar relevância é a complexidade ciclomática.
Ela mede quantos caminhos lógicos diferentes existem dentro de uma função.
Exemplo simples:
function calculate(price: number, type: string) {
if (type === 'A') {
if (price > 100) {
return price * 0.8
}
return price * 0.9
}
return price
}Parece simples.
Mas conforme IAs começam a adicionar:
- retries,
- fallbacks,
- validações extras,
- edge cases,
- flags,
- múltiplos estados,
a complexidade explode rapidamente.
O problema?
Código complexo não quebra imediatamente.
Ele apenas:
- fica difícil de entender;
- difícil de testar;
- difícil de alterar;
- perigoso para refatorar.
E IAs têm uma tendência natural de aumentar complexidade “por precaução”.
O perigo dos edge cases inúteis
Esse talvez seja um dos comportamentos mais perigosos das IAs modernas.
Você pede:
“crie um hook de autenticação”
E ela responde adicionando:
- race conditions improváveis;
- retries excessivos;
- múltiplos fallbacks;
- proteção para cenários inexistentes;
- abstrações futuras hipotéticas;
- caches desnecessários.
Tudo isso parece “engenharia madura”.
Mas muitas vezes é apenas complexidade especulativa.
E existe uma regra clássica da engenharia de software:
Toda complexidade adicionada vira custo permanente.
Um edge case raro pode nunca acontecer.
Mas o código que tenta tratá-lo ficará no sistema para sempre.
Desenvolvedores experientes começaram a rejeitar feedback da IA
Isso é algo curioso de observar.
Profissionais mais experientes não usam IA como “autoridade”.
Eles usam como:
- acelerador mecânico;
- assistente operacional;
- ferramenta de brainstorming;
- gerador inicial.
Mas continuam filtrando tudo.
Principalmente sugestões como:
- “talvez exista uma race condition aqui”;
- “e se duas threads alterarem simultaneamente…”;
- “e se o usuário fizer refresh exatamente…”
Porque muitas vezes o custo da proteção:
- supera o risco;
- piora legibilidade;
- aumenta acoplamento;
- dificulta onboarding;
- complica debugging.
A maturidade está justamente em saber:
quais problemas valem complexidade.
O retorno das especificações detalhadas
Esse é provavelmente o maior shift da engenharia moderna com IA.
Antes:
- o desenvolvedor escrevia código.
Agora:
- o desenvolvedor escreve especificações.
E quanto mais detalhada a spec, melhor o resultado.
Por que prompts vagos geram código ruim
Se você pedir:
“crie um sistema de notificações”
A IA precisará inventar:
- arquitetura;
- estrutura de pastas;
- responsabilidades;
- abstrações;
- padrões;
- bibliotecas;
- fluxo de dados.
E ela provavelmente vai errar partes importantes.
Agora compare com isso:
Objetivo:
Criar um Notification Center desacoplado.
Regras:
- Hook apenas controla polling.
- UI deve ser puramente presentational.
- React Query responsável por cache.
- Zustand apenas para persistência local.
- Não criar abstrações genéricas.
- Evitar classes.
- Priorizar composição funcional.
- Complexidade máxima por função: 5.
- Não adicionar retry automático.
- Não tratar edge cases não descritos.A qualidade muda drasticamente.
Porque IA não é boa em tomar decisões arquiteturais implícitas.
Ela é boa em executar instruções claras.
Pseudo-código virou engenharia de contexto
Muitos desenvolvedores seniores começaram a escrever pseudo-código antes da implementação.
Exemplo:
1. Buscar notificações
2. Se falhar:
- mostrar toast
- parar polling
3. Se sucesso:
- atualizar cache
4. Se status = completed:
- invalidar query
- encerrar pollingIsso reduz drasticamente:
- ambiguidade;
- overengineering;
- abstrações erradas;
- decisões arbitrárias da IA.
Na prática, pseudo-código virou uma camada intermediária entre:
- arquitetura humana
e
- execução automatizada.
Orquestração de modelos: o fluxo que times maduros estão adotando
Outro padrão que está surgindo:
Nem toda IA precisa fazer tudo.
O fluxo mais eficiente frequentemente é:
Modelos grandes
Usados para:
- arquitetura;
- trade-offs;
- reasoning;
- revisão crítica;
- especificações;
- debugging complexo.
Exemplos:
- OpenAI GPT
- Anthropic Claude Opus
Modelos locais menores
Usados para:
- geração mecânica;
- boilerplate;
- refactors simples;
- testes;
- transformações repetitivas.
Exemplos:
- Meta Llama
- Mistral AI Mistral
Por que isso faz sentido economicamente
Usar um modelo gigante para gerar:
- CRUDs,
- DTOs,
- schemas,
- testes repetitivos,
é desperdício financeiro.
O custo alto deve ficar concentrado onde existe:
- tomada de decisão;
- arquitetura;
- raciocínio;
- análise crítica.
O restante pode ser delegado para modelos menores.
Isso transforma IA em uma pipeline de engenharia.
Não apenas em um chatbot que escreve código.
O desenvolvedor virou um “engenheiro de decisões”
Esse talvez seja o ponto mais importante de todos.
A IA diminuiu o custo de escrever código.
Mas aumentou absurdamente o valor de:
- bom julgamento;
- arquitetura;
- priorização;
- clareza;
- pensamento sistêmico;
- simplificação;
- capacidade de dizer “não”.
Porque hoje:
o maior risco não é falta de código.
É excesso de código ruim.
Conclusão
A adoção de IA no desenvolvimento não eliminou engenharia de software.
Na verdade, ela tornou engenharia ainda mais importante.
Os times mais maduros perceberam rapidamente que:
- IA sem quality gates gera caos;
- IA sem especificação gera inconsistência;
- IA sem limites gera overengineering;
- IA sem revisão humana gera dívida técnica acelerada.
O diferencial deixou de ser:
“quem escreve código mais rápido”
E passou a ser:
“quem consegue direcionar a IA sem destruir a simplicidade do sistema”.
No fim, a habilidade mais valiosa continua sendo a mesma:
tomar boas decisões técnicas.
