miércoles, 25 de marzo de 2009

Metaprogramación o DSL con javascript method chaining

Hoy vamos a ver un poco de como crear un mini Lenguaje de dominio especifico (como SQL, o CSS) con javscript de manera facil, rápida, elegante, agil y económica.
Partamos de un problema.
Supongamos que tenemos un select html de paises y solo si elijen eeuu debemos mostrar el select de estados, hariamos lo siguiente (usando la libreria prototype)

Event.observe(window, "load", function() {

Event.observe($("country"), "change", function() {
if ($F("country") == "United States")
$("state-field").show();
else
$("state-field").hide();
});

});

por ahora creanme que Event.observe recibe un objeto del dom, el nombre de un evento, y la funcion a attachear, $ en la lib prototype es un atajo a document.getElementById, $F es un atajo al value de un objeto de formulario, y finalmente se le agregan a los objetos del DOM dos metodos show y hide que simplemente manipulan el valor de display a nivel de css.

lo importante aqui es ver que nuestro limpio codigo puede convertirse en algo mucho mas complicado si varían los requerimientos.

ahora supongamos que agregamos un campo de provincias, que debe aparecer solo cuando elijamos Canada,
y un campo brutus que solo debe aparecer cuando elijamos Michigan u Ohio
el código elegante se empobrece y se torna dificil de leer

Event.observe(window, "load", function() {

Event.observe($("country"), "change", function() {
var country = $F("country");
if (country == "United States") {
$("us-state-field").show();
$("province-field").hide();
} else if (country == "Canada") {
$("province-field").show();
$("us-state-field").hide();
} else {
$("us-state-field").hide();
$("province-field").hide();
}
});

Event.observe($("us-state"), "change", function() {
var state = $F("us-state");
if (state == "Ohio" || state == "Michigan")
$("brutus").show();
else
$("brutus").hide();
});

});



eso sin contar que eredamos un bug que no nos oculta brutus si deseleccionamos estados unidos
Pero eso no es importante, lo importante es ver como la legibilidad del codigo se degrado luego de haber cambiado los requerimientos (cosa que raramente pasa en el mundo real, jajajaja)

Entonces como mejorar esto?
lo mejor es intentar separar el QUE? del COMO?
es decir separar las reglas de lo que tenemos que hacer
de la implementación de como hacerlo.
entonces veamos como creariamos un pequeño lenguaje que nos permita definir esto
para crear un lenguaje vamos a utilizar el lenguaje natural mas parecido al lenguaje del dominio del problema, (pero ahora lo vamos a hacer en ingles).


show us-state when country is “United States”
show province when country is “Canada”
show Brutus when state is “Ohio” or “Michigan”


ahora como convertimos esto en javascript, simple
creando objetos que se encarguen de la implementación teniendo en cuenta el orden de llamadas de metodos


show("us-state-field").when("country").is("United States");
show("province-field").when("country").is("Canada");
show("brutus").when("us-state").is("Ohio,Michigan");


para ver como implementariamos estos metodos los voy a dejar en suspenso hasta un proximo encuentro
ja

fuente
libreria Event.behavior

No hay comentarios:

Publicar un comentario