Dívida técnica, dívida cognitiva e dívida de intenção
(martinfowler.com)- Em um ambiente em que LLMs produzem código em massa, não só os problemas do código em si se enfraquecem como também o entendimento compartilhado da equipe e o registro dos objetivos do sistema, aumentando a necessidade de tratar isso em três camadas: dívida técnica, dívida cognitiva e dívida de intenção
- Technical debt limita a capacidade de mudanças futuras, Cognitive debt enfraquece a capacidade da equipe de raciocinar sobre mudanças no sistema, e Intent debt torna difuso o registro de objetivos e restrições, dificultando a evolução contínua por humanos e agentes de IA
- A teoria Tri-System, que posiciona a IA como System 3, distingue o cognitive surrender, em que se confia sem crítica no raciocínio artificial externo e se pula a reflexão, do cognitive offloading, que é visto de forma diferente por ser uma delegação estratégica da cognição
- À medida que o custo de programar cai, o que fica caro é a verification, e os critérios de precisão e sucesso variam conforme o contexto, como ETA no trânsito, despacho de motoristas ou operação de centenas de microsserviços, tornando mais importante o julgamento humano e o desenho de sistemas de verificação
- O eixo central da engenharia se desloca da quantidade de implementação para a verificação, e os humanos continuarão responsáveis por papéis como criar abstrações úteis e dar nomes, além de definir acceptance criteria e projetar test harnesses para preservar o significado do sistema
Três dívidas e a saúde do sistema
- Em um ambiente em que LLMs geram grandes volumes de código, cresce a visão de que as equipes podem perder o entendimento do que o sistema faz, e isso pode ser visto como Cognitive Debt
- Three layers of system health divide a dívida em dimensões de código, pessoas e artefatos
- Technical debt existe no código, se acumula quando decisões de implementação prejudicam a possibilidade de mudanças futuras e limita como o sistema pode evoluir
- Cognitive debt existe nas pessoas, se acumula quando o entendimento compartilhado sobre o sistema se enfraquece mais rápido do que é reposto e limita a capacidade da equipe de raciocinar sobre mudanças
- Intent debt existe nos artefatos, se acumula quando os objetivos e restrições que deveriam guiar o sistema não são devidamente registrados ou mantidos, e limita tanto a capacidade de continuar refletindo o que originalmente se queria construir quanto a de humanos e agentes de IA evoluírem o sistema de forma eficaz
- Essa visão inclui até seções para diagnosticar e mitigar cada tipo de dívida, além de tratar de como as três interagem entre si
- As equipes precisam executar em conjunto atividades gerais para manter essas três dívidas sob controle
Teoria Tri-System e rendição cognitiva
- O artigo que adiciona LLMs ao modelo de pensamento de dois sistemas de Kahneman amplia o modelo cognitivo ao posicionar a IA como System 3
- System 1 toma decisões rapidamente por intuição, e System 2 corresponde à etapa de pensar deliberadamente sobre um problema
- Para economizar energia, os humanos tendem por padrão a confiar na intuição e, com isso, podem deixar passar elementos que perceberiam se tivessem refletido mais
- Como resultado do System 3, surge o cognitive surrender, definido como o estado em que se confia sem crítica no raciocínio artificial gerado externamente e se contorna o System 2
- O artigo distingue isso de cognitive offloading
- cognitive offloading é tratado como o ato de delegar estrategicamente a cognição durante o processo de reflexão
- O artigo desenvolve em detalhe a Tri-System theory of cognition e valida com vários experimentos o quanto essa teoria é eficaz para prever comportamento, ao menos em ambiente de laboratório
A notação <> como ícone de código
- Algumas ilustrações recentes usam o símbolo “<>” como ícone de código, mas essa notação parece pouco natural como forma de envolver elementos de linguagens de programação
- Em vez de outros símbolos como “{ }”, o uso de “<>” parece remeter a HTML ou XML
- Quando aparece até na forma “</>”, a associação com HTML fica ainda mais direta, mas HTML não é tratado como uma linguagem em que programadores escrevem programas
Quando programar fica barato, o caro é verificar
- if coding agents make coding free, what becomes the expensive thing argumenta que, quanto mais os agentes de codificação reduzem o custo de programar, mais verification se torna o elemento caro
- O critério de correção continua variando conforme o contexto
- Um algoritmo de ETA no trânsito de Jakarta e um algoritmo de ETA no trânsito de Ho Chi Minh City podem ter significados diferentes para “correct”
- No despacho de motoristas, é preciso equilibrar ao mesmo tempo justiça na receita, tempo de espera do cliente e utilização dos veículos, então não existe uma única definição de “successful”, mas várias
- Em um ambiente em que centenas de engenheiros fazem deploy contínuo em cerca de 900 microsserviços, “correct” deixa de ter uma definição única e se fragmenta em milhares de definições, todas mutáveis e dependentes de contexto
- Esse tipo de julgamento aparece como um trabalho que agentes não podem substituir
- Os agentes tendem a funcionar especialmente bem em fluxos nos quais há boa verificação do resultado e, se possível, automatizada
- Esses fluxos incentivam Test Driven Development
- Como ainda há muito a verificar, é preciso investir mais em formas de ajudar humanos a compreender com facilidade escopos de teste mais amplos
- Sobre modernização de legado, o texto também apresenta algumas divergências
- A expectativa de que agentic coding resolva de vez a modernização de sistemas legados está superestimada
- Ainda assim, há fortes evidências de que LLMs ajudam muito na compreensão do que o código legado está fazendo
Reorganização em torno da verificação
- Se os agentes assumem a execução, o trabalho humano se desloca para projetar sistemas de verificação, definir qualidade e lidar com casos ambíguos que os agentes não conseguem resolver
- A estrutura organizacional também precisa mudar para acompanhar essa transformação
- A pergunta da reunião de segunda-feira de manhã deixa de ser “o que foi entregue” e passa a ser “o que foi verificado”
- Em vez de rastrear volume de output, passa-se a rastrear se o resultado estava correto
- Uma equipe de 10 engenheiros que antes construía funcionalidades pode ser reorganizada em 3 engenheiros e outros 7 responsáveis por definir acceptance criteria, projetar test harnesses e monitorar outcomes
- Essa reorganização pode causar desconforto, porque reduz o status do ato de construir e eleva o status do ato de julgar
- Culturas de engenharia que não resistirem a essa mudança têm maior chance de se sair melhor
O futuro do código-fonte e linguagens amigáveis a LLM
- Em meio à tendência de tratar LLMs como programadores, o próprio futuro do código-fonte passa a ser uma questão
- several views of the future of code reúne várias perspectivas sobre o futuro do código
- Alguns estão experimentando linguagens totalmente novas projetadas com LLMs em mente
- Outros avaliam que linguagens existentes, especialmente as de tipagem rigorosa como TypeScript e Rust, podem ser mais adequadas para LLMs
- O texto tem muitas citações e pouca análise própria, mas vale como material de visão geral sobre a discussão
As abstrações e os nomes que cabem aos humanos
- Mesmo ao desenvolver software com LLMs, os humanos continuarão responsáveis por criar abstrações úteis que permitam explicar o que o código faz
- Isso se conecta à Ubiquitous Language do DDD
- growing a language trata de como fazer essa linguagem crescer junto com LLMs
- Programar não é apenas inserir sintaxe de codificação que o computador consiga entender e executar, mas também dar forma a uma solução
- Isso envolve dividir o problema em partes focadas, agrupar dados e comportamentos relacionados e escolher nomes que revelem a intenção
- Bons nomes separam a complexidade e transformam o código em um esquema que todos conseguem acompanhar, conectando com clareza a estrutura do problema à estrutura da solução
3 comentários
O termo dívida de intenção foi algo que eu mesmo defini à minha maneira no passado, então é bom revê-lo assim. Acho que no fim as pessoas pensam de forma bem parecida.
Post no blog: https://brunch.co.kr/@limjk/2
Também me dá uma certa sensação de aversão, como se até mesmo reorganizar a organização rapidamente para acompanhar as mudanças fosse algo levemente conservador.
Comentários no Hacker News
Se você é do tipo que só fica tranquilo quando entende profundamente tudo o que coloca em produção, essa mudança pode parecer bem inquietante
Hoje em dia, até um projeto de modernização que levaria 2 meses pode ser concluído em cerca de uma semana se, em vez de tentar cavar toda a lógica de negócio e reproduzi-la fielmente, você focar em desenhar bem os limites e as interfaces
E, como o texto diz, basta montar um bom test harness para verificar a equivalência o máximo possível
Eu também fiquei bastante dividido no começo, mas pensando bem percebi que, nos outros sistemas que mantenho no dia a dia, eu também não conhecia tão bem assim a implementação interna nem a lógica de negócio
Como era código que eu mesmo escrevi alguns anos atrás e quase não mexi desde então, quando precisava mudar algo acabava confiando na suíte de testes ou seguindo a estrutura do código para entender um comportamento específico
Mesmo em ciclos de demissão ou corte de custos, já vi várias vezes que quem tem muito desse conhecimento sobrevive mais do que quem não tem
Fico curioso sobre o que estou deixando passar
Não é como se faltasse ao LLM a virtude da preguiça
Se você der um prompt base alinhado com a intenção, dá para induzir agentes baseados em Claude a minimizar mudanças no código, rodar uma passada de remoção de duplicação e demonstrar comportamentos que parecem instintos de um desenvolvedor bem sênior
Não acho que o modelo seja incapaz de aprender esse conhecimento; ele só não fica em primeiro plano na configuração padrão
Imagino que todo mundo já tenha visto modelos com um estilo de over-editing, saindo mexendo no codebase inteiro sem se preocupar nem um pouco com mudanças de outras pessoas ou com o risco de perda de conhecimento
Essa discussão sobre geração e validação de documentos também se parece, no fim, com um problema clássico de locking, e existem soluções tradicionais para isso
O agente consegue perfeitamente ler o git e entender o que veio primeiro e se, por convenção, deve esperar outras mudanças antes de prosseguir
Eu também sou bastante sênior, e já trabalhei no mesmo time de algumas das pessoas citadas nesse texto
Acho que elas não questionariam meus padrões de engenharia
Mesmo assim, no meu workflow com LLM eu quase não vejo esse tipo de dívida e, na verdade, sinto que a qualidade dos projetos melhorou em comparação com 5 ou 10 anos atrás, mesmo julgando pelos mesmos critérios de antes
Não é mágica; basta operar bem agentes que compartilhem essas prioridades de qualidade
E eu estou entregando mais trabalho real em vez de tentar chamar atenção em conferências
Só que a parte de estar melhor do que há 5 ou 10 anos mesmo sob métricas tradicionais de qualidade de software soa vaga demais
Queria entender de forma mais concreta que métricas você usa e como o código de 10 anos atrás, 5 anos atrás e o de agora se compara em cada uma delas
Sem essa explicação, a mensagem acaba ficando mais difusa e meio fora do ponto principal
Se tiver mais para compartilhar, eu realmente teria interesse
Você até poderia escrever um livro com o título Practical LLM Coding
Acho que a parte mais subestimada aqui é esse enquadramento de intent debt
Dívida cognitiva e dívida técnica ao menos deixam rastros no código, mas intent debt é invisível
Por isso ela só aparece quando entra uma mudança que faz sentido localmente, mas está errada no contexto global
A restrição original simplesmente não ficou registrada em nenhum artefato
O caso mais difícil é quando, em sistemas enterprise, essa restrição vinha de um requisito regulatório que mudou silenciosamente há 3 anos e ninguém atualizou o código
Como os testes continuam passando, fica ainda mais fácil deixar passar
Só a suíte de testes não consegue recuperar a intenção
Não acho que o Martin esteja completamente errado, mas essa lógica parece ser o tipo de argumento que sempre pode ser feito toda vez que subimos um nível de abstração
Pela definição dele, até a passagem de Assembly para Python criaria uma quantidade enorme de intent debt e cognitive debt
Afinal, você deixou de pensar diretamente em como manipular bits e delegou isso ao interpretador
Meu contraponto é que essa intenção técnica de que ele fala existe, no fundo, porque era preciso traduzir a intenção humana para código de máquina
Pensar profundamente sobre um problema não exige necessariamente construir abstrações orientadas ao domínio dentro do código
Você pode pensar profundamente desenhando mapas mentais, escrevendo em um diário ou colando post-its na parede
Abstração orientada a objetos não é mágica
Nesse processo, ambiguidades, detalhes não considerados e até a necessidade de repensar toda a abordagem acabam aparecendo
Escrever em linguagem natural também pode ajudar a pensar, mas há algo essencialmente diferente em ajustar o pensamento a uma linguagem formal que não permite ambiguidade
É parecido com fazer matemática só em linguagem natural, sem notação matemática: fica trabalhoso e sujeito a erros
Só estamos fazendo isso em uma linguagem mais fácil para humanos entenderem
Existe um mapeamento direto entre intenção e implementação
Porque esse mapeamento é bem definido e determinístico
O objetivo da abstração é permitir que você confie que o que fez continua certo sem precisar voltar a olhar o que está embaixo dela
Isso só é possível porque eu ou alguém em quem confio já pagou esse custo uma vez
Mas com LLM é preciso validar a saída toda vez que ela é gerada, e essa dívida precisa ser paga de novo em cada ocasião
Por isso é difícil chamar isso de abstração
O texto está realmente muito bem escrito
Ontem mesmo eu escrevi nas minhas notas pessoais que, se você não continua evoluindo o código organicamente, fica difícil dizer que ele é realmente seu
É como carro autônomo: antes você pelo menos lembrava da paisagem no caminho; agora parece mais que te teleportaram para outro lugar e só te mostraram a gravação depois
Esse tipo de revisão perde eficácia
Em ferramentas pequenas, esse tipo de ghosted code até pode ser aceitável, mas em sistemas como bancos de dados isso me preocupa de verdade
Por isso hoje quase não dou permissão de escrita para agentes e voltei a um fluxo mais centrado em QA manual, como fazia 2 anos atrás
Inclusive foi mais eficiente, tanto em uso de tokens quanto em resultado
Claro, isso é só a minha experiência
Infelizmente, boa parte do artigo de Wharton que ele linkou parece ter sido gerada por IA, e ainda nem passou por peer review
Eu sei que hoje em dia pesquisadores usam IA para ajudar na escrita, mas quando o tema do artigo é justamente cognitive surrender, fica difícil levar o conteúdo tão a sério
not merelynada menos que 7 vezesNem sei se um LLM repetiria a mesma expressão tantas vezes assim; talvez o autor é que tenha adquirido um hábito de escrever como LLM
O Martin não está totalmente errado, mas eu já vi casos em que a IA produziu código preguiçoso, e a resposta correta era justamente ter mais código
Mais especificamente, havia modelos em Python definindo o esquema de banco de dados para um conjunto de conceitos lógicos
Foi adicionado um novo conceito muito parecido com um conjunto lógico já existente, e o Claude concluiu que dava para simplesmente reutilizar o conjunto de modelos atual
Em teoria funcionava, mas do lado do consumidor isso exigia várias gambiarras por causa de inferência de tipos em runtime
Funcionava, mas era um caso claro de escolher completamente errado o nível de abstração
Humanos querem abstrações, mas às vezes repetição é simplesmente a escolha mais certa
Se a máquina é quem escreve e mantém o código, talvez aquela camada extra de abstração que antes fazia sentido já não seja mais necessária
Antigamente usávamos Duff's device e fazíamos unrolling manual de loops, criando código duplicado de propósito
Hoje o compilador entende a intenção e gera o assembly duplicado, e nós não nos preocupamos com essa duplicação
Recentemente precisei de alguns trechos nada triviais de geometria computacional com ajuda de LLM, e antes eu teria que procurar uma biblioteca, conseguir aprovação de compliance e ainda adaptar minhas estruturas de dados de domínio para o formato daquela biblioteca
Isso seria mais barato do que implementar tudo manualmente, mas ainda assim não seria algo pequeno
Agora o LLM consegue escrever só a parte de que preciso e usar exatamente o formato de dados que eu já tenho armazenado
Não preciso incluir uma biblioteca enorme nem fazer conversão de estruturas de dados
Pelo manual, o certo seria usar uma geometry library para evitar duplicação, mas aqui uma função autocontida simplesmente funciona bem
Foi facilmente uma das melhores coisas que li no Hacker News em muito tempo
Me identifiquei demais
Por causa da cognitive debt de que o Simon Willison fala, e dessa visão de que “seu trabalho é colocar em produção apenas código cujo funcionamento você comprovou”, eu acabei indo trabalhar em projetos na linha de Intent-Driven Development
A intenção anterior sempre pareceu se dissipar à medida que as mudanças se acumulavam
Talvez eu consiga transformar isso em um protocolo de verdade e postar no Hacker News depois
Se você ainda não viu meus textos, recomendo dar uma olhada
Em resumo, a ideia é esta
Hoje a visualização do problema que tenho em mente se parece com este diagrama: https://excalidraw.com/#json=y1fSSx2z8-0nFs7CDnqhp,d9Di8JdGU...
Acho que o gargalo cognitivo em engenharia de software não está tanto dentro do código, mas entre os artefatos
O código é só um deles
outcome → requirements → spec → acceptance criteria → executable proof → review
Estou criando um ferramental experimental para automatizar as partes entediantes dessas transições e deixar os humanos focarem em verificar se a intenção sobreviveu em cada etapa
Uma camada que eu ainda acrescentaria aqui é proxies/métricas
Em sistemas muito orientados por análise, a perda real muitas vezes não acontece em spec → code, mas em question → proxy
Quando o proxy acaba embutido em acceptance criteria, dashboards ou evals, as pessoas passam a otimizá-lo e vão esquecendo aos poucos que aquilo era só uma métrica substituta
No celular, ao tentar mover, dar zoom e rolar, fico deslocando os elementos do canvas sem querer