Loading...

CINCO PERGUNTAS SOBRE DESIGN DE LINGUAGEM

Original

Maio de 2001

(Estas são algumas anotações que fiz para uma discussão em painel sobre design de linguagens de programação no MIT em 10 de maio de 2001.)

1. Linguagens de Programação São para Pessoas.

Linguagens de programação são como as pessoas falam com os computadores. O computador ficaria tão feliz falando qualquer linguagem que fosse inequívoca. A razão pela qual temos linguagens de alto nível é porque as pessoas não conseguem lidar com linguagem de máquina. O objetivo das linguagens de programação é evitar que nossos pobres e frágeis cérebros humanos sejam sobrecarregados por uma massa de detalhes.

Arquitetos sabem que alguns tipos de problemas de design são mais pessoais do que outros. Um dos problemas de design mais limpos e abstratos é projetar pontes. Lá, seu trabalho é em grande parte uma questão de atravessar uma determinada distância com o menor material possível. O outro extremo do espectro é projetar cadeiras. Designers de cadeiras têm que passar seu tempo pensando em traseiros humanos.

O software varia da mesma forma. Projetar algoritmos para roteamento de dados através de uma rede é um problema agradável e abstrato, como projetar pontes. Enquanto projetar linguagens de programação é como projetar cadeiras: tudo se resume a lidar com as fraquezas humanas.

A maioria de nós odeia reconhecer isso. Projetar sistemas de grande elegância matemática soa muito mais atraente para a maioria de nós do que se submeter às fraquezas humanas. E há um papel para a elegância matemática: alguns tipos de elegância tornam os programas mais fáceis de entender. Mas a elegância não é um fim em si mesma.

E quando digo que as linguagens têm que ser projetadas para se adequar às fraquezas humanas, não quero dizer que as linguagens têm que ser projetadas para programadores ruins. Na verdade, acho que você deve projetar para os melhores programadores, mas mesmo os melhores programadores têm limitações. Não acho que alguém gostaria de programar em uma linguagem onde todas as variáveis eram a letra x com subscritos inteiros.

2. Projete para Você e Seus Amigos.

Se você olhar para a história das linguagens de programação, muitas das melhores foram linguagens projetadas para seus próprios autores usarem, e muitas das piores foram projetadas para outras pessoas usarem.

Quando as linguagens são projetadas para outras pessoas, sempre é um grupo específico de outras pessoas: pessoas não tão inteligentes quanto o designer da linguagem. Assim, você obtém uma linguagem que fala de forma condescendente. Cobol é o mais extremo, mas muitas linguagens são permeadas por esse espírito.

Isso não tem nada a ver com quão abstrata a linguagem é. C é bastante de baixo nível, mas foi projetada para seus autores usarem, e é por isso que os hackers gostam dela.

O argumento para projetar linguagens para programadores ruins é que há mais programadores ruins do que bons programadores. Isso pode ser verdade. Mas esses poucos bons programadores escrevem uma porcentagem desproporcionalmente grande do software.

Estou interessado na questão, como você projeta uma linguagem que os melhores hackers vão gostar? Acredito que isso é idêntico à questão, como você projeta uma boa linguagem de programação?, mas mesmo que não seja, é pelo menos uma questão interessante.

3. Dê ao Programador o Máximo de Controle Possível.

Muitas linguagens (especialmente as projetadas para outras pessoas) têm a atitude de uma governanta: tentam impedir você de fazer coisas que acham que não são boas para você. Eu gosto da abordagem oposta: dê ao programador o máximo de controle que você puder.

Quando aprendi Lisp pela primeira vez, o que mais gostei foi que ele me considerava um parceiro igual. Nas outras linguagens que aprendi até então, havia a linguagem e havia meu programa, escrito na linguagem, e os dois eram muito separados. Mas em Lisp, as funções e macros que escrevi eram como aquelas que compunham a própria linguagem. Eu poderia reescrever a linguagem se quisesse. Tinha o mesmo apelo que o software de código aberto.

4. Busque a Brevidade.

A brevidade é subestimada e até mesmo desprezada. Mas se você olhar nos corações dos hackers, verá que eles realmente a amam. Quantas vezes você ouviu hackers falarem com carinho sobre como em, digamos, APL, eles podiam fazer coisas incríveis com apenas algumas linhas de código? Acho que qualquer coisa que pessoas realmente inteligentes realmente amam vale a pena prestar atenção.

Acho que quase qualquer coisa que você possa fazer para encurtar programas é boa. Deve haver muitas funções de biblioteca; qualquer coisa que possa ser implícita deve ser; a sintaxe deve ser concisa a ponto de ser excessiva; até mesmo os nomes das coisas devem ser curtos.

E não são apenas os programas que devem ser curtos. O manual deve ser fino também. Uma boa parte dos manuais é ocupada com esclarecimentos e reservas e avisos e casos especiais. Se você se forçar a encurtar o manual, no melhor dos casos, você faz isso corrigindo as coisas na linguagem que exigiam tanta explicação.

5. Admita o que é Hacking.

Muitas pessoas gostariam que hacking fosse matemática, ou pelo menos algo como uma ciência natural. Acho que hacking é mais como arquitetura. A arquitetura está relacionada à física, no sentido de que os arquitetos têm que projetar edifícios que não desmoronem, mas o objetivo real dos arquitetos é fazer grandes edifícios, não fazer descobertas sobre estática.

O que os hackers gostam de fazer é criar grandes programas. E eu acho que, pelo menos em nossas próprias mentes, temos que lembrar que é algo admirável escrever grandes programas, mesmo quando esse trabalho não se traduz facilmente na moeda intelectual convencional de artigos de pesquisa. Intelectualmente, é tão valioso projetar uma linguagem que os programadores vão amar quanto projetar uma horrível que incorpore alguma ideia sobre a qual você pode publicar um artigo.

1. Como Organizar Grandes Bibliotecas?

Bibliotecas estão se tornando um componente cada vez mais importante das linguagens de programação. Elas também estão ficando maiores, e isso pode ser perigoso. Se leva mais tempo para encontrar a função de biblioteca que fará o que você quer do que levaria para escrevê-la você mesmo, então todo aquele código não está fazendo nada além de tornar seu manual grosso. (Os manuais da Symbolics foram um caso em questão.) Então, acho que teremos que trabalhar em maneiras de organizar bibliotecas. O ideal seria projetá-las de forma que o programador pudesse adivinhar qual chamada de biblioteca faria a coisa certa.

2. As Pessoas Realmente Têm Medo da Sintaxe Prefixada?

Este é um problema em aberto no sentido de que eu me pergunto sobre isso há anos e ainda não sei a resposta. A sintaxe prefixada parece perfeitamente natural para mim, exceto possivelmente para matemática. Mas pode ser que a muita da falta de popularidade do Lisp se deva simplesmente a ter uma sintaxe desconhecida. Se devemos fazer algo a respeito, se isso for verdade, é outra questão.

3. O que Você Precisa para Software Baseado em Servidor?

Acho que muitas das aplicações novas mais empolgantes que serão escritas nos próximos vinte anos serão aplicações baseadas na Web, ou seja, programas que ficam no servidor e falam com você através de um navegador Web. E para escrever esses tipos de programas, podemos precisar de algumas novas coisas.

Uma coisa que precisaremos é suporte para a nova maneira que os aplicativos baseados em servidor são lançados. Em vez de ter uma ou duas grandes versões por ano, como software de desktop, aplicativos baseados em servidor são lançados como uma série de pequenas mudanças. Você pode ter até cinco ou dez lançamentos por dia. E, como regra, todos sempre usarão a versão mais recente.

Você sabe como pode projetar programas para serem depuráveis? Bem, o software baseado em servidor também precisa ser projetado para ser modificável. Você precisa ser capaz de mudá-lo facilmente, ou pelo menos saber o que é uma pequena mudança e o que é uma mudança significativa.

Outra coisa que pode acabar sendo útil para software baseado em servidor, surpreendentemente, são continuações. Em software baseado na Web você pode usar algo como o estilo de passagem de continuidade para obter o efeito de sub-rotinas no mundo inherentemente sem estado de uma sessão Web. Talvez valha a pena ter continuações reais, se não for muito caro.

4. Quais Novas Abstrações Restam para Descobrir?

Não tenho certeza de quão razoável é essa esperança, mas uma coisa que eu realmente adoraria fazer, pessoalmente, é descobrir uma nova abstração-- algo que faria tanta diferença quanto ter funções de primeira classe ou recursão ou até mesmo parâmetros de palavra-chave. Isso pode ser um sonho impossível. Essas coisas não são descobertas com tanta frequência. Mas estou sempre procurando.

1. Você Pode Usar Qualquer Linguagem Que Quiser.

Escrever programas de aplicação costumava significar escrever software de desktop. E no software de desktop há um grande viés em favor de escrever a aplicação na mesma linguagem que o sistema operacional. E assim, há dez anos, escrever software significava praticamente escrever software em C. Eventualmente, uma tradição evoluiu: programas de aplicação não devem ser escritos em linguagens incomuns. E essa tradição teve tanto tempo para se desenvolver que pessoas não técnicas como gerentes e capitalistas de risco também a aprenderam.

O software baseado em servidor derruba todo esse modelo. Com software baseado em servidor, você pode usar qualquer linguagem que quiser. Quase ninguém entende isso ainda (especialmente não gerentes e capitalistas de risco). Alguns hackers entendem isso, e é por isso que ouvimos sobre novas linguagens independentes como Perl e Python. Não estamos ouvindo sobre Perl e Python porque as pessoas estão usando-as para escrever aplicativos Windows.

O que isso significa para nós, como pessoas interessadas em projetar linguagens de programação, é que agora há potencialmente um público real para nosso trabalho.

2. A Velocidade Vem de Profilers.

Designers de linguagens, ou pelo menos implementadores de linguagens, gostam de escrever compiladores que geram código rápido. Mas não acho que isso é o que torna as linguagens rápidas para os usuários. Knuth apontou há muito tempo que a velocidade só importa em alguns gargalos críticos. E qualquer um que tenha tentado sabe que você não pode adivinhar onde esses gargalos estão. Profilers são a resposta.

Os designers de linguagens estão resolvendo o problema errado. Os usuários não precisam de benchmarks para rodar rápido. O que eles precisam é de uma linguagem que possa mostrar quais partes de seus próprios programas precisam ser reescritas. É daí que vem a velocidade na prática. Então, talvez seja um ganho líquido se os implementadores de linguagens gastassem metade do tempo que teriam gasto fazendo otimizações de compilador e gastassem escrevendo um bom profiler em vez disso.

3. Você Precisa de uma Aplicação para Impulsionar o Design de uma Linguagem.

Isso pode não ser uma regra absoluta, mas parece que as melhores linguagens todas evoluíram junto com alguma aplicação que estavam sendo usadas para escrever. C foi escrito por pessoas que precisavam dele para programação de sistemas. Lisp foi desenvolvido em parte para fazer diferenciação simbólica, e McCarthy estava tão ansioso para começar que estava escrevendo programas de diferenciação mesmo no primeiro artigo sobre Lisp, em 1960.

É especialmente bom se sua aplicação resolver algum novo problema. Isso tende a levar sua linguagem a ter novos recursos que os programadores precisam. Pessoalmente, estou interessado em escrever uma linguagem que seja boa para escrever aplicações baseadas em servidor.

[Durante o painel, Guy Steele também fez esse ponto, com a sugestão adicional de que a aplicação não deve consistir em escrever o compilador para sua linguagem, a menos que sua linguagem seja destinada a escrever compiladores.]

4. Uma Linguagem Tem que Ser Boa para Escrever Programas Descartáveis.

Você sabe o que é um programa descartável: algo que você escreve rapidamente para alguma tarefa limitada. Acho que se você olhasse ao redor, descobriria que muitos programas grandes e sérios começaram como programas descartáveis. Eu não ficaria surpreso se a maioria dos programas começasse como programas descartáveis. E assim, se você quiser fazer uma linguagem que seja boa para escrever software em geral, ela tem que ser boa para escrever programas descartáveis, porque essa é a fase larval da maioria do software.

5. A Sintaxe Está Conectada à Semântica.

É tradicional pensar em sintaxe e semântica como sendo completamente separadas. Isso pode soar chocante, mas pode ser que não sejam. Acho que o que você quer em sua linguagem pode estar relacionado a como você expressa isso.

Recentemente, estava conversando com Robert Morris, e ele apontou que a sobrecarga de operadores é um ganho maior em linguagens com sintaxe infixa. Em uma linguagem com sintaxe prefixada, qualquer função que você define é efetivamente um operador. Se você quiser definir um mais para um novo tipo de número que você inventou, pode simplesmente definir uma nova função para somá-los. Se você fizer isso em uma linguagem com sintaxe infixa, há uma grande diferença de aparência entre o uso de um operador sobrecarregado e uma chamada de função.

1. Novas Linguagens de Programação.

Nos anos 1970 era da moda projetar novas linguagens de programação. Recentemente não tem sido. Mas acho que o software baseado em servidor fará com que novas linguagens voltem a ser da moda. Com software baseado em servidor, você pode usar qualquer linguagem que quiser, então se alguém projetar uma linguagem que realmente pareça melhor do que outras disponíveis, haverá pessoas que correrão o risco e a usarão.

