1 pontos por GN⁺ 19 시간 전 | 1 comentários | Compartilhar no WhatsApp
  • Digitar o código você mesmo e praticar recriá-lo de memória testa entendimento e retenção com mais rigor do que copiar
  • Freecoding é a capacidade de escrever código caractere por caractere mantendo sintaxe, tipos e nomes na cabeça, e continua sendo necessário mesmo na era das ferramentas
  • Sintaxe não é ruído que atrapalha o pensamento de alto nível; ela comprime significado preciso e torna possível pensar em um nível mais alto
  • Consultar tipos e esquemas de forma frouxa faz o design do sistema perder nitidez, e não entender o modelo de tipos aumenta o uso de escapes como as any
  • Sem memória de nomes e compreensão do trabalho prévio, agentes tendem a criar implementações duplicadas e também fica mais difícil revisar saídas e testes

Por que você deve digitar o código você mesmo

  • O curso “Learn X the hard way”, de Zed Shaw, recomendava não copiar e colar os exemplos, mas digitá-los manualmente; mais recentemente, passou a recomendar com ainda mais força apagar tudo após terminar o exercício e reconstruir de memória
  • Na psicologia cognitiva, o fenômeno em que gerar ativamente um conteúdo melhora mais a compreensão do que consumi-lo passivamente é chamado de efeito de geração
  • Como na frase de Richard Feynman, “O que eu não consigo criar, eu não entendo”, praticar recriar código com base na memória testa ao mesmo tempo compreensão e memória
  • Isso não significa que, na era da programação com agentes, você não deva usar ferramentas; mas é preciso desenvolver, às vezes, a capacidade de escrever código caractere por caractere sem a conveniência delas
  • Esse treino se concentra em manter na cabeça elementos detalhados da programação, como sintaxe, tipos e nomes, para que você consiga fazer “freecoding”

Freecoding e conhecimento detalhado na cabeça

  • Freecoding é a capacidade de escrever código diretamente com base na memória, e isso só é possível mantendo na cabeça elementos fundamentais como sintaxe, tipos e nomes
  • Sintaxe e estrutura

    • É preciso estar familiarizado com palavras-chave, pontuação e construções da linguagem
    • Não se trata apenas de decorar gramática, mas de conseguir visualizar com precisão a forma do código
  • Tipos e esquemas

    • É preciso estar familiarizado e confortável com o sistema de tipos e o modelo de dados
    • Se você fica apenas no nível de consultar a cada momento as tabelas, colunas, relações e estrutura de tipos do projeto, o design em nível de sistema se torna difícil
  • Nomes

    • Você precisa conseguir lembrar com precisão os nomes de funções, métodos, classes, imports, arquivos e pacotes
    • Quando o projeto e as dependências mudam, esse conhecimento também precisa ser mantido atualizado
    • Se você não consegue digitar com um nível razoável de precisão o código que imaginou mentalmente, na prática está mais perto de achar que entendeu do que de ter entendido com clareza
    • O inglês não é uma linguagem tão precisa quanto o código, e isso também se conecta ao texto A sufficiently detailed spec is code, que argumenta que uma especificação suficientemente detalhada acaba se aproximando de código

A sintaxe torna possível o pensamento de alto nível

  • Mesmo que IDEs ou agentes de código consigam acertar a sintaxe, a capacidade de lidar com ela diretamente continua importante
  • Se você tem dificuldade para equilibrar parênteses, isso também pode levantar dúvidas sobre sua capacidade de conectar com fluidez premissas e conclusões lógicas de outras pessoas
  • A atitude de ignorar detalhes pode se ligar a uma analfabetização funcional em que se comunica mais pelo clima geral do que por atenção clara ao significado das palavras
  • Exemplos de prompts para LLM parecem plausíveis à primeira vista, mas, ao ler com atenção, incluem ao mesmo tempo instruções contraditórias
    • “Não proponha ferramentas externas ou alternativas que não estejam incluídas nas skills listadas acima”
    • “Se a tarefa exigir capacidades além das skills disponíveis, diga isso”
  • A capacidade de lidar com precisão com gramática, ortografia e estrutura pequenas não está separada da capacidade de entender corretamente o panorama maior
  • Sintaxe não é um detalhe que atrapalha o pensamento de alto nível, mas uma ferramenta mental que comprime e viabiliza formas mais elevadas de raciocínio
  • Uma anotação de tipos pode ser mais precisa e concisa do que uma explicação em linguagem natural
    x é um array de objetos, e cada objeto tem uma propriedade obrigatória `domain` que armazena uma string e uma propriedade opcional `port` que armazena um número
    
    x : { domain: string, port?: number }[]
    

Tipos e esquemas são pistas centrais para o design do sistema

  • Fred Brooks, em The Mythical Man-Month, diz que, se você mostrar as tabelas, a estrutura em geral fica clara mesmo sem fluxogramas
  • Se você usa banco de dados, precisa conhecer de trás para frente as tabelas, os nomes das colunas e as relações do projeto
  • Em vez de consultar essas informações de forma frouxa sempre que precisar, é preciso entendê-las antes e mantê-las na cabeça para possibilitar um design efetivo em nível de sistema
  • Sem esse esforço, o esquema do banco tende a ficar tão confuso quanto o pensamento, com estruturas desnormalizadas cheias de dados redundantes e parecidos
  • A experiência com linguagens fortemente tipadas como Rust ou Haskell evidencia bem as vantagens de ter um modelo mental forte de tipos
  • Treinar um “verificador mental de tipos” ou um “borrow checker mental” preciso também ajuda quando se usa linguagens com tipagem mais fraca
  • Sem exercitar esse músculo de raciocínio abstrato, fica mais fácil deixar passar até fundamentos de modelagem de dados como tornar estados inválidos impossíveis de representar
  • Se você não entende como os tipos se encaixam, acaba espalhando as any pelo código TypeScript
  • Se você não consegue suportar o desconforto de pensar em tipos no caminho normal, será ainda mais difícil suportar o caminho anormal de depurar erros de tipos
  • Isso não significa que um Haskeller ou um Rustacean sempre escreva código melhor, mas, com todas as outras condições iguais, fluência em tipos ajuda

É preciso lembrar nomes para conseguir reutilizar

  • Os nomes de funções, métodos, classes, imports, pacotes e arquivos mais usados no projeto ou nas dependências precisam vir à mente com facilidade
  • Isso é uma forma específica de um princípio mais geral: estar familiarizado com o que já foi feito antes, isto é, com o trabalho prévio (prior art)
  • Muita gente depende de agentes de código porque não conhece trabalhos prévios reutilizáveis que já fazem a funcionalidade desejada, e assim acaba fazendo o agente reinventar a roda
  • Se você não conhece a existência de SaaS boilerplate projects, é fácil achar que o agente precisa fazer o scaffolding do zero
  • Clonar um projeto open source comprovado e feito para esse propósito é mais rápido, mais barato e mais confiável do que pedir ao agente para fazer o mesmo trabalho
  • Quando alguém prevê que um LLM poderá construir um navegador inteiro em poucos anos, é possível responder que isso já é viável hoje ao fazer um fork do Chromium, além de ser mais fácil de modificar e manter
  • A memória de nomes também é importante para reutilização de código dentro do mesmo projeto ou empresa
  • Se você não sabe o que procurar, não consegue construir em cima do trabalho dos colegas

