8663-Texto Del Artículo-42854-1-10-20150906

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 13

ISSN: 2344-8288 Volumen 1 No.

1 – Enero-Julio de 2014 – Revista TIA - Aplicaciones Modulares en JavaScript   17

Aplicaciones Modulares en JavaScript

Modular Applications in JavaScript

Resumen

La creciente popularidad de JavaScript en los últimos


años y los mitos que aún se tienen sobre él, fueron
las motivaciones para escribir el presente artículo,
Luis Daniel Esteban Puerta Ortiz -
cuyo objetivo es demostrar que en este lenguaje es
[email protected] posible crear aplicaciones complejas, mantenibles y
con capacidad de evolucionar mediante módulos
reutilizables. Para esto se realizó una revisión de
Luis Felipe Becerra Arias - algunas de las formas como se pueden definir
[email protected] módulos en JavaScript, tomando como base
conceptual las principales características de los
sistemas modulares y del mismo lenguaje a la luz de
Universidad Distrital Francisco José de los lenguajes de scripting. Finalmente se identificó
Caldas que tal definición de módulos está en proceso de
estandarización.
Tipo: Artículo de Investigación
Palabras clave: componente, JavaScript, lenguajes
Para citar este artículo: Puerta Ortiz D.E. basados en objetos, lenguajes de scripting, modelos
& Becerra Arias L.F. (2014) Aplicaciones de componentes, módulo.
Modulares en JavaScript. Revista TIA, pp
17-29. Abstract

Fecha de recepción: 05 de noviembre de The growing popularity of JavaScript in recent years


2014 Fecha de aceptación: 05 de junio de and the myths that still exist related with him, were
2014 the motivations for writing this article , which aims
to shown that it is possible to create complex and
Revista  Digital  TIA   maintainable applications with capacity to evolve
through reusable modules. For this reason was
Tecnología  Investigación  y  Academia  
realized a review of the forms for define modules in
  JavaScript, taking as conceptual bases the main
 
characteristics of modular systems and of the same
language in the light of scripting languages. Finally
was identified that such definition of modules is in
the standardization process.

Key words: component models, component,


JavaScript, module, object-based languages,
scripting languages.

http://revistas.udistrital.edu.co/ojs/index.php/tia      
ISSN: 2344-8288 Volumen 1 No. 1 – Enero-Julio de 2014 – Revista TIA - Aplicaciones Modulares en JavaScript   18

Ranking RedMonk
I. Introducción

Durante los últimos años los denominados lenguajes


de scripting han estado ganando popularidad entre
los desarrolladores, como se puede evidenciar en el
sitio web IEEE SPECTRUM que a mediados de julio
del 2014 publicó una lista con los lenguajes de
programación más populares, basándose en métricas
tomadas de sitios como Google, Xplore, Github y
por supuesto la IEEE. [1].

Como se puede apreciar en la figura 1, a pesar de


que los lenguajes tradicionales la encabezan, el
quinto puesto es ocupado por Python, seguido de
JavaScript, PHP y Ruby en los siguientes puestos. Figura 2. Ranking RedMonk.
Otra prueba de la popularidad de estos lenguajes se
encuentra en la medición realizada por RedMonk Finalmente, el sitio TIOBE que realiza mediciones
(figura 2) que correlaciona las discusiones acerca del de popularidad cada mes basado en motores de
tema en Stack Overflow y el uso de los mismos búsqueda como Google, Amazon, Wikipedia,
manifestado en GitHub; JavaScript es el lenguaje Yahoo, Bing y Baidu, para el mes de abril del 2014
más popular seguido muy de cerca por Java. PHP ubica a Java de nuevo en el primer lugar y hasta el
ocupa el tercer puesto, Python el cuarto y Ruby se sexto, séptimo y octavo puesto encontramos a
ubica en el quinto lugar. [2] JavaScript, PHP y Python respectivamente. [3] Sin
embargo, sigue siendo evidente que los lenguajes de
scripting están cobrando fuerza y no es difícil
Ranking IEEE SPECTRUM encontrarlos entre los primeros diez puestos de la
mayoría de mediciones de este tipo, y es aún más
evidente que JavaScript se está convirtiendo en uno
de los lenguajes de programación más usados, a
pesar de que durante algún tiempo se consideraba
como un intermediario entre la interfaz de usuario y
lenguajes de servidor (PHP, Java, etc.).

Con el tiempo y la aparición de herramientas como


Node.js las capacidades de JavaScript se han
ampliado, hasta posibilitar la construcción de
aplicaciones completamente desarrolladas en él. A
pesar de esto y gracias a las malas prácticas de
desarrollo, aún existe la creencia de que no es útil
para realizar productos de software de gran tamaño,
lo que es una motivación para analizar de qué
manera se pueden definir módulos reutilizables en
este lenguaje que simplifiquen la complejidad de
aplicaciones grandes y que faciliten su
mantenimiento y evolución. Con este objetivo se ha
Figura 1. Ranking IEEE SPECTRUM, [1] organizado el artículo de la siguiente manera. La
sección Sistemas modulares, tratará los conceptos de
módulos, componentes y aplicaciones o sistemas
modulares; la sección JavaScript, un lenguaje de
scripting definirá a JavaScript desde el punto de vista
de los lenguajes de scripting y la sección; la sección
Definición de módulos en JavaScript mostrará cómo

http://revistas.udistrital.edu.co/ojs/index.php/tia      
ISSN: 2344-8288 Volumen 1 No. 1 – Enero-Julio de 2014 – Revista TIA - Aplicaciones Modulares en JavaScript   19

