Gambiarras com nomes

Quando se está projetando uma linguagem de programação nova, é preciso ter um objetivo principal, um tema, em mente. Você pode querer que sua linguagem proporcione diversão, leve uniformidade e simplicidade extremamente a sério ou que sirva de base para o que houver de mais moderno em termos de pesquisa em linguagens de programação. O número de escolhas possíveis é estonteantemente grande, mas uma coisa é certa: não se pode ter tudo ao mesmo tempo. Não dá para incluir todos os recursos que puder imaginar na sua linguagem nova porque ela seria muito difícil de aprender.

Então nos fim das contas, é preciso escolher o que entra e o que fica de fora. Algumas coisas que ficaram de fora podem ser incluídas em bibliotecas e outras publicadas em artigos e livros e chamadas de padrões de projeto. Os padrões precisam existir porque nenhuma linguagem é a melhor alternativa para todos os trabalhos. Por causa disso as pessoas acabam inventando pequenas gambiarras para resolver alguns problemas comuns que a linguagem não resolveu. A cultura da linguagem influencia as pessoas quando estão bolando essas gambiarras e assim os padrões surgem em várias equipes independentemente.

Um padrão não é nada mais que uma gambiarra para contornar fraquezas de algumas linguagens. Estas fraquezas são completamente naturais. Não se espera que toda linguagem consiga dar suporte a todo tipo de construção, mas que seja boa naquilo a que se propõe. Já que não há como ter suporte direto a tudo que se possa pensar, as pessoas começam a criar construções padronizadas para cada tipo de trabalho. Estas construções são os padrões.

Antes da orientação a objeto tornar-se a panacéia que é atualmente e ser requisito primordial para toda e qualquer linguagem de largo uso, ela já era utilizada na forma de padrões em linguagens como C. Uma das formas de se fazer isso era ter uma estrutura de dados para armazenar os valores dos atributos e os endereços para o código executável das funções que operavam sobre os atributos (os famigerados métodos). Deste modo os dados e as operações sobre eles ficam agrupados, exatamente como nos nossos objetos de hoje. Quando alguém queria executar uma operação sobre um objeto bastava usar o endereço de memória indicado nele próprio. Com esta organização ainda é possível ter coisas como herança e classes abstratas. Este padrão é bem interessante se você quiser desvendar como seu código orientado a objeto é executado pela máquina, mas o objetivo deste artigo não é ensinar como fazer objetos em C e quem estiver interessado em mais detalhes pode dar uma olhada no artigo do Mark Dominus.

Se o termo fosse tão popular na época quanto é hoje, essa construção poderia muito bem ter sido classificada como padrão de projeto. Ela não teve esta honra, mas foi tão aceita e utilizada que acabou sendo incorporada em linguagens posteriores, como C++ e Java. Com estas novas linguagens não era preciso lembrar de construir a estrutura de dados ou evitar utilizar os membros tidos como privativos, tudo isto podia ser controlado automaticamente pelos compiladores e interpretadores. Quando uma linguagem incorpora alguma construção, as pessoas começam a pensar de forma mais abstrata e acabam surgindo novos padrões sobre os antigos. De fato, seria difícil imaginar que teríamos padrões como o Visitor ou o Iterator hoje se ainda precisássemos nos preocupar em controlar ponteiros de funções dentro de estruturas de objetos.

No entanto, os padrões são aplicáveis a linguagens específicas. O caso dos Iteradores1 é bem interessante. Eles são uma solução para o problema de executar um determinado trecho de código (uma função) sobre todos os elementos de algum tipo de recipiente. Em linguagens funcionais, como Haskell, este problema não é nem um problema porque um de seus principais propósitos é permitir tratar funções como cidadãos de primeira classe e possibilitar passá-las de um lado para o outro como qualquer outro valor. Iteradores também desaparecem na maior parte das linguagens que suportam blocos anônimos, como Ruby. Se alguém quiser muito, pode até usar um Iterador em Ruby, mas não há nenhum motivo para fazer isso quando pode-se usar blocos anônimos. Estas linguagens eliminam a necessidade deste padrão porque ele pode ser incorporado à linguagem na forma de bibliotecas.

Algumas linguagens possuem mesmo esta capacidade de permitir que os padrões sejam escritos apenas uma vez e reutilizados muitas outras. Deve ser por isso que Paul Graham parece não gostar de padrões. Ele é um programador Lisp e o modo de se fazer um programa Lisp é inventar um dialeto (essencialmente uma linguagem nova) e utilizá-lo (junto com um monte de parênteses) para resolver o problema. Os padrões acabam sendo incorporados ao novo dialeto durante seu desenvolvimento e não faz muito sentido catalogar esses padrões se eles já estão codificados. Inventar uma linguagem nova para cada problema pode parecer exagero e realmente é, se a linguagem base não tiver sido projetada para isso. Mas Lisp foi e não há nada mais natural para um programador Lisp do que fazer um pequeno dialeto.

Enquanto existirem computadores para serem programados, isso vai continuar a acontecer. As melhores gambiarras vão ser chamadas de padrões e os melhores padrões serão incorporados a novas linguagens, tornando-se invisíveis ou desnecessários. Foi assim que aconteceu com chamadas de subrotinas, classes, objetos e outras várias construções que hoje achamos extremamente naturais. O melhor de tudo é que esta evolução toda nos permite pensar cada vez mais longe da máquina e de forma mais natural. Assim podemos manter o ciclo inventando novas gambiarras que podem se tornar novos padrões que por sua vez podem ser incorporados a novas linguagens.

Padrões são gambiarras, mas não são como qualquer gambiarra. O que realmente diferencia um padrão de projeto das demais gambiarras é o fato de ter um nome. Os nomes dos padrões permitem que os programadores se comuniquem mais eficientemente. Eles podem se referir às gambiarras pelo nome, ao invés de dizer “acho que aqui podemos usar uma gambiarra que eu vi em outro sistema” e depois precisar de um bom tempo para explicar.

A maior força dos padrões é também sua maior fraqueza. Um vocabulário rico ajuda muito os experientes, mas pode atrapalhar os novatos. Para começar a programar sério em uma linguagem onde toda solução precisa a ser repleta de convenções e padrões, não basta aprender somente a linguagem base: é preciso aprender também todo um vocabulário de padrões. Mais ou menos como aprender um segundo idioma não é só estudar a gramática para formar frases estruturalmente corretas, mas também manter-se em contato com o idioma a fim de incrementar o vocabulário e aprender como os nativos falam para evitar soar como um tradutor automático.

1. Iterador é o nome que uso em português para Iterator, caso você esteja caindo do septuagésimo-terceiro andar da Torre de Babel e ainda não tenha ligado o nome à pessoa

3 Responses to “Gambiarras com nomes”


  1. 1 Marcos Tapajos 11/mar/2007 às 02\0246

    Thiago, parabéns pelo post, achei ótimo e refletiu muito o que eu penso e por isso escrevi um post no blog da empresa onde tomei a liberdade de citar seu post e um paragrafo especifico dele.
    Mas claro que dei os devidos créditos ao verdadeiro autor !

    Um abraço
    Tapajós

  2. 2 Vinicius AC 26/abr/2007 às 21\0938

    Parabéns pelo post. Muito bem escrito e interessante.
    Me fez pensar agora e, o mais importante, vai me fazer pensar de forma bem mais crítica quando estudar/usar padrões.
    Agradeço,
    ViniciusAC.


  1. 1 CMilfont » Padrões não são gambiarras Trackback em 12/mar/2007 às 18\0651
Comments are currently closed.




%d blogueiros gostam disto: