PROGRAMACION MODULAR CON JAVASCRIPT

<script src=”other pages” title=”programacion modular con javascript”>

Javascript es un lenguaje de scripting, útil para hacer ciertas tareas que corresponden a un contexto determinado, que en este caso corresponde al Navegador Web. Las páginas y aplicaciones web dependen en mayor o menor medida de él, pero [casi] siempre lo vamos a necesitar (por ahora…). Pero, al ser un lenguaje de script, una arquitectura modular era impensable en Javascript.

¿módulos en Javascript? Imposible…

Afortunadamente, los tiempos cambian, y con la implementación actual de Javascript 5.1 (y futuras implementaciones como Harmony a finales de Mayo en Junio de este año 😀 ) es posible tener una arquitectura modular como flujo de trabajo en aplicaciones Web. El ejemplo más común de esto es el ecosistema de aplicaciones y librerias que conviven bajo Node.js. Aún sin depender tanto de él, podemos escribir nuestros propios módulos en Javascript, pero ¿qué es un módulo? Veamos:

“En software, un módulo [puede ser] parte de un programa. Dichos programas [pueden estar] compuestos por uno o más módulos desarrollados independientemente, pero éstos no son conocidos por el programa hasta que son [combinados o] enlazados. Un módulo puede contener una u varias rutinas de código”

Traducido desde webopedia.com

Para ejemplificar esto, es típico en las páginas o aplicaciones web que los scripts estén instanciados uno a uno en orden para realizar determinadas funcionalidades:

<!DOCTYPE html>
<html>
    <head>
        <title>Ejemplo</title>
        <script src="assets/js/uno.js"></script>
        <script src="assets/js/dos.js"></script>
        <script src="assets/js/tres.js"></script>
        <script src="assets/js/cuatro.js"></script>
        <script src="assets/js/cinco.js"></script>
    </head>
    <body>
        <!--Cuerpo de la página-->
    </body>
</html>

Cada vez que un <script></script> aparezca en el código (que generalmente aparece dentro de <head></head>) es una petición HTTP que debe ser resuelta desde el servidor hacia el navegador. El ahorro en ancho de banda puede ser una muy buena razón para usar módulos en Javascript (pero no es la única razón).

En VanillaJS (o Javascript trocho y mocho, como yo le digo 😛 ), podemos escribir módulos de la siguiente forma:

(function(){
    //hacer cosas de manera global para todos
    //los módulos que instancien este script
}());

Este envoltorio (llamado closure, en inglés) sirve para unificar varias rutinas generales pero no maneja dependencias de otros scripts, y tampoco herencia de módulos. Además de que el módulo es cargado cada vez que se necesite o que aparezca referenciado en una página (carga síncrona).

Pero existen librerías externas que hacen el trabajo por nosotros (gracias a Dios 😀 ), tal es el caso de RequireJS y MelchiorJS, que trabajan con carga asíncrona o AMD (Asyncronous Module Definition).

El principio de AMD se basa en que en vez de resolver una petición HTTP por cada módulo, se pretenda resolver las dependencias necesarias con una sola petición HTTP de la cual se deriven las dependencias de otros módulos, rutinas y variables y se instancien según se necesiten.

En RequireJS, y usando el ejemplo anterior podemos hacer uso de AMD de esta forma:

<!DOCTYPE html>
<html>
    <head>
        <title>Ejemplo</title>
        <!--
        "data-main" es usado por RequireJS para determinar
        la ubicación del script que tiene las dependencias
        a ser cargadas de forma asíncrona por la app
        -->
        <script data-main="assets/js" src="/ruta/absoluta/a/require.js"></script>
    </head>
    <body>
        <!--Cuerpo de la página-->
    </body>
</html>

En MelchiorJS es exactamente igual. La diferencia de ambas librerías está en la definición del script de dependencias que manejarán. En RequiereJS se definen los módulos así:

require(["uno", "dos", "tres", "cuatro", "cinco"],
function(uno, dos, tres, cuatro, cinco){
    //hacer cosas con las dependencias directamente
    //uno.metodo() o cinco.atributo según se necesite
    //todos los scripts se cargan desde assets/js
    //definido en el atributo data-main
});

En MelchiorJS:

melchiorjs.module("mi modulo")
.require("uno")
.require("dos")
.require("tres")
.require("cuatro")
.require("cinco")
.body(function(){
    //hacer cosas con las dependencias directamente
    //uno.metodo() o cinco.atributo según se necesite
    //todos los scripts se cargan desde assets/js
    //definido en el atributo data-main
});

Mientras que RequireJS coloca las dependencias en un Array y se van cargando según se necesiten, en MelchiorJS se encadenan, similar a como si fueran Promesas. Personalmente me inclino por MelchiorJS, porque tiene una aproximación más limpia (en cuanto a sintaxis) de un comportamiento asíncrono de Javascript, sin embargo, el estándar de facto ha sido hasta ahora RequireJS.

Para la nueva versión de Javascript (a.k.a. Harmony) hay varias propuestas de una API que soporte AMD de forma nativa, dichas propuestas están en CommonJS. Pero más allá de ser nuevo, lo importante es que el código sea mantenible, escalable y configurable en la medida de lo posible, sin Panaceas ni magia vudú 😉

BTW: Más info sobre patrones de desarrollo modular y una comparación entre CommonJS vs. RequireJS

Actualizado 22/06/2015: ¡Señoras y señores, el futuro está aquí!

</script>

Anuncios

Un comentario en “PROGRAMACION MODULAR CON JAVASCRIPT

Los comentarios están cerrados.