se pueden crear aplicaciones modulares utilizando (GRASP) alta cohesión y bajo acoplamiento [6]. La
herramientas como CommonJS, AMD y Servicios cohesión tiene relación con la estructura interna de
Web en JavaScript. los módulos, cuyos elementos deben estar
estrechamente relacionados y tener un objetivo
II. Sistemas modulares común. El acoplamiento tiene que ver con la relación
entre módulos de tal manera que la dependencia
En esta sección se definirán los sistemas modulares entre estos sea mínima [4]. De esta forma se
como sistemas de software mantenibles con garantiza que los módulos puedan ser agregados,
capacidad de evolucionar. retirados y modificados sin que haya un impacto
negativo en el sistema (figuras 3 y 4).
Los sistemas modulares y la ingeniería de software
basada en componentes (CBSE) surgen de la Representación gráfica de la baja cohesión y el
necesidad de constituir una ingeniería de software alto acoplamiento
madura, donde existan unidades funcionales que
puedan ser reutilizadas en la construcción de
sistemas de software con el fin de disminuir
esfuerzos, costos y otros recursos, emulando lo que
ocurre en otras ingenierías como la civil o la
electrónica. Dichas unidades funcionales se conocen
como módulos o componentes, tienen una
funcionalidad determinada y pueden integrarse para
conformar sistemas más complejos, como si de
ladrillos de un edificio se tratase.
Figura 3. Baja cohesión y alto acoplamiento [4]
Estos sistemas pueden ser creados con un enfoque de
abajo hacia arriba (bottom-up), donde se desarrollan Representación gráfica de la alta cohesión y el
primero los componentes y más adelante se bajo acoplamiento
combinan para generar el sistema [4]. Este método se
llama “composición” y es apropiado para trabajar
con modelos de proceso iterativos e incrementales,
tanto así que incluso existen métodos para mapear
requerimientos a componentes, como se evidencia en
[5], donde cada nueva iteración significa una
aproximación más cercana al sistema final (principio
del incremento) [5]. Sin embargo, también pueden
construirse por medio de un enfoque de arriba hacia
abajo (top-down) llamado “descomposición”, donde Figura 4. Alta cohesión y bajo acoplamiento [4]
primero se planifica el sistema y cómo interactúan
sus componentes antes de entrar a desarrollar cada
uno de manera individual [5]. En este enfoque se ve
cada módulo como una caja negra donde se ignoran En términos generales los componentes o módulos
sus detalles internos y solo se tiene en cuenta lo que dotan a los sistemas de software o aplicaciones la
requieren para funcionar y los servicios que proveen, capacidad de mantenerse, adaptarse al cambio y
de tal manera que puedan intercomunicarse. evolucionar sin importar su complejidad. Por lo tanto
en la sección IV se mostrará cómo crear este tipo de
Además los módulos o componentes deben estar en elementos en JavaScript.
capacidad de integrarse con nuevos componentes
provenientes de librerías y aplicaciones de terceras II. JavaScript, un lenguaje de scripting
partes, ser integrados en sistemas diferentes para el
que fueron creados o integrarse con otros En esta sección se definirá JavaScript con base en los
componentes para conformar un componente lenguajes de scripting.
compuesto. Para esto es necesario que se apliquen
los patrones de separación de responsabilidades Existen muchas dudas sobre las características que
debe tener un lenguaje de programación para ser

http://revistas.udistrital.edu.co/ojs/index.php/tia      
ISSN: 2344-8288 Volumen 1 No. 1 – Enero-Julio de 2014 – Revista TIA - Aplicaciones Modulares en JavaScript   20

lenguaje de scripting. Esto se debe a que los ejecutables llamado script”. Esto significa que sin
recientes avances tecnológicos han desvanecido aún importar si el lenguaje es compilado, interpretado,
más la frontera entre los lenguajes tradicionales y orientado a objetos, procedimental, manejado por
dichos lenguajes. Hace una década esta tarea de una máquina virtual, con asignación de tipos de
taxonomía era menos compleja, los lenguajes datos dinámicos o estáticos, es posible realizar
tradicionales como C o Java eran propicios para el scripts.
desarrollo de aplicaciones o componentes y los de
scripting servían como intermediario, como una JavaScript es uno de los denominados lenguajes de
herramienta auxiliar que por su flexibilidad eran scripting (PHP, Perl, Ruby, Python, VBScript, etc.)
idóneos para unir componentes o en el caso de al que más se le ajusta esta definición por la forma
JavaScript contener pequeñas lógicas de negocio como fue sido utilizado durante muchos años y que
como validación de formularios, controles de poco a poco ha ido quedándose atrás a medida que
interfaz, etc. Ahora es posible crear aplicaciones su popularidad crece. Esto se debe a la también
completas y complejas con solo estos lenguajes, creciente popularidad de internet (al ser un lenguaje
llegando a competir con los tradicionales y principalmente desarrollado para aplicaciones Web)
alcanzando popularidad entre los desarrolladores, y según [10], al esfuerzo de los proveedores de
por lo que categorizarlos es una tarea más difícil. navegadores de crear motores de procesamiento más
Según [7], los lenguajes de scripting son potentes, junto con la posibilidad de crear
interpretados en lugar de compilados, las variables aplicaciones del lado del servidor con Node.js (Que
no necesitan ser declaradas y tienen una asignación funciona con el motor V8), además de robustecer la
de tipos dinámica en lugar de estática. Sin embargo, funcionalidad del lado del cliente con la llegada de
con el surgimiento de la compilación JIT (Just in frameworks como JQuery que suavicen las
Time) los lenguajes de programación compilados diferencias entre navegadores y AngularJS que den
pueden tener una flexibilidad similar a los que no lo una estructura al código siguiendo el patrón MVC.
son y en algunos lenguajes de programación
tradicionales, como Java, es posible la asignación de Esto ha propiciado que JavaScript llegue a terrenos
tipos de datos como si de objetos se tratasen (en insospechados como al de las aplicaciones móviles
algunos casos Java es considerado como un lenguaje mediante Phonegap, que en combinación con JQuery
de scripting). Mobile y Sencha pueden tener interfaces responsivas
que incluso parecen nativas al manejo de sistemas
Por otro lado, en [8] se presentan como embebidos (Arduino) y la creación de aplicaciones
características de los lenguajes de scripting, la Stand-alone por medio de NodeWebkit.
utilización de tipos de datos de alto nivel (arreglos,
listas, etc.) y el manejo de memoria por el recolector A pesar de estos avances, sigue siendo un lenguaje
de basura; pero estas características son estigmatizado sin razón. Un ejemplo de esto son las
convencionales, tanto en estos lenguajes como en los palabras de Miles Lines en [10], “Estéticamente no
tradicionales. Finalmente, se señala que los lenguajes me gusta JavaScript....Es una cuestión personal”, lo
de scripting tienen afinidad con el paradigma de que indica que no tiene una razón técnica para juzgar
programación procedimental, no obstante, en la el lenguaje, solo puede basarse en su estructura y es
actualidad esto ya no es tan cierto porque muchos por eso que creo que CoffieScript es como
han migrado hacia la programación orientada a JavaScript, pero con una sintaxis más limpia
objetos, como el caso de PHP, Python y Perl, además limitando un poco el control de los programadores
de otros que fueron creados bajo este paradigma, sobre la puntuación del lenguaje.
como Ruby que es tan orientado a objetos como el Esto es importante, porque da cuenta de que aún
mismo SmallTalk [7]. existen inconformidades provocadas por su
Como se puede ver, la ambigüedad abunda a la hora flexibilidad, que si bien permite abordar un problema
de determinar si un lenguaje de programación es de desde muchas perspectivas, también ha conducido a
scripting o no basándose solo en sus características, la implementación de malas prácticas (como las
tal vez porque lo que importa no es eso, sino cómo variables globales), por parte de desarrolladores
se utilice, lo que puede evidenciarse en la primera inconscientes, lo que a fin de cuentas genera la falsa
parte de la definición dada en [9], donde “Un concepción de que no es apto para desarrollar
lenguaje de scripting es un lenguaje de programación aplicaciones complejas y robustas. Para contradecir
simple usado para escribir una lista de comandos esto en la siguiente sección se muestran varias

