Todos os artigos

A Linguagem Que Conheces Ainda Importa?

Ouvir o artigo (experimental) · 09:54

00:00 / 09:54

Vários fluxos de código ténues, de formas diferentes, a fluir para dentro e a convergir num único nó âmbar estável que permanece aceso enquanto os fluxos mudam à sua volta

Passaste anos a tornar-te bom numa linguagem. Aprendeste as regras, depois os hábitos, depois as pequenas verdades feias que só se ganham a pôr coisas em produção com ela e a vê-las partir. E agora um modelo escreve essa linguagem com fluência, e todas as outras também, no momento em que pedes. Por isso a pergunta chega, numa qualquer versão de: continuo com o que sei ou mudo para aquilo para onde toda a gente está a mudar? O medo por baixo dela é mais simples do que a pergunta. Os anos deixaram simplesmente de contar?

A linguagem são duas coisas

Há a linguagem como digitação: a sintaxe, a forma de um ciclo, onde vão os pontos e vírgulas. E há tudo o que está por baixo: como gere a memória, como lida com duas coisas a acontecer ao mesmo tempo, os modos de falha que lhe pertencem e a mais nenhuma, os idiomatismos que são corretos e os que só parecem corretos, o ecossistema e as ferramentas que cresceram à sua volta. A IA tornou a digitação barata. Mal tocou no resto, e há uma razão. O resto não está propriamente no texto. Vive em sistemas a correr e na memória do que partiu, e um modelo aprende com texto. É por isso que a metade profunda não se limitou a sobreviver à mudança. É a metade que a mudança tornou escassa.

Repara em que bugs ficaram mais fáceis

Os erros contra os quais a fluência superficial costumava proteger são exatamente os que o modelo agora evita e o compilador sempre apanhou: uma palavra-chave errada, um pedaço de sintaxe mal usado, uma chamada a algo que não existe. O que sobra são os erros que só a profundidade apanha: a falha de segurança que se lê como código comum, a decisão de design que está errada mesmo com todas as linhas certas, o bug de concorrência que não se vê em linha nenhuma. A IA limpou os erros baratos e deixou os caros, e os baratos eram o único tipo que o conhecimento superficial alguma vez apanhou.

A profundidade é um alarme que dispara sozinho

Há uma sensação que todo o programador experiente conhece. Na linguagem que conheces a fundo, o código errado faz disparar um alarme antes de conseguires dizer porquê. Algo na forma dele não bate certo, por isso paras e olhas. Numa linguagem que só conheces por alto, esse alarme nunca dispara. O código parece plausível, por isso aceita-lo. Um modelo produz código plausível por construção, página após página. Os testes apanham parte do que está errado, e podes apontar um segundo modelo ao primeiro, mas uma suite só verifica as falhas que alguém se lembrou de escrever, e modelos treinados no mesmo código partilham os mesmos pontos cegos. No fim, o que está entre o plausível e o correto é um leitor cujo alarme ainda funciona. Esse leitor é alguém que conhece a linguagem a fundo. Não há atalho para o alarme.

Muda por uma razão, não por um capricho

Os custos de mudar dividem-se da mesma forma que a linguagem. Podes estar a escrever código com ar plausível numa linguagem nova na mesma tarde, e essa parte costumava levar meses. Os idiomatismos, o runtime, o modo como esta linguagem em particular falha, pouco disso se transfere entre linguagens que são estranhas uma à outra. Entre parentes próximas, linguagens que partilham um modelo de execução, passa mais, e esse é o único atalho real que existe. O resto continua a ter de ser conquistado. O que se transfere por inteiro é a parte que nunca foi sobre a linguagem: o modo como decompões um problema e raciocinas sobre um sistema.

Por isso muda quando houver uma razão real, um domínio que o exija, um emprego que queres, um problema para o qual a linguagem foi feita, e não porque o ruído subiu de volume. Alguns domínios decidem a linguagem por si. O trabalho de tempo real e embedded não pode dar-se ao luxo de um garbage collector a pausar no momento errado, por isso as linguagens de sistemas são donas desse terreno, e o browser é o browser; em ambos, a linguagem está no lugar de um modelo de execução que tens de manter na cabeça, e nenhuma fluência de um modelo muda o que o hardware vai fazer. O machine learning pertence ao Python por uma razão diferente, o ecossistema, e o efeito é o mesmo.

Vê o passo específico com que as pessoas se atormentam, ficar com C++ ou pegar em Rust. Discutido como qual das linguagens vence, não tem resposta limpa e a discussão nunca acaba. Visto através da profundidade, há menos para discutir. Se conheces bem C++, a maior parte do que Rust te pede, pensar a sério em ownership e lifetimes, é peso que já carregavas, só que agora o compilador carrega-o contigo. Isso está mais perto de subir de nível do que de começar do zero. E a versão adulta do passo normalmente não é uma mudança limpa, mas saber o suficiente de cada uma para trabalhar onde cada uma pertence. O erro era tratar isto como uma escolha entre uma ou outra.

O mercado também tem uma palavra a dizer

Há mais uma razão para mudar, e é a menos romântica: a porta. Quanto importa o rótulo na tua experiência depende de como ganhas a vida. Constrói o teu próprio produto e ninguém que o compra pergunta em que está escrito. Ajuda outros a construir os deles, consultoria, freelancing, trabalho de agência, e trabalhas dentro da stack deles, por isso a tua tem de estar suficientemente perto para te contratarem. E na contratação pura e simples, o rótulo pode decidir tudo antes de um humano ler o teu nome. O filtro quer anos de uma framework específica, e profundidade numa linguagem vizinha não te garante a entrevista.

O mercado também tem épocas. As linguagens incham e encolhem na procura, em ciclos que pouco têm que ver com mérito, e uma stack que encheu uma década de anúncios de emprego pode ficar em silêncio enquanto uma em que nunca tocaste aparece em todas as ofertas. Isso não é razão para perseguir cada época. É razão para saberes em que jogo estás. Se o teu rendimento passa pelas stacks dos outros, mantém pelo menos uma linguagem que o mercado quer nesta época, e usa a máquina para aquilo em que agora é boa, levar-te depressa ao plausível numa stack nova, enquanto fazes a parte que ela não consegue: construir profundidade suficiente para defenderes o código na entrevista e depois de contratado. O requisito assinalado abre a porta, e a profundidade é o que te mantém lá dentro.

Onde a profundidade compensa e onde não compensa

Nada disto torna a amplitude inútil. Uma segunda linguagem, sobretudo uma que pensa de forma diferente da primeira, apura a maneira como vês a primeira, e a IA torna a experimentação barata, por isso vaguear quase não custa nada agora. O que perdeu valor foi a amplitude enquanto pilha de sintaxes, cinco linguagens que consegues digitar e nenhuma que consigas defender.

A profundidade também não compensa em todo o lado. Para um script descartável, um bocado de cola, um protótipo que vais apagar na sexta-feira, o modelo nivela o campo e a linguagem quase não importa. A profundidade ganha o seu lugar no código que vive: o sistema maduro onde o desempenho ou a segurança importam de verdade, o código que ainda vais estar a manter daqui a três anos.

A parte incómoda é que as repetições que costumavam construir profundidade vinham de graça com o trabalho, e agora não vêm. Escrevias os ciclos à mão, tropeçavas nos bugs baratos, corrigia-los, e a profundidade acumulava-se como efeito secundário. A máquina faz agora essa parte, por isso as repetições têm de ser escolhidas de propósito. Faz debug ao código gerado em vez de o regenerar. Lê o diff como um revisor leria. Parte algo de propósito para ver como falha. A profundidade acontecia-te; agora tem de ser uma decisão.

Isto é um argumento antigo a voltar à superfície: a produção mecânica de código nunca foi aquilo por que eras pago, e agora é a parte que uma máquina faz. O que resta é o discernimento, e o discernimento na programação não é independente da linguagem como gostamos de fingir. Grande parte dele vive dentro de um runtime, aprendida pela via lenta, a construir coisas nele e a estar presente quando falharam.

Por isso os anos contaram. A parte que perdeu valor nunca foi a parte que estava a contar. A sintaxe que decoraste vale menos agora, e nunca valeu muito. O modelo da linguagem que construíste por baixo dela, fundo o suficiente para saberes quando o código gerado te está a mentir, vale mais do que alguma vez valeu. Aprende uma linguagem bem o suficiente para a reveres.

Perguntas a que este artigo responde

  • Fico na linguagem que sei ou mudo para aquela para onde toda a gente está a mudar?

    Muda quando houver uma razão real, um domínio que o exija, um emprego que queres, um problema para o qual a linguagem foi feita, e não porque o ruído subiu de volume. Alguns domínios decidem por ti: o trabalho de tempo real e embedded não pode dar-se ao luxo de um garbage collector a pausar no momento errado, o browser é o browser, e o machine learning pertence ao Python pelo ecossistema. Se o teu rendimento passa pelas stacks dos outros, consultoria ou contratação pura e simples, mantém pelo menos uma linguagem que o mercado quer nesta época, porque o rótulo pode decidir tudo antes de um humano ler o teu nome.

  • Porque não aponto simplesmente um segundo modelo ao código do primeiro?

    Porque modelos treinados no mesmo código partilham os mesmos pontos cegos, e uma suite de testes só verifica as falhas que alguém se lembrou de escrever. Um modelo produz código plausível por construção, página após página, e o que está entre o plausível e o correto é um leitor cujo alarme ainda dispara quando a forma do código não bate certo. Esse leitor é alguém que conhece a linguagem a fundo, e não há atalho para o alarme.

  • Sei bem C++. Pegar em Rust é começar do zero?

    Está mais perto de subir de nível do que de começar do zero. A maior parte do que o Rust te pede, pensar a sério em ownership e lifetimes, é peso que um programador de C++ já carregava, só que agora o compilador carrega-o contigo. A versão adulta do passo normalmente não é uma mudança limpa, mas saber o suficiente de cada uma para trabalhar onde cada uma pertence, e o erro é tratar isto como uma escolha entre uma ou outra.

  • Como é que construo profundidade agora que a máquina escreve o código de rotina?

    Escolhendo as repetições de propósito, porque já não vêm de graça com o trabalho. Escrevias os ciclos à mão, tropeçavas nos bugs baratos e corrigias-os, e a profundidade acumulava-se como efeito secundário. Faz debug ao código gerado em vez de o regenerar, lê o diff como um revisor leria, e parte algo de propósito para ver como falha.