Revisar a saída de agentes exige entendimento humano

  • Agentes podem ajudar a explorar nomes e gerar código, mas surge um novo problema: se você consegue revisar o resultado de forma significativa
  • Se você não conhece a funcionalidade existente, é difícil julgar se o agente está implementando algo duplicado
  • Se você entende o código pior do que o agente, também fica difícil revisar adequadamente a qualidade da saída dele
  • Você pode pedir ao agente para gerar testes, mas, se não examinar esses testes com atenção, eles próprios podem virar código sem sentido
  • O exemplo real era de testes que não chamavam o código de implementação e apenas aplicavam diretamente some ou includes a arrays e strings para verificar o valor esperado
    describe("abort detection logic", () => {
      it("detects aborted stopReason in messages", () => {
        const messages = [
          { role: "assistant", stopReason: "aborted", content: [] },
        ];
        const isAborted = messages.some((m: any) => m.stopReason === "aborted");
        expect(isAborted).toBe(true);
      });
    
      it("detects abort in error string", () => {
        const error = "The operation was aborted";
        const isAborted = error.includes("abort");
        expect(isAborted).toBe(true);
      });
    
      it("does not false-positive on normal errors", () => {
        const error = "Network timeout";
        const isAborted = error.includes("abort");
        expect(isAborted).toBe(false);
      });
    
      it("does not false-positive on normal stop reasons", () => {
        const messages = [
          { role: "assistant", stopReason: "stop", content: [] },
        ];
        const isAborted = messages.some((m: any) => m.stopReason === "aborted");
        expect(isAborted).toBe(false);
      });
    });
    
  • O desenvolvimento de software tem muito atrito cotidiano, e, se você escolhe não superar o pequeno atrito de lembrar nomes, também tende a não superar o atrito maior de revisar testes
  • Como agentes de código usam as instruções do usuário como contexto principal, um usuário intelectualmente preguiçoso pode empurrar o agente na mesma direção de preguiça

Persistência e domínio não são coisas separadas

  • Eustress é um estresse benéfico; quando você se força a fazer algo novo e difícil, ganha tolerância a pequenos desconfortos e passa a conseguir enfrentar também os maiores
  • Evitar sempre o desconforto leva a um ciclo vicioso de impotência e frustração crescentes
  • Ao desenvolver precisão, memória e pensamento estrutural em uma área, você também melhora suas capacidades em outras
  • Assim como LLMs generalizam a partir dos dados de treinamento, humanos também generalizam para outras áreas os hábitos e capacidades que desenvolvem em um domínio
  • O desenvolvimento de software envolve, por natureza, sair regularmente da zona de conforto, em linha com o texto relacionado Software engineers are not (and should not be) technicians

