Publicidad

sábado, 4 de octubre de 2008

La metaprogramación

Como no podia entrar al blog no habia subido nada pero ya lo logre, bueno encontre esta nota y me parecio interesante ponerla en el blog es sobre la metaprogramación, espero y les guste sale:
Nota: no se ven todas las funciones del editor y del blog no se por que pero la subo asi:

La metaprogramación es una técnica muy poderosa, y muy socorrida en el terreno de los lenguajes dinámicos. Puede llevarnos a reducir muy fuertemente el total de código que escribimos - Y lo que es mucho más importante, a minimizar la cantidad de código repetido innecesariamente. Nos lleva claramente a aumentar la calidad y mantenibilidad de nuestro código.

Programas que escriben programas

La metaprogramación consiste en escribir código que no ataca directamente al dominio del problema que queremos atacar, sino que al código que lo resolvería. Dicho sea de otro modo, el código que escribimos no modifica los datos o el estado de nuestra información, sino que el del programa.

Las ventajas de los lenguajes dinámicos
La metaprogramación no es una nueva idea - Nació hace ya más de 40 años, con el lenguaje Lisp, y se popularizó tremendamente en el lenguaje Smalltalk, a principios de los 80.

Ambos lenguajes fueron revolucionarios en diversos aspectos, y si no gozan hoy en dí­a de mayor popularidad, se debe a que, en sus implementaciones originales sufrí­an de problemas de rendimiento en el hardware de su época. Sin embargo, sus ideas básicas han servido para conformar a una gran cantidad de lenguajes que han ido adquiriendo una cada vez mayor popularidad y aceptación: Los lenguajes dinámicos.

Podemos categorizar a un lenguaje de dinámico cuando no requiere de ciclos determinados y claramente separados de compilación y ejecución. Mucha gente cree erróneamente que los lenguajes dinámicos (por ejemplo, Perl, Ruby, Python o PHP, ampliamente utilizados en el mundo del Software Libre) son interpretados - La realidad es completamente distinta, son lenguajes que cuentan con compiladores tremendamente eficientes, que en fracciones de segundo pueden convertir decenas de miles de ­líneas de código en una representación binaria (bytecode para sus respectivas máquinas virtuales).

La caracterí­stica definitoria de estos lenguajes como dinámicos no es el compilador ágil (aunque, claro está, lo requieren) - Es la presencia de la instrucción (o familia de instrucciones) «eval». En resumidas cuentas, eval recibe un parámetro, tí­picamente una cadena, y lo evalúa como código fuente - Como una primer probadita de metaprogramación, consideren el siguiente código de Ruby:

def crea_clase(nombre, clase_padre)
eval "class #{nombre} < #{clase_padre} ; end"
end

Al invocar a este método -claro está, en tiempo de ejecución- puedo ampliar la jerarquí­a de clases existente. Por ejemplo, si quiero definir suficientes clases para representar los muebles de una oficina, podrí­a decirle a Ruby:

['Mesa', 'Silla', 'Archivero', 'Librero'].each do |tipo|
crea_clase(tipo, 'Mueble')
end

Obviamente, la lista de objetos no necesariamente la tengo representada en mi código fuente - puede ser proporcionada por el usuario o determinada a partir del entorno de ejecución. Y a partir de este punto, para todos los propósitos de nuestro código, sería como si en tiempo de compilación hubiéramos incluido explí­citamente en el código:

class Mesa < Mueble; end
class Silla < Mueble; end
class Archivero < Mueble; end
class Librero < Mueble; end


Pero esto va mucho más allá de una manera cómoda y reducida de especificar clases.

Lenguajes específicos de dominio
A partir del número noviembre-diciembre de 2007 de SoftwareGurú hemos recibido entregas del tutorial de Ruby on Rails escrito por Carlos Ortega. Cuando nos acercamos por primera vez a Rails, lo primero que encontramos es una serie de declaraciones que no pertenecen a Ruby, y aparentan un estilo de programación declarativo. Por ejemplo, al definir un modelo:

class Person < ActiveRecord::Base
validates_presence_of :name
validates_numericality_of :age, :greater_than => 0, :less_than => 100
end

ActiveRecord es el ORM de Ruby on Rails - presenta una abstracción de los datos en las tablas de la base de datos, dándoles una interfaz natural orientada a objetos. El módulo ActiveRecord::Validations::ClassMethods extiende al lenguaje a través de la metaprogramación, y expone una serie de validadores, que presentan una sintaxis natural de escribir y fácil de leer - Un lenguaje especí­fico al dominio de las validaciones.

Reflectividad
La mayor parte de los lenguajes dinámicos son también reflectivos. Los objetos (y, recuerden, en los lenguajes completamente orientados a objetos, todo es un objeto - Incluyendo las clases, no sólo los objetos instanciados) pueden ser interrogados respecto a los métodos que ofrecen. Un ejemplo simple que muestra el poder combinado de la reflectividad junto con la metaprogramación es este simple rastreador universal:

def trace(obj)
obj.methods.each do |meth|
eval "def obj.#{meth}(*args)
warn 'Llamando al método #{meth} en #{obj.class}'
super(*args)
end"
end
end


Basta llamar a nuestra función «trace» con cualquier objeto del sistema para que nos muestre un rastreo completo de cada una de las acciones que éste realice. Por ejemplo (desde la consola interactiva de Ruby):

>> p = Person.find(:first)
>> trace(p)
>> p.name
Llamando al método method_missing en Person
Llamando al método class en Person
Llamando al método class en Person
Llamando al método class en Person
Llamando al método send en Person
=> "Fulano D. Tal"


Aquí podemos encontrar cómo es que incluso la misma clase Person (que no es otra que la que declaramos hace algunas líneas) recibe sus métodos: ¡A través de la reflexibilidad, preguntándole a la base de datos acerca de su propia estructura!

El espacio no permite, tristemente, dar más ejemplos de cómo podemos explotar estas técnicas - Pero espero que con esta sencilla muestra puedan comprender la riqueza que esta técnica nos proporciona, y lo conciso que puede hacer a nuestro código.

Acerca del autor
Gunnar Wolf ha sido usuario y promotor de Software Libre en México por más de diez años. Es fundador del Congreso Nacional de Software Libre (CONSOL) y miembro externo del Departamento de Seguridad de Cómputo en la UNAM. Participa como desarrollador en el proyecto Debian desde el 2003. Trabaja como administrador de red y en el desarrollo de sistemas para el Instituto de Investigaciones Económicas de la UNAM.

1 comentario:

Bret Cohen dijo...

Me inspiraste tanto con está entrada que yo escribí una entrada sobre el mismo tema.

Ahora veo que lo que Gunar Wolf se llama metaprogramación no refiere meramente a un programa que escribe otros programas, pero tambien a un programa que es ejecutado diferentemente depende de las accienes de un usuario o el eterno de ejecución. En este caso, no es diferente que cualquier otro programa interactivo. Vé a mi entrada.