http://revistas.udistrital.edu.co/ojs/index.php/tia      
ISSN: 2344-8288 Volumen 1 No. 1 – Enero-Julio de 2014 – Revista TIA - Aplicaciones Modulares en JavaScript   21

opciones para crear aplicaciones modulares en este 6 },


lenguaje. 7 resetCounter: function () {
8 console.log( "counter value prior to reset:
III. Definición de módulos en JavaScript 9 " + counter );
1 counter = 0;
En esta sección se presentaran algunas de las formas 0
como se pueden definir módulos en JavaScript. 1 }
“Los módulos son la pieza integral de cualquier 1
arquitectura de software robusta y típicamente 1 };
ayudan a mantener las unidades de código de un 2
proyecto limpiamente separadas y organizadas”, a 1 })();
esta definición dada en [11] debe agregársele que 3
desde el punto de vista de JavaScript los módulos 1
son objetos cuyas propiedades (funciones) son 4
tratadas como unidades funcionales individuales, que 1 console.log(testModule.incrementCounter());
vendrían siendo el equivalente a los componentes 5
utilizados en aplicaciones del lado del servidor [12]. 1 testModule.resetCounter();
Estos, como ya se mencionó, son el elemento 6
constituyente de las aplicaciones o sistemas Gráfico 1. Declaración del módulo testModule
modulares definidos en la sección II. mediante el patrón módulo [11]

Existen muchas formas de definir módulos en Como se puede apreciar hay un atributo counter que
JavaScript, tanto para la creación de la interfaz de por el simple hecho de estar fuera del return ya es
usuario (ComponentJS) como para la lógica de privado y no puede ser invocado fuera del módulo al
negocio, mediante frameworks (BackBone.js, que pertenece. Por el contrario, se definieron dos
Ember.js) como a través de código nativo (Patrones operaciones públicas, insertCounter que incrementa
de diseño, ES6), tanto para definición asíncrona del un contador y resetCounterque lo reinicia. El
lado del cliente (AMD) como síncrona del lado del resultado de ejecutar ambas operaciones se pone de
servidor (CommonJS), estandarizados tanto para la manifiesto en la figura 5.
creación de SOA (Servicios Web) como con otro
estilo arquitectónico, entre otros. A continuación se
trataran específicamente patrones para definición de
módulos, AMD, CommonJS, Servicios Web y ES6.
Figura 5. Resultado en consola de ejecutar las
A). Patrones para la definición de módulos funciones del módulo ‘TestMdoule’.

Los patrones de diseño orientados a la definición de El patrón módulo revelado es una variación del
módulos más importantes son el patrón módulo y el patrón módulo donde todos sus miembros son
módulo revelado. El primero tiene la intención de privados y donde hay unas interfaces públicas para
emular el encapsulamiento y visibilidad de una clase ciertas propiedades. El ejemplo anterior definido con
en los lenguajes de programación orientada a el patrón módulo revelado tendría la estructura
objetos, es decir la capacidad de definir métodos y presente en el gráfico 2 [12].
atributos de una clase como si fueran públicos (que
puedan ser usados por otros módulos) o privados 1 var testModule = (function () {
(que puedan ser usados solo por el mismo módulo). 2 var counter = 0;
En el gráfico 1 es posible ver la implementación de 3 function privateIncrementCounter() {
un módulo mediante dicho patrón [11]. 4 return counter++;
5 }
1 var testModule = (function () { 6 function privateResetCounter() {
2 var counter = 0; 7 console.log( "counter value prior to reset:
3 return { 8 " + counter );
4 incrementCounter: function () { 9 counter = 0;
5 return counter++; 1 }
0

http://revistas.udistrital.edu.co/ojs/index.php/tia      
ISSN: 2344-8288 Volumen 1 No. 1 – Enero-Julio de 2014 – Revista TIA - Aplicaciones Modulares en JavaScript   22

1 return { están correctamente ordenadas o si no se etiquetaron


1 scripts, de los cuales dependen otros scripts para
1 incrementCounter:privateIncrementCounter,
funcionar. Para solucionar esto los scripts loader
2 cargan scripts junto con sus dependencias de manera
1 resetCounter:privateResetCounter automática y en algunos casos lo hacen de manera
3 asíncrona.
1 };
4 Cargar scripts de esta forma puede ser beneficioso
1 })(); para el rendimiento de las aplicaciones (sobre todo
5 cuando los scripts tienen bajo acoplamiento), ya que
1 son cargados en paralelo permitiendo además que el
6 proceso de carga del resto de la página continúe de
1 console.log(testModule.incrementCounter());
manera independiente. Dentro de los script loader
7 asíncronos encontramos RequireJS, curl.js, BDLoad,
1 testModule.resetCounter(); $script.js, Steal.js, LABjs y yepnope.js. [13]
8 AMD justamente tiene como función definir
Gráfico 2. Declaración del módulo testModule módulos donde tanto el módulo como las
mediante el patrón módulo revelado. dependencias del mismo puedan ser cargados de
manera asíncrona[11], por lo que necesita un script
La principal desventaja de definir módulos mediante loader asíncrono (para los ejemplos que se verán más
patrones es que existen muchas más variantes del adelante se utilizó RequireJS).
patrón módulo (que pueden ser consultadas en [11]),
las cuales terminan provocando “el síndrome del Esta API tiene dos conceptos fundamentales, la idea
salvaje oeste”, donde cada desarrollador hace lo que de un método define que se encarga de la definición
considere y como lo considere. Además no hay del módulo y la idea de un método require que se
manera de controlar la carga asíncrona y paralela de encarga de manejar las dependencias del módulo.
módulos, las dependencias entre estos, la El primer método está constituido por un
disminución de las etiquetas HTML, la optimización identificador de módulo que puede ser opcional, en
y algunas características más [12]. Como una cuyo caso el módulo seria anónimo (lo que puede
alternativa para solucionar estos problemas aparecen evitar colisiones con otros módulos de terceras
CommonJS y posteriormente AMD. partes), un arreglo de dependencias que son
requeridas por el módulo para su funcionamiento y
B). AMD (Asynchronous Module Definition) una función que se utiliza para definir el módulo
(gráfico 3) [11].
A excepción de los lenguajes tradicionales,
JavaScript no proveía en su versión ECMA-262, la 1 define(
forma de definir módulos de manera estándar, limpia 2 module_id /*optional*/,
y ordenada, la única forma de hacer esto era 3 [dependencies] /*optional*/,
mediante los patrones de diseño mencionados en el 4 definition function /*function for
numeral A con las desventajas que esto tenía, por eso 5 instantiating the module or object*/
se crearon APIs como AMD y CommonJS, que 6 );
pueden trabajar en conjunto con unas herramientas Gráfico 3. Declaración del método define en AMD.
llamadas script loaders, cuya función es evitar que
los scripts sean declarados manualmente en páginas El siguiente ejemplo muestra cómo mediante el
HTML. método define se pueden definir los módulos Book y
BookManager. El primero tiene los atributos title y
Tradicionalmente esta declaración se da mediante content con sus respectivos métodos de obtención y
etiquetas <Script>, donde es necesario añadir la ruta modificación (setters y getters) emulando el
del recurso (similar a lo que sucede con la etiqueta paradigma orientado a objetos, mientras que el
<Link> para especificar CSS); sin embargo esto segundo expone funciones para modificar el estado
presenta un problema y es que el navegador carga los de los ejemplares del módulo Book y por ende este
elementos de manera secuencial, lo que puede tener último aparece en su arreglo de dependencias,
efectos negativos en la aplicación si las etiquetas no gráficos 4 y 5.

http://revistas.udistrital.edu.co/ojs/index.php/tia      
ISSN: 2344-8288 Volumen 1 No. 1 – Enero-Julio de 2014 – Revista TIA - Aplicaciones Modulares en JavaScript   23

comunique con la interfaz de usuario) o para cargar


1 define("Book",function(){ de manera dinámica las dependencias de un módulo.
2 var title; En el ejemplo es posible observar que el método
3 var content; require está haciendo uso de una ejemplificación de
4 return { BookManager para escribir y luego leer el contenido
5 setTitle:function(bookTitle){ del ejemplar del módulo Book (gráfico 6). Por medio
6 title=bookTitle; de la función write se modifica el estado de dicho
7 }, ejemplar pasando como parámetros el título y el
8 getTitle:function(){ contenido del mismo, que en este caso en un
9 return title; fragmento de la reconocida novela The Shining
1 }, escrita por Stepen King [14]. Luego se utiliza la
0 función read para mostrar en consola el título y
1 setContent:function(bookCont){ contenido del ejemplar (figura 6).
1
1 content=bookCont; 1 require(['BookManager'],function(bookManager
2 2 ){
1 }, 3 bookManager.write("The Shining"," Jack
3 4 Torrance thought: Officious little prick");
1 getContent:function(){ 5 bookManager.read();
4 6 });
1 return content; Gráfico 6. Definición del método require para
5 BookManager en AMD. Fuente propia
1 }
6 El método require está contenido dentro de un
1 } archivo JavaScript de nombre App.js que es cargado
7 junto con todas sus dependencias mediante
1 }); RequireJS, a través de una etiqueta <Script> que
8 tiene un atributo especial llamado data-main, donde
Gráfico 4. Definición del módulo Book en AMD. es necesario especificar la ruta de dicho archivo
(gráfico 7). El diagrama de secuencia en la figura 7
1 define("BookManager",['Book'], muestra esta inyección de dependencias y el paso de
2 function(bookManaged){ mensajes entre el script App.js y los módulos
3 return{ definidos en AMD.
4 read:function(){
5 1 <script data-main="js/app"
console.log(bookManaged.getTitle()+" 2 src="js/require.js"></script>
6 "+bookManaged.getContent()); Gráfico 7. Declaración del archivo app.js mediante
7 }, la etiqueta <script>. Fuente propia
8 write:function(title,text){
9 bookManaged.setTitle(title); Resultado en consola de ejecutar la función read del
1 bookManaged.setContent(text); módulo BookManager definido en AMD
0
1 }
1
1 };
2 Figura 6. Resultado en consola de ejecutar la función
1 }); ‘read’ del módulo ‘BookManager’ definido en
3 AMD.
Gráfico 5. Definición del módulo BookManager en
AMD. Diagrama de secuencia del sistema con los módulos
definidos en AMD
El método require es utilizado para cargar código en
un archivo JavaScript de más alto nivel (que se

http://revistas.udistrital.edu.co/ojs/index.php/tia      
ISSN: 2344-8288 Volumen 1 No. 1 – Enero-Julio de 2014 – Revista TIA - Aplicaciones Modulares en JavaScript   24

Esta función es importada por el script ‘exeDep.js


por medio del método require que recibe como
parámetro la ruta del módulo (gráfico 8 y 9).

1 function sayHello (name){


2 console.log('Hello, my name is
'+name+'
3 !!!');}
4 function sayBye(){
5 console.log('Bye, bye !!!');
6 }
7 exports.sayHello=sayHello;
Figura 7. Diagrama de secuencia del sistema con los Gráfico 8. Definición del módulo ‘Dep en
módulos definidos en AMD. CommonJS.
1 var dep=require("./dep");
AMD presenta una forma clara, flexible y 2 dep.sayHello('Daniel');
encapsulada de definir módulos y dependencias en Gráfico 9. Script exeDep.js.
JavaScript sin necesidad de etiquetas <script> (salvo La función sayHello recibe en tiempo de ejecución
la etiqueta del script principal), no presenta el String Daniel y lo asigna a la variable name en el
problemas de cross-domain, se pueden incluir varios String 'Hello, my name is '+name+' !!!' para después
módulos en un solo archivo, es posible realizar carga mostrarlo en consola (figura 8).
perezosa de scripts si se necesita y la mayoría de
script loaders soportan la carga de módulos en Resultado en consola de ejecutar la función sayHello
navegadores sin un proceso de compilación. Además del módulo dep definido en CommonJS
puede integrarse con frameworks como Backbone.js
y ember.js para mantener las aplicaciones ordenadas
y se ha utilizado en grandes compañías como IBM Y
BBC iPlayer en proyectos no triviales [11] Figura 8. Resultado en consola de ejecutar la función
‘sayHello’ del módulo ‘dep’ definido en CommonJS.
C). CommonJS, módulos optimizados para
servidor La simplicidad de CommonJS es evidente, porque
solo es necesario utilizar el método require para
CommonJS es un API de definición de módulos del solicitar contenido de manera síncrona. También es
lado del servidor, al contrario de AMD que está más posible apreciar la ausencia de una función envoltura
enfocado a la definición de módulos del lado del o wrapper como en AMD, lo que resta complejidad
cliente (esto no significa que no se puedan utilizar en a la definición de módulos, pero permite la
sentido contrario, solo que CommonJS tiene algunas declaración de variables globales. Para evitar esto
funciones especiales que no funcionarían en el RequireJS provee una forma para crear wrappers
navegador, como el manejo de archivos, promises, para los módulos hechos en CommonJS que además
entre otros). Tiene varias implementaciones como puedan ser declarados mediante etiquetas <Script>
Node.js y surgió gracias a un grupo de trabajo como si de un módulo AMD se tratase.
encargado del diseño, prototipado y estandarización
de las APIs de JavaScript [11]. AMD y CommonJS podrían ser herramientas
complementarias y son muy similares en su
Un módulo, desde el punto de vista de CommonJS, estructura (AMD inicio como una extensión de
es una pieza reutilizable de código que exporta CommonJS). Sin embargo AMD presenta ciertas
objetos para que sean utilizados por otros módulos ventajas como el soporte de pluguins, poder cargar
mediante la variable exports. Además cuenta con el más que archivos JavaScript, tener facilidades para
método require que importa los objetos exportados trabajar tanto en el navegador como en el servidor y
por otros módulos [11]. En el ejemplo se definió un haber sido adoptado por librerías JavaScript como
módulo llamado dey que tiene dos funciones Dojo, Mootools y Jquery [15].
sayHello y sayBye pero solo exporta la primera
(dado que en JavaScript las funciones son objetos). D). Servicios web

http://revistas.udistrital.edu.co/ojs/index.php/tia      
ISSN: 2344-8288 Volumen 1 No. 1 – Enero-Julio de 2014 – Revista TIA - Aplicaciones Modulares en JavaScript   25

REST mediante Node.js y su framework Express; sin


En este mundo globalizado la integración entre embargo existe un módulo llamado Restify que es
empresas es algo común, sin embargo esto significa más apropiado para la realización de esta tarea,
también una integración entre sistemas de software porque como está señalado en su página oficial
que siempre ha sido una labor dispendiosa y (Restify Documentation), “Restify existe para dejarte
problemática, máxime cuando dichos sistemas están construir APIs 'estrictas' de servicios que sean
en diferentes plataformas, hardware y lenguajes de mantenibles y observables”, en cambio Express tiene
programación [16]. Con el objetivo de hacer menos como objetivo la creación de aplicaciones Web
traumático este proceso y de generar arquitecturas de robustas. A continuación se puede observar una parte
software flexibles con capacidad de adaptación, se de la creación de un Servicio Web llamado
generó la arquitectura orientada a servicios (SOA) BookStore con el módulo Restify , la creación del
[17]. servidor HTTP que contendrá el servicio y la
declaración de operaciones asociadas a verbos HTTP
Este estilo arquitectónico concibe los sistemas de que en este caso son funciones de búsqueda e
software como conjuntos de componentes llamados inserción de libros (gráfico 10 y 11).
servicios, que se interrelacionan por medio de
interfaces para cumplir con el objetivo del sistema, 1 var restify= require('restify');
con una característica extra y es que los servicios 2 var PATH='/BookStore';
pueden integrarse sin importar en que tecnología 3 var server=restify.createServer({
estén desarrollados (plataforma, hardware, lenguaje 4 name: "myBookStore"
de programación, etc), lo que significa desacoplar la 5 });
funcionalidad de un componente de su 6 server.listen('8080' ,'127.0.0.1',
implementación. Además SOA aprovecha la amplia function(){
aceptación de XML y JSON para la especificación 7 console.log('%s listening at %s ',
de las interfaces mediante Servicios Web (no es la server.name ,
única pero sí la más común) [17]. 8 server.url); });
Gráfico 10. Creación del Servicio Web y del servidor
Existen varios modelos para servicios web, pero los HTTP.
más utilizados son SOAP y REST. SOAP (Simple
Object Access Protocol) es el modelo estándar y está 1 server.get({path : PATH , version :
fuertemente basado en XML y XML Schema, donde '0.0.1'} ,
se especifican las operaciones que el servicio provee, 2 findAllBooks);
los parámetros de entrada tipados (entero, cadena, 3 server.get({path : PATH +'/:isbn' ,
flotante e incluso tipos complejos) de dichas version :
operaciones y su respectiva respuesta. Todo esto se 4 '0.0.1'} , findBook);
codifica en un WSDL (Web Service Definition 5 server.post({path : PATH , version:
Lenguage) que por analogía sería el contrato entre el '0.0.1'}
proveedor del servicio y el consumidor. Un servicio 6 ,postNewBook);
REST (Representational State Transfer) por su parte Gráfico 11. Definición de operaciones asociadas a
hace uso del protocolo HTTP y utiliza los verbos que verbos HTTP.
este ofrece para representar las operaciones
proveídas; los verbos más comunes son GET, PUT, En Restify también se pueden añadir pluguins para
POST y DELETE, además los datos pueden personalizar el servicio por ejemplo para parsear las
estructurarse tanto XML como en YAML o JSON peticiones HTTP, acceder a recursos en otros
entre otros (Aunque JSON es el preferido). De igual dominios, transformar los datos de la petición en un
manera REST también presenta su propio esquema o objeto JavaScript en el servidor automáticamente,
contrato llamado WADL (Web Application etc.
Description Lenguage) definido en XML donde se
describen las acciones disponibles y algunos Una vez declarado el servicio es posible acceder a
metadatos (es mucho más flexible que el WSDL) este mediante una URL y el conjunto de verbos
(SmartBear). HTTP (Para este caso GET y POST). En el ejemplo
para obtener todos los libros del BookStore se debe
En JavaScript es posible definir servicios web tipo realizar una petición GET al servidor, para obtener

http://revistas.udistrital.edu.co/ojs/index.php/tia      
ISSN: 2344-8288 Volumen 1 No. 1 – Enero-Julio de 2014 – Revista TIA - Aplicaciones Modulares en JavaScript   26

solo uno específicamente debe realizarse una EcmaScript es un “lenguaje de scripting”


petición GET con el parámetro ISBN (Número de estandarizado por Ecma International e
identificación del libro) en la URL y finalmente para implementado por JavaScript, por ende la siguiente
añadir un nuevo libro es necesario hacer una petición versión de dicho lenguaje (EcmaScript 6) es en
POST. Los resultados de dichas peticiones se pueden esencia la siguiente versión de JavaScript. Esta ya
observar en la figura 9, la figura 10 y la figura 11. tiene una sintaxis definida al menos en lo que a
Para generar el código JavaScript que consuma el especificación de módulos se refiere, sin embargo
servicio existen muchas opciones, es posible utilizar aún no es soportada por los navegadores y se espera
por ejemplo Restify, SoapUI o un módulo de Node.js que siga siendo así al menos hasta junio del 2014
llamado wadl-client que genera código JavaScript a que es su fecha de lanzamiento inicial. Por esta razón
partir de una especificación WADL. para implementar algunas de las características de
ES6 en ES5 (la versión actual), es necesario el uso
Petición GET al servicio BookStore de algunas herramientas extra por el momento[18].

Entre las características más llamativas de la nueva


versión de JavaScript están el soporte para clases,
utilización de funciones arrow y promises, block
scoping y soporte para definición de módulos[19].
Figura 9. Petición GET al servicio ´BookStore´. Esta última se incluyó con el fin de crear un formato
que fuera fácil de utilizar tanto por usuarios de AMD
Petición POST al servicio BookStore como de CommonJS y por lo tanto tiene propiedades
de ambas APIs. Es similar a AMD por que permite la
carga y definición de módulos de manera asíncrona y
es similar a CommonJS en su simplicidad y la
inclinación por exportar un único objeto por módulo
[20].
Figura 10. Petición POST al servicio ´BookStore´.
Los módulos definidos en ES6 pueden exportar
Petición GET con parámetro al servicio BookStore recursos mediante el prefijo export e importar
módulos por medio del prefijo import donde además
debe especificarse que recursos se importaran y de
que módulo [20]. En el ejemplo se define un módulo
llamado Adder que exporta una función double que
duplica el valor de un número. Dicha función es
Figura 11. Petición GET con parámetro al servicio importada y utilizada por el script ‘main.js
´BookStore´. generando una respuesta en consola (gráfico 12 y
13).
El principal problema de ambos modelos está en su
especificación. El WSDL de SOAP es demasiado 1 var double = function(x) {
rígido, si hay una modificación (aunque sea solo un 2 return x + x;
parámetro) en alguna operación del servicio, la 3 }
especificación debe modificarse y esto implica una 4 export { double };
modificación en la implementación de los Gráfico 12. Definición del módulo ‘Adder en ES6.
consumidores de ese servicio, mientras que el Fuente (Franklin, 24Ways to impress your friend,
WADL de REST es opcional, lo que le da 2014).
flexibilidad pero a cambio de no especificar las
operaciones que ofrece el servicio. Para superar estas 1 import { double } from './adder';
deficiencias existen aplicaciones para 2 console.log("El resultado de la
documentación como RAML y JSON-Home operación es:
(SmartBear). 3 "+double(2)); //4
Gráfico 13. Script ‘main.js, (Franklin, 24Ways to
E). EcmaScript 6 (ES6), el futuro impress your friend, 2014).
Esta sintaxis para la definición de módulos es la que

http://revistas.udistrital.edu.co/ojs/index.php/tia      
ISSN: 2344-8288 Volumen 1 No. 1 – Enero-Julio de 2014 – Revista TIA - Aplicaciones Modulares en JavaScript   27

proveerá ES6 de manera definitiva. Sin embargo como lo hace RequireJS. Traceur por su parte es un
como se mencionó antes, no es una versión de transpiler que compila de ES6 a ES5 lo que tiene
JavaScript actualmente soportada por los como ventaja que puedan ser implementadas otras
navegadores. Para solucionar este inconveniente es características (Además de los módulos) de la nueva
necesario utilizar otros recursos para poder ejecutar versión de JavaScript que aún no son soportadas por
módulos hechos en ES6 al menos por ahora. La el navegador [21].
primera opción es utilizar ES6 module-transpiler,
que toma los módulos definidos en ES6 y los Para su funcionamiento SystemJS debe ser cargado
compila en AMD o CommonJS para que puedan ser mediante las etiquetas <script>, luego es necesario
interpretados por el navegador (una guía para la declarar la función System.import (mediante las
instalación del ES6 module-transpiler se encuentra mismas etiquetas), que recibe como parámetro la
en (Franklin, JavaScript Playground, 2014)) (gráfico ruta del archivo JavaScript principal que carga los
14 y 15). Para el ejemplo anterior el resultado de la módulos. En el ejemplo esta función carga el archivo
compilación fue en CommonJS y se ejecutó por main.js y las dependencias del mismo, en este caso el
medio de Node.js, dando como resultado el que se módulo adder (gráfico 16). El resultado en la
puede ver en la figura 12. consola del navegador puede verse en la figura 13 y
la inyección de dependencias puede apreciarse en el
1 "use strict"; diagrama de secuencia en la figura 14.
2 var double = function(x) { 1 <script
3 return x + x; src="js/System/system.js"></script>
4 } 2 <script>
5 exports["double"] = double; 3 System.import('./js/ES6/main');
6 //# sourceMappingURL=adder.js.map 4 </script>
Gráfico 14. Resultado en CommonJS de compilar el Gráfico 16. Declaración del archivo ‘system.js
módulo ‘Adder con ES6 module-transpiler. mediante la etiqueta <script> y carga del archivo
‘main.js.
1 // 4
2 "use strict"; Resultado en consola de ejecutar la función double
3 var adder$$ = require("./adder"); por medio de SystemJS
4 console.log("El resultado de la
operación es: "
5 +adder$$["double"](2));
6 //# sourceMappingURL=app.js.map
Gráfico 15. Resultado en CommonJS de compilar el Figura 13. Resultado en consola de ejecutar la
script ‘main.js con ES6 module-transpiler. función ‘double’ del módulo ‘adder’ por medio de
Resultado en consola de ejecutar la función ‘double SystemJS.
por medio de ES6 module-transpiler
Diagrama de secuencia del sistema con el módulo
definido en ES6

Figura 12. Resultado en consola de ejecutar la


función ‘double’ del módulo ‘adder’ por medio de
ES6 module-transpiler.

La segunda opción es utilizar SystemJS que es un


compilador para módulos universal, sin importar que
estén definidos en ES6, AMD, CommonJS o
cualquier otra forma. Este depende de dos librerías
para cumplir su función ES6 module loader polyfill
y Traceur. La primera se encarga de cargar archivos
JavaScript y sus dependencias de manera automática
por medio de la función System.import similar a

http://revistas.udistrital.edu.co/ojs/index.php/tia      
ISSN: 2344-8288 Volumen 1 No. 1 – Enero-Julio de 2014 – Revista TIA - Aplicaciones Modulares en JavaScript   28

Figura 14. Diagrama de secuencia del sistema con el para integrar componentes desarrollados en
módulo definido en ES6. lenguajes de servidor, pueda ser utilizado para
integrar componentes hechos enteramente en el
Además en ES6 se puede definir exportar solo un mismo lenguaje, demostrando que la creación de
recurso (objeto) por módulo similar a CommonJS, aplicaciones robustas con él es una realidad.
añadiendo el prefijo default al prefijo export.
También es posible importar módulos de manera Por otro lado, en los lenguajes de programación
condicional mediante la Programmatic Loader API y tradicionales para la creación de aplicaciones del
se pueden definir dependencias cíclicas entre lado del servidor (Java, .Net) existen modelos de
módulos [20]. componentes cuya función es estandarizar la
implementación, nombramiento, personalización,
A pesar de que hace falta un poco de trabajo extra composición, interoperabilidad, evolución y
para definir módulos en ES6 gracias a que ningún despliegue de componentes[23]. En JavaScript, por
navegador actualmente lo soporta (Y por unos meses su parte, no existe aún una definición de módulos o
seguirá siendo así), no dista mucho del trabajo que componentes estándar, pero se espera que esto
significa utilizar RequireJS por ejemplo; además cambie cuando ES6 sea soportado por los
cuando esta versión de JavaScript sea finalmente navegadores. Lo que tiene como principal objetivo
soportada, los módulos hechos ahora en ES6 serán mediar entre las distintas formas de crear módulos
migrados automáticamente [18]. Ya no serán (AMD, CommonJS, patrones, etc.) definiendo reglas
necesarias las herramientas intermediarias para su comunes y acabando por ende con El síndrome del
compilación e interpretación (ES6 module-transpiler salvaje oeste, al menos en este aspecto.
o SystemJS) y se tendrá una solución nativa (mejor
que el patrón módulo), lo que es sin duda es una Finalmente, aún en su versión ES6, JavaScript es
ventaja frente a APIs como AMD y CommonJS. permisivo en cuanto a que se pueden exportar más
que operaciones entre módulos, es decir se pueden
Como se mencionó antes existen muchas formas de compartir variables u objetos con estado. En ese
definir módulos que constituyan aplicaciones orden de ideas el estatus de componente estaría
mantenibles y con capacidad de evolución en reflejado más por las buenas prácticas del
JavaScript, sin embargo las anteriormente desarrollador que por el mismo lenguaje.
especificadas son las más utilizadas y sobre las que
existe mayor documentación. Sumado a esto, IV.Referencias
muestran de una manera clara que todo va
encaminado hacia el establecimiento de un estándar [1] S. Cass, “IEEE spectrum”, 19 de julio de 2014,
para definir módulos reutilizables en JavaScript [en línea]. Consultado el 14 de abril de 2014,
(exceptuando los servicios web que se incluyeron disponible en:
por la relevancia que está cobrando el estilo http://spectrum.ieee.org/computing/software/top-10-
arquitectónico SOA en la actualidad), objetivo que programming-languages
según la promesa se podrá conseguir en ES6.
[2] S. O'Grady, “RedMonk”, 14 de enero de 2014,
IV. Conclusiones [en línea]. Consultado el 14 de abril de 2014,
disponible en:
El concepto de componente o módulo ha venido http://redmonk.com/sogrady/2014/01/14/language-
cobrando trascendencia en los últimos años, gracias rankings-1-15/
a que son elementos que pueden constituir
aplicaciones o sistemas mantenibles, adaptables y [3] Tiobe, “Tiobe Software, the software quality
con capacidad de evolucionar sin importar su company”, abril de 2014, [en línea]. Consultado el
complejidad. En JavaScript existen multitud de 14 de abril de 2014, disponible en:
formas de crear aplicaciones con este tipo de http://www.tiobe.com/index.php/content/paperinfo/t
características mediante APIs (AMD, CommonJS y pci/index.html
todas las que surgieron a partir de CommonJS),
servicios web y de manera nativa (patrón módulo, [4] C. Ghezzi, D. Mandrioli y M. Jazayeri, “Software
sus derivados y ES6), lo que posibilita que ahora en Qualities and Principles”, Computer Science
lugar de ser un lenguaje de programación utilizado Handbook, Second Edition, Chapman & Hall/CRC,

http://revistas.udistrital.edu.co/ojs/index.php/tia      
ISSN: 2344-8288 Volumen 1 No. 1 – Enero-Julio de 2014 – Revista TIA - Aplicaciones Modulares en JavaScript   29

pp. 2376-2401, 2004.

[5] K. Lau, A. Nordin, F. Taweel and T. Rana, [16] C. Kankanamge, Web Service Testing with
“Constructing Component-based Systems Directly SOAPUI, Birmingham, Pack Publishing, 2012.
from Requirements using Incremental Composition”,
Proc. 36th EUROMICRO Conference on Software [17] M. Bolo, “Aquitectura de integración orientada
Engineering and Advanced Applications, 2010. a servicios”, INTERFACES, nº 1, pp. 19-46, 2006.

[6] C. Larman, Applying UML and patterns, Second [18] J. Franklin, “24 Ways to impress your friend”, 3
Edition, Prentice Hall, 2002. de diciembre de 2014, S.f., [en línea]. Consultado el
15 de mayo de 2014, disponible en:
[7] R. E. Noonan y . W. L. Bynum, “Scripting http://24ways.org/2014/javascript-modules-the-es6-
Lenguages”, Computer Science Handbook, Second way/
Edition, Chapman & Hall/CRC, pp. 2213-2230,
2004. [19] N. Stieglitz, “Wintellect Blogs”, 24 de marzo de
2014. S.f., [en línea]. Consultado el 15 de mayo de
[8] A. Kanavin, “An overview of scripting 2014, disponible en:
languages”, Lappeenranta, 2002. http://www.wintellect.com/devcenter/nstieglitz/5-
great-features-in-es6-harmony
[9] WebMonkey, “WebMonkey”, febrero de 2010,
[en línea]. Consultado el 27 de abril de 2014, [20] A. Rauschmayer, “2ality JavaScript and More”,
disponible en: 7 de septiembre de 2014. [en línea]. Consultado el 15
http://www.webmonkey.com/2010/02/scripting_lang de mayo de 2014, disponible en:
uage/ http://www.2ality.com/2014/09/es6-modules-
final.html
[10] P. Wayner, “InfoWorld”, 17 de octubre de
2011, [en línea]. Consultado el 28 de abril de 2014,
disponible en: [21] J. Franklin, “JavaScript Playground”, 8 de junio
http://www.infoworld.com/article/2620515/applicati de 2014. [en línea]. Consultado el 15 de mayo de
on-development/from-php-to-perl--what-s-hot-- 2014, disponible en:
what-s-not-in-scripting-languages.html?page=2 http://javascriptplayground.com/blog/2014/06/es6-
modules-today/
[11] A. Osmani, “Learning JavaScript Design
Patterns”, O'Reilly, 2014.

[12] A. Castrounis, “innoarchitech.com”, 24 de [22] SmartBear, “SoapUI”, S.f., [en línea].


agosto de 2014, [en línea]. Consultado el 21 de mayo Consultado el 18 de mayo de 2014, disponible en:
de 2014, disponible en: http://www.soapui.org/testing-dojo/world-of-api-
http://www.innoarchitech.com/scalable- testing/soap-vs--rest-challenges.html
maintainable-javascript-modules/
[23] G. T. Heineman y W. T. Councill, Component-
[13] J. Hann, “unscriptable.com”, 30 de marzo de Based Software Engineering: Putting the Pieces
2011, [en línea]. Consultado el 8 de agosto de 2014, Together, Addison-Wesley Longman Publish CO,
disponible en: 2001.
http://unscriptable.com/2011/03/30/curl-js-yet-
another-amd-loader/ [24] “Restify Documentation”, S.f., [en línea].
Consultado el 18 de mayo de 2014, disponible en:
[14] S. King, The Shining, 1977. http://mcavage.me/node-restify/

[15] M. Medeiros, 30 de septiembre de 2011, [en


línea]. Consultado el 10 de mayo de 2014, disponible
en: http://blog.millermedeiros.com/amd-is-better-for-
the-web-than-commonjs-modules/

http://revistas.udistrital.edu.co/ojs/index.php/tia      

También podría gustarte