Javascript es un lenguaje muy activo. A pesar de su longevidad (va ya camino de cumplir los 18 añitos) y de haber pasado etapas de enorme y negativa crítica, no ha dejado de crecer y de hacerse más popular, especialmente en los últimos tiempos con la aparición de por ejemplo, el motor V8 de Google para su navegador Chrome, NodeJS o la infinidad de frameworks para el desarrollo de complejas aplicaciones front-end que hoy día pueblan la red.
Si bien es cierto que todas estas nuevas aportaciones a Javascript han facilitado mucho la vida de los desarrolladores, que cada vez pueden emplearlos de forma más sencilla para realizar con éxito tareas más complejas, también es cierto que dichas aportaciones algunas veces “idiotizan” a los programadores, que llegamos a depender de ellas sin entender del todo qué estamos haciendo, olvidando conceptos tales como los patrones de diseño que, aplicados a nuestro problema de una forma más o menos directa, “embellecen” nuestro código y lo hacen más robusto ante fallos tales como la “contaminación” de los espacios de nombres u otro tipo de errores muy comunes cuando uno maneja lenguajes tan “volubles” como Javascript.
La idea de este post es recordar (y para muchos probablemente descubrir) uno de los más básicos, a la par que útiles patrones: Singleton. Este patrón tiene muchos usos en Javascript, principalmente:
Definición de espacios de nombres (“namespacing”): Al reducir el número de variables globales en nuestras páginas.
Generalización de funcionalidades, ignorando las diferencias que pueda ocasionar la ejecución de estas dependiendo del navegador empleado (técnica conocida como “branching”)
Organización del código de una página (o aplicación): incrementando la legibilidad y mantenibilidad de dicho código.
A pesar de que el patrón Singleton, dada su utilidad, ha evolucionado en muchos aspectos distintos, su definición básica es muy sencilla:
/* Ejemplo básico de Singleton */
var Singleton = {
atributo1: ‘un texto’,
atributo2: 250,
metodo1: function() {
},
metodo2: function(arg) {
}
};
Y con esta aplicación tan básica (y aparentemente absurda) del patrón ya estamos consiguiendo sustanciales mejoras en nuestro trabajo, tales como agrupar atributos y funcionalidad con características comunes bajo un mismo espacio de nombres (la variable “Singleton” por supuesto no es el mejor ejemplo de namespace...) y evitar contaminar el espacio de nombres global con una serie de métodos y atributos. Claro está que sigue existiendo la posibilidad de que, en el caso del ejemplo, la variable Singleton sea sobreescrita por otro código/biblioteca posterior, pero ya la situación se reduce a ¼ si lo comparamos con disponer los cuatro elementos que contiene de forma independiente.
Miembros privados con Singleton
Algunas veces puede resultar útil establecer miembros privados a nuestro espacio de nombres, como si de clases se tratara. Existen dos formas de hacer esto desde Singleton:La más directa es “simular” estos elementos privados mediante el convencionalismo de comenzar el nombre con un guión bajo “_”.
/* Singleton simulando miembros privados con _ */
miNamespace.MiClase = {
// Miembros privados
_atributoPrivado: 25,
_metodoPrivado: function(){
},
...
// Miembros públicos
metodoPublico: function(arg) {
// Aquí podremos usar los miembros privados
var v1 = _metodoPrivado(_atributoPrivado);
...
},
...
}
Esto realmente no evita que nadie pueda acceder o reescribir dicho método, pero da una idea a los programadores que posteriormente vayan a emplear este elemento que dichos miembros no deberían ser modificados ni accedidos desde fuera del propio objeto.
La alternativa consiste en aplicar “clausuras” a nuestro patrón Singleton, de la siguiente forma:
miNamespace.MiClase = (function() {
// Miembros privados
var atributoPrivado = 25;
function metodoPrivado(){
};
...
// Miembros públicos
return {
metodoPublico: function(arg) {
// Aquí podremos usar los miembros privados
var v1 = metodoPrivado(arg);
…
},
…
};
})();
Este patrón es también conocido como “patrón módulo”, refiriéndose al hecho de que modulariza y encapsula un conjunto de métodos y atributos relacionados de alguna forma.
Conclusión: ¿Cuándo conviene usar Singleton?
La respuesta en este caso es tan sencilla como el patrón: tan a menudo como sea posible, sin importar el tamaño del proyecto.En proyectos simples, puede emplearse como espacio de nombres para contener todo nuestro código bajo una única variable global. En grandes, puede ser usado para agrupar código relacionado para simplificar la mantenibilidad del mismo y localizarlo en un único lugar en nuestro proyecto, facilitando la modularidad. Incluso en los proyectos de mayor envergadura, Singleton ayuda a optimizar nuestra aplicación, facilitando la carga asíncrona de partes del código que no sean usadas frecuentemente.
En definitiva, a pesar de que es probable que mucha gente ya conozca este patrón, nunca está de más refrescar su utilidad, ya que difícilmente existirá un proyecto donde Singleton no sea aplicable.
Sergio Almécija
No hay comentarios:
Publicar un comentario