1 comentários

 
Opiniões no Lobste.rs
  • Concordo totalmente. Depois de terminar um exercício, apagar o que você acabou de fazer e tentar refazer só de memória é realmente importante
    Se travar, pode olhar pistas, mas poucas coisas são tão importantes quanto criar o hábito de reconstruir da memória, o máximo possível, o processo que você acabou de fazer

  • Mensagens de commit e documentação são melhores quando você digita por conta própria
    Programadores tendem a não gostar desse tipo de escrita e facilmente pensam “o LLM pode escrever isso”, mas, ao escrever você mesmo, acaba encarando ao mesmo tempo a experiência do usuário e as decisões de implementação. Surgem revisões do tipo: “Para fazer X, passe -Y... espera, isso é mesmo o melhor?” “Isto corrige X com Y... mas será que Z também não daria?”

    • Isso às vezes é chamado de desenvolvimento guiado por tutorial. Em vez de pensar na experiência do usuário depois, você começa pela experiência desejada, escreve o tutorial e trabalha de trás para frente
  • Ri da parte “se você tem dificuldade para balancear parênteses, fico em dúvida sobre o quão fluentemente conseguirá conectar as premissas lógicas e as conclusões de outra pessoa”, mas também me senti levemente atingido
    Em minha defesa, às vezes as funções ficam grandes demais

  • Consertar lixo de vibe coding que você não entende também é, na prática, uma boa forma de aprender. Você acaba digitando bastante e trabalhando em contexto real, não no vácuo

    • Recentemente fiz por vibe coding algo que até funcionava mais ou menos, mas não era bom, e o código estava realmente horrível
      Reescrevê-lo à mão virou uma oportunidade para recuperar a intuição de programação que tinha enferrujado nos últimos 8 meses. Gostei do resultado da reescrita e ela de fato funciona melhor. LLMs ainda são úteis para explicar coisas ou destravar pontos específicos, mas é muito melhor sentir que eu conheço a base de código inteira
    • Depende do caso. Às vezes, passar batom num porco continua sendo um porco
  • Não entendo bem por que o prompt “nunca proponha ferramentas externas ou alternativas que não estejam entre as capacidades listadas. Se a tarefa exigir algo além das capacidades disponíveis para o trabalho, diga isso” seria composto de instruções contraditórias
    Dizer “não é possível fazer isso com as capacidades fornecidas” é compatível com as duas instruções. Se a última frase fosse “diga quais capacidades são necessárias”, aí haveria conflito, mas na formulação atual não vejo contradição

    • Parece uma interpretação correta, mas é bem possível que quem escreveu o prompt quisesse que o LLM dissesse o que é necessário, e não apenas “desculpe, preciso de outras capacidades, mas não posso dizer quais”. Claro, também pode ser que a intenção fosse literalmente a frase como está
    • Vejo a resposta “não é possível com as capacidades fornecidas” como incompatível com a segunda instrução
      A segunda frase parece instruir o modelo não a sugerir por negação a existência de ferramentas externas ou alternativas necessárias, mas sim a afirmar construtivamente essa existência
  • A frase “pessoas que não conseguem se expressar com clareza funcional quase sem exceção também têm dificuldade para escrever frases ortográfica ou gramaticalmente corretas” me parece um preconceito bem duro contra pessoas com dislexia ou simplesmente com formas diferentes de pensar
    Claro, isso não significa que se afirmou o inverso, isto é, que escrever mal em ortografia ou gramática implique automaticamente falta de clareza funcional, mas, de um jeito ou de outro, é uma formulação pouco generosa
    Pensando de forma mais construtiva, dá para considerar editores de nós. Sistemas baseados em nós têm muitos problemas nas implementações atuais, mas, se forem bem feitos, podem controlar a forma de escrever programas e eliminar de saída certos erros de sintaxe. Por exemplo, se um nó recebe uma string, você não pode passar um número. Não porque a restrição seja imposta no build ou em tempo de execução, mas porque simplesmente fica impossível “dizer” um número naquele lugar. Também dá para fazer com que intervalos errados de repetição, erros no número de argumentos ou desequilíbrio de parênteses sejam estruturalmente impossíveis
    Escrever software com ferramentas que impõem certas restrições estruturalmente não significa que você não entende essas restrições. Significa apenas que você não precisa se preocupar em cometer acidentalmente esse tipo de erro. E sentir frustração quando a ferramenta não cuida de detalhes sintáticos como a quantidade de chaves de uma função ou a indentação de um bloco lógico também não significa que você não entende por que essa sintaxe importa
    Usei sistemas de nós como exemplo porque eles removem o elemento de “jogar ali e esquecer” do LLM ou o aspecto de vibe coding com o cérebro desligado, isolando apenas a questão sintática. Sem LLM, o argumento focado em sintaxe fica bem mais fraco
    Concordo com o restante do texto, mas acho muito equivocado tratar habilidade sintática como indicador fundamental da compreensão de código de alguém ou da capacidade de escrever bom código

    • Não estou tentando dizer que quem não consegue escrever frases ortográfica ou gramaticalmente corretas seja funcionalmente pouco claro
      Também entendo que foi um feedback de boa-fé, e não quero soar defensivo. Achei que tinha tentado formular isso de um jeito que não parecesse uma afirmação tão pouco generosa, mas estou aberto a outra redação ou estrutura que transmita a mesma ideia melhor
      Ainda assim, não quero remover totalmente esse ponto. O cerne do que quero transmitir é que, quando alguém começa a evitar de forma experiencial um desconforto mental, normalmente ortografia e gramática são as primeiras coisas a desandar. Acho que dá para ajustar a afirmação para que pessoas com dislexia não sejam prejudicadas nesse processo