Quinta-feira, Março 18, 2010

Interface Programador-Máquina

Ouvi algo interessante em uma aula do curso 6.00 do MIT, vendo o vídeo no celular, sobre a sobrecarga de operadores; o professor argumentava que essa era uma carecterística boa da linguagem de programação porque permitia uma interface consistente de programação.

Esse é um uso interessante das palavras; em geral, dizemos interface para nos referir a um contrato de comunicação entre dois pedaços de código executável.

Realmente, da mesma forma como essa representação é um contrato ou protocolo entre dois pedaços de código executável que se comunicam, também há contrato ou protocolo entre quaisquer duas coisas que se comunicam, como por exemplo o programador e a máquina.

Isso nos leva a pensar na linguagem de programação, como regra de sintaxe e semântica, como uma interface; e em pensar na qualidade de uma linguagem de programação como a qualidade dessa interface.

O meta-caso-de-uso que essa interface pretende realizar é "expressar o programa que eu tenho em mente"; o componente que implementa essa interface é o compilador. Realmente é o compilador, e não a máquina física; o compilador, sob essa ótica, é a máquina abstrata, que interpreta a expressão do programa e faz algo de útil. De fato, normas como C e C++ descrevem o efeito do programa sobre uma máquina abstrata.

Então, o que há com y + x ?

Há interface de alta qualidade na medida em que + significa o que você aprendeu ao longo de uma década de ensino de aritmética. Este julgamento fundamenta ambos os lados da divergência sobre se este símbolo deve ou deve não ser sobrecarregado para significar "concatenar duas strings". O lado deve entende que qualquer indivíduo compreende + como "juntar", "unir", "somar". O lado deve não entende que concatenar é "pôr um na frente do outro", que não possui a propriedade de associatividade.

O tema da aula no vídeo que eu estava assistindo era classes em Python e uma introdução aos abstract data types. Acho essa discussão pertinente porque ADTs são um conceito de meta-linguagem, e um ADT existe apenas na mente do programador. Faço essa distinção como a distinção entre o conjunto dos inteiros de que trata a álgebra e o tipo int da linguagem de programação.

Quando o programador representa um ADT na linguagem de programação como uma classe, ele por sua vez oferece a outro programador uma interface de programação. O usuário do ADT, por assim dizer, escreverá programas que dissertam sobre esse ou aquele valor. Assim, eu concordo com o professor: se eu estou descrevendo um ADT numérico, é muito conveniente poder sobrecarregar o símbolo + e permitir aos meus usuários falar sobre coisas na forma de y + x .

Agora, há algo de estético nessa história toda. Suponha que por qualquer motivo você não pode usar o símbolo + . Que nome você escolheria, add ou sum? Ou plus? add tem algo de imperativo, enquanto sum é um substantivo; ambos sugerem uma leitura diferente da expressão; e plus é apenas o nome de um símbolo!

  add(y, x) // add y to x


  sum(y, x) // the sum of y and x


  plus(y, x) // y plus x

O Elements of Programming argumenta que o projetista de um ADT deve se esforçar para determinar uma "base computacional" para o ADT, um conjunto mínimo de operações básicas e eficientes que permitem ao programador expressar todos os programas úteis possíveis que discursam sobre seus valores.

Este é o aspecto aritmético de uma interface programador-máquina, por assim dizer; uma boa escolha de nomes é seu aspecto estético, talvez. Parte do processo de decifragem ou aprendizagem de um sistema -- rotina de um arqueólogo de sistemas legados -- é justamente aprender os símbolos na caótica cultura desse sistema, que podem ou não fazer sentido como se espera de um sistema "fresquinho".

Parte do esforço hercúleo em se convencer de um teorema de matemática avançada é justamente ler a notação simbólica usada -- que, sendo altamente abstrata, é frequentemente irreprodutível em linguagem natural. (E às vezes a diferença entre um signo e outro é meia dúzia de três ou quatro pixel.)

Produzir uma interface programador-máquina eficiente é sempre bom, mas programadores em execesso usam a eficiência como desculpa para produzir interfaces incompreensíveis. E no fim das contas todos nós sabemos que o custo de um projeto de sistema convencional é dominado por seu custo de manutenção.

0 comentários: