Kumpera.net delírios sobre linguagens de programação

Meus achados sobre tecnologia

Monkeypatching: gambiarra du-jour

March 3rd, 2008 · 3 Comments

Finalmente o óbvio atingiu a comunidade de desenvolvedores de Ruby. Enfim descobriram que meta-programação sem disciplina é um engôdo. No começo produz resultados fabulosos rapidamente, só que mais adiante se torna um inferno de integração. Não falta gente calejada em Rails para te contar uma miríade de problemas ao integrar frameworks que modificam classes como Object ou Fixnum.

Sistemas grandes e complexos exigem que seus componentes sejam isolados o máximo possível entre si para minimizar a interferência que um pode causar no outro. Em linguagens como Java, com um sistema de tipos simples, normalmente isso se resume a usar interfaces para delimitar fronteiras e protocolos de comunicação inter-módulo. Porém quando temos classes abertas o problema é muito maior, já que o sistema todo pode ser modificado de um único lugar. Permitir que a modificação de classes fundamentais como Kernel em um canto do sistema influencie todo o resto é um sério problema pois fica difícil controlar o estrago que essas mudanças causam.

O problema com Ruby pode ser entendido melhor se olharmos para ele segundo o a classificação de domínios de page-jones. Segundo o mesmo, podemos classificá-los em fundamental, arquitetural, negócios e aplicação; sendo que a especificidade aumenta na mesma ordem. Outro ponto é que o domínio menos específico não deve depender de um mais específico, assim como dependências laterais devem ser evitadas. Por essa ótica, código da aplicação alterando uma classe fundamental do sistema é uma clara violação desse modelo.

O motivo pelo qual Ruby viola o modelo de page-jones é por não ser possível definir um escopo que não seja global para alterações feitas a classes externas a código em questão. Outro problema que agrava a situação é a impossibilidade de realmente controlar o mecanismo de resolução de nomes de um bloco de código, isso é um grande problema para criação de DSLs que acabam por fazer enormes cirurgias no core da linguagem ou apelam para o monkeypatching, uma “solução” muito menos intrusiva.

Existem duas formas de ser realizar meta-programação; uma é a intrínseca, a qual se permite operar sobre a definição dos tipos e, uma vez feita a alteração, ela é visível a todos usuários do dado tipo, podemos dizer também que é meta-programação no ponto de definição; a outra é a extrínseca, na qual se altera o mecanismo de resolução de nomes para um dado corpo de código, isso permite realizar as mesmas operações que o método anterior, porém todo código precisa informar direta ou indiretamente se existe algo alterando tal mecanismo, podemos dizer também que é meta-programação no ponto de uso.

A vantagem do primeiro é simplicidade e alcance, uma vez feita a modificação nada mais precisa ser feito para sua aplicação utilizar a versão modificada do tipo, porém também é sua fraqueza, pois se uma função depender explicitamente do comportamento anterior ela não mais funcionará - Ruby é um ótimo exemplo de meta-programação intrínseca. Já a segunda técnica é quase o oposto, pois exige que as modificações sejam explicitamente ativadas, que é sua principal vantagem, pois permite facilmente compor conjuntos de alterações e restringir seu escopo, em contrapartida é sua fraqueza pois não permite que uma dada alteração seja definida por completo em um único lugar - extension methods do C# 3.0 é um exemplo simples de meta-programação extrínseca.

Tentar comparar ambas as técnicas e concluir qual a melhor é um exercício fútil, pois sempre existirão fartos casos no qual uma falha e a outra brilha. Assim como achar que Ruby é uma linguagem quebrada por possuir seus defeitos, pois apesar de tudo é um modelo ao mesmo tempo muito rico e simples de usar.

Tags: Programming · java · language design · ruby

3 responses so far ↓

  • 1 Phillip Calçado "Shoes" // Mar 3, 2008 at 6:50 pm

    Boa sacada sobre como não ter opções decentes de eval() afetam domínios.

  • 2 Edson Watanabe // Mar 31, 2008 at 1:54 pm

    Parece que a discussão sobre “monkey patching is harmful” está popular. O blog do Gilad Bracha está falando sobre isso também.
    http://gbracha.blogspot.com/2008/03/monkey-patching.html

  • 3 Aquila // Aug 14, 2008 at 5:34 pm

    Olha eu de novo.
    Mais uma vez o Ruby é um linguagem simplificada e mt eficiente tem varios problemas mais é uma linguagem que precisa ser amadurecida,
    se você é desenvolvedor em uma linguam seja ela “Cliper” (atualize - se imediatamente) mantenha sua logica e capacidade de desenvolver com ela por mais limitada que ela seja.

    Bons desenvolvedores são aqueles que fazem coisas que a linguagem não mostra explicitamente como é que funciona, eles as criam, programadores apenas pegam e as executam.
    se funcionar
    begin
    print : muito bom
    end
    se não
    begin
    print : Fazer o quê né!!!!
    end

Leave a Comment