2. Compartilhamento de Tempo.

Richard Kelsey deu isso como uma ideia cujo tempo voltou a chegar no último painel, e eu concordo completamente com ele. Meu palpite (e o palpite da Microsoft, parece) é que muito da computação se moverá do desktop para servidores remotos. Em outras palavras, o compartilhamento de tempo está de volta. E acho que haverá necessidade de suporte para isso no nível da linguagem. Por exemplo, sei que Richard e Jonathan Rees fizeram muito trabalho implementando agendamento de processos dentro do Scheme 48.

3. Eficiência.

Recentemente, estava começando a parecer que os computadores estavam finalmente rápidos o suficiente. Cada vez mais, começávamos a ouvir sobre bytecode, o que implica para mim, pelo menos, que sentimos que temos ciclos de sobra. Mas não acho que teremos, com software baseado em servidor. Alguém terá que pagar pelos servidores que o software roda, e o número de usuários que eles podem suportar por máquina será o divisor de seu custo de capital.

Então, acho que a eficiência importará, pelo menos em gargalos computacionais. Será especialmente importante fazer I/O rapidamente, porque aplicações baseadas em servidor fazem muito I/O.

Pode ser que o bytecode não seja um ganho, no final. A Sun e a Microsoft parecem estar se enfrentando em uma espécie de batalha de bytecodes no momento. Mas estão fazendo isso porque o bytecode é um lugar conveniente para se inserir no processo, não porque bytecode é em si uma boa ideia. Pode ser que esse todo campo de batalha seja contornado. Isso seria meio engraçado.

1. Clientes.

Isso é apenas um palpite, mas meu palpite é que o modelo vencedor para a maioria das aplicações será puramente baseado em servidor. Projetar software que funcione na suposição de que todos terão seu cliente é como projetar uma sociedade na suposição de que todos serão apenas honestos. Certamente seria conveniente, mas você tem que supor que isso nunca acontecerá.

Acho que haverá uma proliferação de dispositivos que têm algum tipo de acesso à Web, e tudo o que você poderá supor sobre eles é que podem suportar HTML simples e formulários. Você terá um navegador em seu celular? Haverá um telefone em seu palm pilot? Seu blackberry terá uma tela maior? Você poderá navegar na Web em seu gameboy? Em seu relógio? Não sei. E não preciso saber se apostei em tudo estar apenas no servidor. É muito mais robusto ter todos os cérebros no servidor.

2. Programação Orientada a Objetos.

Eu percebo que isso é uma questão controversa, mas não acho que a programação orientada a objetos seja um grande problema. Acho que é um bom modelo para certos tipos de aplicações que precisam desse tipo específico de estrutura de dados, como sistemas de janelas, simulações e programas CAD. Mas não vejo por que deveria ser o modelo para toda programação.

Acho que parte da razão pela qual as pessoas em grandes empresas gostam de programação orientada a objetos é porque ela gera muito do que parece trabalho. Algo que poderia ser naturalmente representado como, digamos, uma lista de números inteiros, agora pode ser representado como uma classe com todo tipo de andaimes e agitação.

Outra atração da programação orientada a objetos é que os métodos lhe dão parte do efeito de funções de primeira classe. Mas isso é notícia velha para programadores de Lisp. Quando você tem funções de primeira classe reais, pode usá-las da maneira que for apropriada para a tarefa em questão, em vez de forçar tudo em um molde de classes e métodos.

O que isso significa para o design de linguagens, eu acho, é que você não deve construir a programação orientada a objetos de forma muito profunda. Talvez a resposta seja oferecer coisas mais gerais e subjacentes, e deixar as pessoas projetarem quaisquer sistemas de objetos que desejarem como bibliotecas.

3. Design por Comitê.

Ter sua linguagem projetada por um comitê é uma grande armadilha, e não apenas pelas razões que todos conhecem. Todos sabem que comitês tendem a produzir designs irregulares e inconsistentes. Mas acho que um perigo maior é que eles não correrão riscos. Quando uma pessoa está no comando, ela pode correr riscos que um comitê nunca concordaria.

É necessário correr riscos para projetar uma boa linguagem, no entanto? Muitas pessoas podem suspeitar que o design de linguagem é algo onde você deve se manter bastante próximo da sabedoria convencional. Aposto que isso não é verdade. Em tudo o que as pessoas fazem, a recompensa é proporcional ao risco. Por que o design de linguagem deveria ser diferente?