Estamos vivendo um dos momentos mais fascinantes — e desafiadores — da história da engenharia de software. Em 2026, a presença de agentes autônomos de código no nosso dia a dia já não é mais novidade. IAs escrevem arquivos inteiros, rodam testes, corrigem bugs e abrem Pull Requests em questão de segundos.
No entanto, essa aceleração trouxe à tona um grande conflito: O Paradoxo do Código.
De um lado, temos uma velocidade avassaladora de geração de código. Do outro, um gargalo brutal no Code Review, onde engenheiros humanos gastam horas tentando entender, revisar e validar PRs massivos gerados por IA.
E aqui surge a pergunta fundamental: como acelerar a entrega com IA sem corromper a arquitetura do software e sem passar horas revisando código?
Neste artigo, quero compartilhar uma visão prática sobre como conectar os princípios da Arquitetura Evolutiva, o conceito de Harness e o desenvolvimento orientado a especificações (Spec-Driven Development) para transformar a IA em uma verdadeira alavanca de velocidade com precisão arquitetural.
Estrutura de Pastas Não É Arquitetura
Antes de falarmos sobre IA, precisamos resgatar o que realmente significa Arquitetura de Software.
Muitas vezes, confundimos organização de arquivos com arquitetura. Mas, como nos lembra Uncle Bob em seu clássico artigo sobre Clean Architecture:
"A arquitetura está na estrutura do serviço e na sua interação com o ecossistema. É como a escada e a planta baixa de uma casa."
E, complementando com a clássica definição de Martin Fowler:
"Arquitetura é o conjunto de decisões importantes e difíceis de serem mudadas no futuro."
Toda decisão arquitetural existe para gerenciar a complexidade. E essa complexidade se divide em duas categorias:
- Complexidade Essencial: Inerente ao problema de negócio que você está tentando resolver.
- Complexidade Acidental: Criada pelas decisões da solução técnica que tomamos ao longo do caminho.
No passado, tentávamos prever tudo antes de escrever a primeira linha de código — o chamado Big Upfront Design (BUFD). A experiência nos mostrou que tomar decisões precoces no momento de menor entendimento do projeto só gera rigidez e complexidade acidental.
Em vez disso, a agilidade nos ensinou a praticar o Enough Upfront Design (EUFD): definir apenas a arquitetura necessária para começar. Como resumiu Uncle Bob, o objetivo é "maximizar o número de decisões NÃO tomadas" logo de início, mantendo as opções abertas.
O que é Arquitetura Evolutiva?
"A mudança é inevitável, a evolução é opcional." — Tony Robbins
Se as mudanças de requisitos, mercado e tecnologia são inevitáveis, nosso software precisa ser construído para conviver com elas. Rebecca Parsons, coautora de Building Evolutionary Architectures, define:
"Uma arquitetura evolutiva suporta mudanças contínuas e incrementais como um primeiro princípio."
A arquitetura evolutiva não tenta prever o futuro nem adivinhar o que o negócio precisará daqui a três anos. Em vez disso, ela prepara o sistema para coexistir de forma saudável com as mudanças, facilitando transformações com o menor impacto e custo possíveis.
O Risco da IA sem Limites Arquiteturais
Os agentes autônomos de código atuais possuem alta produtividade, mas funcionam com base em saídas probabilísticas. A IA gera código plausível, mas não necessariamente correto, limpo ou seguro.
O maior perigo é que a IA não possui memória arquitetural.
Sem limites claros e verificáveis, a IA sempre escolherá o caminho mais curto para fazer o código passar no teste imediato — violando camadas, acoplando domínios e criando débito técnico silencioso.
E vale o alerta: pedir no prompt "respeite a Clean Architecture" NÃO impede a erosão. Instruções em linguagem natural sofrem com perda de contexto, atenuação de atenção e alucinação.
Quando deixamos agentes atuarem sem delimitação rígida de escopo executável, os desastres acontecem fora do papel:
- Amazon Kiro: Agente deletou e recriou todo o ambiente produtivo durante um incidente de 13 horas.
- Claude Code: Executou um
terraform destroycom arquivo de estado desatualizado, apagando 2.5 anos de dados. - Replit Agent: Deletou um banco de produção em plena janela de freeze explícito.
- Cursor Plan Mode: Ignorou a instrução de "somente planejar" e apagou 70 arquivos do projeto.
O problema de fundo nesses casos não foi a IA falhar. Foi o escopo de execução não estar restrito fora dela.
O Conceito de Harness e Spec-Driven Development (SDD)
Para resolver esse dilema, precisamos mudar a forma como interagimos com os agentes.
O que é um Harness?
O Harness (ou armadura/cabresto) é a estrutura que envolve o agente de IA com regras de segurança e verificações executáveis fora da IA.
+-------------------------------------------------------------+
| HARNESS |
| |
| +-------------------+ +-----------------------+ |
| | | | | |
| | Agente de IA | ------->| Execução de Tests | |
| | (LLM Isolada) | <-------| & Fitness Functions | |
| | | Feedback| | |
| +-------------------+ de Logs +-----------------------+ |
| |
+-------------------------------------------------------------+
No modelo de Harness:
- A LLM funciona como uma unidade isolada de execução, sem acesso direto ou irrestrito ao ambiente produtivo.
- O sistema opera num loop de feedback fechado: o Harness injeta o contexto e as regras, executa as validações objetivas (testes, linters, checagens estáticas) e devolve apenas os logs de erro para a IA refazer a tarefa até que passe.
Spec-Driven Development (SDD)
Junto com o Harness, adotamos o Spec-Driven Development (SDD). Em vez de dar prompts soltos ("crie uma API de usuários"), o trabalho é guiado por especificações e contratos bem definidos.
- O Framework entrega: Estrutura genérica, orquestração de subagentes, fluxos de validação e gates claros de Definition of Ready (DoR) e Definition of Done (DoD).
- O Humano entrega: Definição das regras de negócio, limites do domínio e premissas específicas do produto.
Existem hoje ecossistemas e metodologias para experimentar esse modelo no seu time, como o Superpowers (skills e workflows modulares para agentes), o TLC (especificação formal de contratos) e o Genesis (geração guiada por specs arquiteturais).
Redução Drástica de Consumo de Tokens
Além da segurança, o SDD traz um benefício financeiro e de performance direto:
- Progressive Disclosure: Injeta no prompt apenas a spec do módulo e suas interfaces imediatas, sem enviar a base de código inteira.
- Batches Atômicos: A spec divide o trabalho em tarefas pequenas com consumo mínimo de contexto.
- Fim do Context Drift: DoR e DoD bem definidos impedem a IA de explorar caminhos irrelevantes.
- Economia de Custo: Menos idas e vindas na conversa podem gerar até 70% de redução no consumo de tokens.
Guardiões da Arquitetura: Fitness Functions na Prática
Como garantimos objetivamente que a IA (ou o próprio time) não está violando a arquitetura? Através de Fitness Functions (Funções de Aptidão).
Como define Rebecca Parsons em Building Evolutionary Architectures:
"Fitness Function é qualquer mecanismo que fornece uma avaliação objetiva da integridade de uma característica arquitetural."
As Fitness Functions formam um espectro de verificação automatizada. Para cada categoria, temos ferramentas consolidadas no mercado:
- Análise Estática & Segurança: Ferramentas como PHPStan, Psalm, SonarQube e Snyk garantem tipagem estrita, prevenção de bugs e zero vulnerabilidades ou credenciais expostas.
- Testes de Unidade & Integração: Frameworks de teste como PHPUnit e Pest PHP fornecem garantia comportamental rápida no nível de métodos e serviços.
- Testes de Mutação: Infection PHP avalia a qualidade da sua suíte de testes inserindo mutações no código para checar se os testes realmente falham ("quem testa os testes?").
- Testes de Contrato: Pact garante a integridade dos contratos de API HTTP/gRPC entre serviços sem precisar subir todo o ecossistema.
- Regras Arquiteturais Executáveis: Ferramentas como Deptrac, PHPArkitect e ArchUnit impedem violações de camadas no CI/CD.
Exemplo Prático: Bloqueando Violações de Camada com Deptrac
Imagine que você deseja garantir estritamente que a sua camada de Domínio nunca importe nada da camada de Infraestrutura ou de Aplicação.
Com o Deptrac, você define esse contrato arquitetural em um arquivo deptrac.yaml:
# deptrac.yaml
deptrac:
paths:
- ./src
layers:
- name: Domain
collectors:
- type: directory
value: src/Domain/.*
- name: Application
collectors:
- type: directory
value: src/Application/.*
- name: Infrastructure
collectors:
- type: directory
value: src/Infrastructure/.*
ruleset:
Domain: [] # Domínio NÃO PODE depender de nenhuma outra camada!
Application:
- Domain
Infrastructure:
- Domain
- Application
Se um agente de IA (ou um desenvolvedor) tentar importar um repositório do Doctrine ou um cliente HTTP dentro de uma entidade de domínio, a execução do deptrac analyze no CI falhará imediatamente:
$ vendor/bin/deptrac analyze
Found 1 violations:
src/Domain/User.php:12
Domain depends on Infrastructure (Infrastructure\Persistence\UserRepository)
Rule: Domain -> Infrastructure is forbidden
O Harness captura esse erro de saída e o devolve para o prompt da IA, que automaticamente entende a violação, cria uma interface na camada de Domínio e move a implementação concreta para a Infraestrutura.
Fitness Functions Não Convencionais
Podemos ir além dos testes tradicionais e criar Fitness Functions para acompanhar requisitos não-funcionais críticos no pipeline:
- Teto de Latência (P95): Integrado com Grafana k6, falha o CI/CD se o tempo de resposta P95 de um endpoint ultrapassar 200ms sob carga.
- Limite de Queries por Request (N+1): Utilizando pacotes como Laravel Query Detector, detecta e bloqueia automaticamente consultas N+1 geradas por ORM em ambiente de testes.
- Teto de Bundle Size: Utilizando bundlesize ou webpack-bundle-analyzer, impede a mesclagem do PR se dependências inflarem o tamanho final do build.
- Eficiência Energética & CPU: Ferramentas como Hyperfine ou Kepler (Kubernetes Efficient Power Level Exporter) medem o consumo de CPU e energia por transação.
O Ciclo Autônomo Protegido & Divisão do Esforço
Com o Harness e as Fitness Functions no lugar, o fluxo de desenvolvimento autônomo se torna seguro:
Agente gera o código ──> Harness roda Fitness Functions
│
┌──────────────┴──────────────┐
▼ ▼
[Se Falhar] [Se Passar]
Harness rejeita e devolve Merge seguro ou revisão
o log de erro para a IA refazer humana focada
Isso redefine radicalmente a divisão de esforço no Code Review:
- Máquina (Harness): Valida tipos, sintaxe, padrões arquiteturais, regras de linting, segurança e cobertura de testes.
- Humano: Revisa a intenção da mudança, o alinhamento com os objetivos de negócio e o real valor entregue para o usuário.
Decisões Reversíveis e Isolamento de Camadas
Para que o código gerado por IA seja facilmente mantido ou substituído, aplicamos a Regra de Dependência em Camadas:
Camadas internas NUNCA dependem de camadas externas. O Domínio comunica-se com o mundo exterior exclusivamente através de interfaces e contratos.
Esse isolamento garante dois grandes benefícios:
- Testabilidade Isolada: Possibilidade de testar toda a regra de negócio sem precisar subir banco de dados, servidor HTTP ou serviços de terceiros.
- Reversibilidade Tecnológica: Possibilidade de trocar de framework ou banco de dados sem alterar uma única linha da regra de negócio.
⚠️ O Custo do Desacoplamento: Reversibilidade vs. Complexidade
Aqui entra um ponto fundamental que muitos negligenciam: desacoplamento aumenta a reversibilidade, mas também aumenta a complexidade acidental do sistema.
Ao introduzir interfaces, ports & adapters, camadas intermediárias, barramentos e filas, você adiciona indireção ao código. Se o sistema não precisa dessa flexibilidade agora, você estará pagando o preço da complexidade sem colher os benefícios da reversibilidade.
Por isso, o desacoplamento deve ser muito bem pensado e pesado. Não isole o código por um purismo teórico cego. Isole apenas os pontos onde a mudança é provável ou onde o risco de acoplamento com terceiros é crítico.
Two-Way Doors vs. One-Way Doors
Inspirado no conceito de tomada de decisão de Jeff Bezos:
- Two-Way Doors 🚪↔️ (Decisões Reversíveis): Possuem baixo custo de mudança. Exemplos: uso de Feature Flags, camada BFF, abstração de serviços por interfaces e rollouts graduais.
- One-Way Doors 🚪➡️ (Decisões Irreversíveis): Possuem alto custo de mudança. Exemplos: escolha da linguagem principal, paradigma de persistência, modelo de banco de dados e provedor de nuvem.
O objetivo da arquitetura evolutiva é tratar o máximo de decisões como reversíveis, abstraindo dependências críticas e mantendo as opções abertas pelo maior tempo possível.
Além disso, busque avaliar o desacoplamento sob duas perspectivas:
- Espacial (Endereço): O consumidor não precisa conhecer o endereço exato do produtor (ex: via BFF ou Barramentos).
- Temporal (Momento): O produtor e o consumidor não precisam estar disponíveis no mesmo instante (ex: via Filas e Mensageria).
Quando a arquitetura é bem isolada nos pontos corretos, o código gerado por IA torna-se verdadeiramente modular, descartável e facilmente substituível.
O Novo Papel do Engenheiro: De Ditador a Guardião
Com a IA assumindo a execução mecânica de código, a atuação do profissional de engenharia se transforma:
| Visão Tradicional | O Engenheiro na Era da IA |
|---|---|
| Digitador de sintaxe e implementador manual de linhas de código. | Arquiteto de soluções, pensador crítico e definidor de limites. |
| Ditador Top-Down que impõe regras arbitrárias e gera dependência manual. | Guia e Guardião que mostra o caminho, ensina os porquês e constrói as automações que protegem o time. |
Conclusão
A Inteligência Artificial veio para ficar e redefinir a produtividade na engenharia de software. Mas velocidade sem direção é apenas o caminho mais rápido para o caos.
Use a IA como alavanca de velocidade e a arquitetura como direção de precisão.
Ferramentas e LLMs geram linhas de código; engenheiros e arquitetos constroem sistemas duradouros, evolutivos e seguros.
E você, como tem delimitado o escopo da IA nos projetos do seu time? Já utiliza Fitness Functions ou guardrails automatizados no CI/CD? Vamos trocar uma ideia nos comentários ou nas redes @eudiegoborgs!