Patrón Singleton con JavaScript

Seguimos con esta idea de presentar diferentes patrones de diseño desde la mirada de JavaScript. En esta oportunidad les traigo el patrón singleton.

En muchos lenguajes de programación este patrón ya viene encapsulado en la propia sintaxis. Usar, por ejemplo, un tipo static en C# es básicamente lo mismo que un singleton, pero sin tener que escribir el código del patrón y al mismo tiempo con ventajas sobre el manejo de hilos y procesos.

En otros lenguajes, como en el caso de JavaScript, aún tenemos que hacerlo al viejo estilo (O por lo menos eso queremos para que este post tenga sentido).

Este patrón nos permite, para resumirlo de forma rápida, obtener una misma instancia de determinado objeto. Una ventaja de esto sería si necesitamos que un proceso particular no pueda ser manejado desde diferentes objetos por más que sean una copia del mismo código.

Un ejemplo simple de imaginar (Aunque no relacionado de forma directa a JavaScript) sería el de tener un formulario para una aplicación de escritorio, el cuál se abre al presionar un botón. Si para abrir este formulario necesitáramos crear un nuevo objeto del mismo, tendríamos copias de este formulario tras cada creación. Con un singleton, por el contrario, podríamos llamar al mismo formulario una y otra vez asegurándonos que siempre será el único y originalmente creado el que se muestre al usuario.

Pero vamos con el código para JavaScript:

(function (w) {
 var _instance = null;
 
 var singleton = function () {
  this.URL = "";
 };
 
 singleton.prototype.conectar = function () {
  console.log("Conectando a ", this.URL);
 };
 
 w.conector = {
  getInstance: function () {
   if (_instance === null) {
    _instance = new singleton();
   }
 
   return _instance;
  }
 };
}(window));

Analicemos un poco el código. Lo que usamos para generar todo el objeto es una función auto ejecutada (Tiene otros nombres, pero puede que ese nombre ayude a entender cómo funciona). Esta función se ejecuta automáticamente y debido a la forma en cómo JavaScript maneja las variables y su alcance (Closure) podremos mantener la variable _instance a la espera de una instancia de un nuevo objeto.

Luego crearemos en la variable singleton lo que sería una representación de nuestro objeto (Como si fuese una clase en otros lenguajes). Esta posee una variable URL y una función conectar.

Por último, inyectaremos al objeto window (Padre del árbol de objetos en el navegador) un objeto llamado conector y que tendrá una función getInstance. Es esta función la que nos permite crear y manejar el singleton. En ella, cada vez que alguien pide una instancia de nuestro singleton verificamos si la variable _instance tiene ya una referencia al objeto en cuestión. Si no la tuviere, creamos un nuevo objeto y retornamos ese valor, pero si por el contrario ya hubiera sido instanciado por otra llamada, entonces retornaremos el mismo objeto ya creado, haciendo que el consumidor de nuestro objeto siempre obtenga la misma referencia al objeto singleton.


Patrón State con JavaScript

Siguiendo con esta idea de los patrones de diseño con JavaScript, y a pedido de (Otra vez) algunos amigos, vamos con el patrón State.

Este patrón es bastante simple pero puede ser implementado de diferentes formas, dependiendo del lenguaje de programación que usemos. En JavaScript, desde lo personal, me gusta jugar un poco con las funciones y algunas referencias a las mismas.

Este patrón, en resumen, permite modificar el comportamiento de un objeto en base a cosas que pudiesen pasar dentro del mismo. De cara al consumidor del objeto, esto se aprecia solo por medio de los resultados del objeto. Otro motivo por el cual utilizar este patrón es el de ahorrarnos en complicados switchs e ifs para realizar determinadas acciones.

Supongamos lo siguiente:

contador += 1
if (contador < 10)
  EjecutarX()
else
  EjecutarY()

En el caso anterior, el código se repetiría indefinidamente, sumando la variable contador y evaluando el if constantemente. Internamente, una función o la otra se ejecutarían en base al estado interno de la variable. El problema de esto es que (Y si bien así como lo vemos no es un problema realmente) si tenemos muchos estados (ifs o switchs) puede ser difícil de mantener y depurar por lo que el patrón en cuestión sería una mejor aproximación.

var State = (function () {

   var state = function () {
      ...
       this._counter = 1;
    };
 
    state.prototype.run = function () {
       var self = this;
      ...
    };
 
    return state;
}());

Lo primero es crear un objeto. En este dejamos la variable _counter y una función run. Además agregaremos dos funciones que representarán el estado del objeto en diferentes momentos de la ejecución.

 state.prototype.state1 = function () {
   console.log("Estado 1");
    this._counter++;
    if (this._counter > 10) {
       this._innerPointer = this.state2;
    }
 };
 
 state.prototype.state2 = function () {
    console.log("Estado 2");
 };

También una función vacía, que si notamos en la función state1 notaremos que se utiliza para asignar la función state2 cuando el contador es superior a 10.

 state.prototype._innerPointer = function () {
 };

El último cambio será en la función run donde iniciaremos un intervalo de 1 segundo ininterrumpido y que llamará a la función _innerPointer. Esta función fue asignada con el estado 1 al inicio del objeto. De esta forma, cada vez que se llame a _innerPointer en realidad se estará llamando a state1. Luego de ser llamada 10 veces, state1 cambiará la referencia de _innerPointer a state2 y esta función se ejecutará indefinidamente.

var State = (function () {

   var state = function () {
       this._innerPointer = this.state1;
       this._counter = 1;
    };
 
    state.prototype.run = function () {
       var self = this;
       setInterval(function () {
          self._innerPointer.call(self);
       }, 1000);
    };
 
    state.prototype._innerPointer = function () {
    };
 
    state.prototype.state1 = function () {
       console.log("Estado 1");
       this._counter++;
       if (this._counter > 10) {
          this._innerPointer = this.state2;
       }
    };
 
    state.prototype.state2 = function () {
       console.log("Estado 2");
    };
 
    return state;
}());

 


Patrón Interpreter con JavaScript

Hace unos días publicaba un ejemplo bastante simple de cómo implementar el patrón cadena de responsabilidad con JavaScript. Un amigo me largó la idea de ir por el patrón Interpreter. Así que aquí vamos.

El patrón Interpreter es útil para, como lo dice su nombre, interpretar cosas. Muy útil para la creación de analizadores sintácticos; El principio de la creación de las reglas de un lenguaje de programación por ejemplo, o para transformar un texto en otra cosa, como números romanos a decimales.

En nuestro caso supongamos lo siguiente:

get http://jsonplaceholder.typicode.com/posts/1 => data

En vez de tener que escribir el código para esta acción, queremos que el interpretador lea la cadena de texto y realice una acción particular. En este caso, realizar una petición HTTP mediante GET a una URL y luego almacenarla en una variable de nombre DATA.

Podemos separar, entonces, nuestro texto en ACCION [parámetros] LUEGO [variable].

Lo primero que necesitaremos será un objeto (Clase) que nos permita crear las diferentes parte de nuestro idioma, teniendo como parte de nuestro idioma aquello que pusimos en mayúsculas (GET y =>).

var expressionBase = Class.extend(function () {
    this.interpret = function (context) { };
});

(Volvemos a usar, como en el caso del patrón anterior, ExtendJS y además jQuery)

Luego crearemos cada una de las secciones de nuestro idioma derivadas de esta clase.

var getExpression = expressionBase.extend(function () {
 this.interpret = function (context) {
 if (context._expression.substring(0, 4) !== "get ") { throw "Incorrect syntax"; }
 
 var target = context._expression.substring(4, context._expression.indexOf(' ', 4));
 
 $.ajax({
 url: target,
 async: false,
 success: function (data) {
 context._data = data;
 }
 });
 };
});

var thenExpression = expressionBase.extend(function () {
 this.interpret = function (context) {
 var validator = context._expression.split(' => ');
 if (validator.length !== 2) { throw "Incorrect syntax near =>"; }
 };
});

var creatorExpression = expressionBase.extend(function () {
 this.interpret = function (context) {
 var holder = context._expression.substring(context._expression.indexOf('=> ') + 3).trim();
 window[holder] = context._data;
 };
});

Por supuesto, hay muchas formas de tomar los valores del texto y actuar en consecuencia. Lo importante es que hemos separado cada una de las partes funcionales de nuestro lenguaje en diferentes clases y cada una de ellas tiene una responsabilidad.

Lo siguiente será crear una pseudo factory (Otro patrón) que nos ayude a crear las reglas de nuestro lenguaje. Aquí hay que aclarar que lo mejor sería tener un árbol con toda la estructura y no una lista, pero para el ejemplo vale.

var context = function () {
 
 this._data = null;
 this._expression = null;
 var expressionTree = [];
 
 expressionTree.push(new getExpression());
 expressionTree.push(new thenExpression());
 expressionTree.push(new creatorExpression());
 
 this.expressionResult = function () {
 return this._data;
 };
 
 this.setContext = function (expression) {
 this._expression = expression;
 
 for (var i = 0; i < expressionTree.length; i++) {
 expressionTree[i].interpret(this);
 }
 };
};

Como podemos ver, la variable expressionTree (Que es un array) define el orden del lenguaje. Primero el GET, luego => y finalmente la variable destino. Con una mejor estructura podríamos crear todas las combinaciones de nuestro propio lenguaje.

Por último, ejecutamos el interpretador:

 var myContext = new context();
 myContext.setContext('get http://jsonplaceholder.typicode.com/posts/1 => data');
 
 console.log(data);

Gracias al dinamismo de JavaScript la variable data es creada conteniendo el valor resultante de la llamada.


Cadena de responsabilidad con JavaScript

Ya que estamos por acá y hacía mucho que no publicaba nada, vamos con un ejercicio práctico rápido.

Una de las cosas que me gustan, y mucho, de escribir código son los patrones de diseño. Esas piezas de código que solucionan algún problema particular de forma elegante.

Hay miles, pero tal vez los más recordados sean los propuestos por el GoF. Patrones que muchas veces usamos sin saberlo o hemos escuchado y mal usado (Porque es el único que recordamos) en todos lados (Ejem… singleton).

Así que, no vamos a hacer un singleton, si no, una cadena de responsabilidades.

Para este caso, hay un par de formas de hacerla pero a la larga es más o menos lo mismo, así que vamos con una forma bastante clásica. Esto es: Teniendo una clase base particular, creamos otras que tendrán tareas específicas y heredan de la base. En cada una de las clases realizaremos una validación o tarea o “responsabilidad“, para luego pasarle la responsabilidad a la siguiente parte de dicha cadena. Si un eslabón falla, la cadena falla. Es un todo o nada.

Suele ser muy útil para validar contraseñas o aplicar reglas a un objeto, tener las reglas separadas y encapsuladas (No una masa de ifs) y poder encadenar dicha cadena de la forma en que nos de la gana. Incluso por código, pudiendo cambiar el comportamiento de la misma sin tener que modificar línea alguna.

En este caso, para ahorrarme algo de código he usado la librería ExtendJS, que permite crear una herencia al estilo de lenguajes como Java o C#, pero por debajo usa prototipos y demás dulzuras de JavaScript.

Lo primero, la clase base:


var chainBase = Class.extend(function(){
this._next = null;
this.goNext = function (value) {
if (this._next !== null) {
this._next.validate(value);
}
};
this.validate = function (value) {};
});

La clase base tiene una propiedad _next donde alojaremos el siguiente eslabón de la cadena, una función goNext para ahorrarnos escribir el código de movernos por la cadena en cada eslabón y una función validate que luego será sobre escrita en las demás clases.

var charMin = chainBase.extend(function () {
this.super();
this.validate = function (value) {
if (value.length < 3) {
throw "No es sufientemente largo";
}
this.goNext(value);
};
});

El primer eslabón se encarga de validar que el largo de nuestro texto a validar no sea superior a los 3 caracteres. Si todo está en orden entonces pasará la tarea al siguiente. Por lo que necesitaremos otro eslabón.

var charMax = chainBase.extend(function () {
this.super();
this.validate = function (value) {
if (value.length > 10) {
throw "Es muy largo";
}
this.goNext(value);
};
});

Este verificará que el largo no supere los 10 caracteres y si todo está bien, pasará al siguiente eslabón.

Podremos crear tantos validadores como creamos necesarios y luego enlazarlos.


var a = new charMin(),
b = new charMax();
a._next = b;
a.validate('abcd');


El indie no profesional

El año pasado escribía una nota para la revista digital Metropía sobre el mundo indie del desarrollo de videojuegos. Lamentablemente la revista aparentemente dejó de publicarse y la nota nunca llegó a hacerse visible.

Dejo a continuación esta nota que no pudo ver la luz.

El indie no profesional

En el anterior artículo hacía referencia a que todo lo que hacemos, aunque hagamos videojuegos, se refiere a código y que podemos gestionar el desarrollo de nuestra criatura mediante las prácticas que han sido implementadas por esta profesión; la del desarrollo de software.

Y que si bien podemos tener una gran carga de componentes visuales, o que el peso de nuestro videojuego esté sobre el arte y no el código, no quita que no podamos manejarnos de forma ordenada y gestionar correctamente el proceso. Concluíamos en ese momento, entonces, que todo era software.

Ahora, podemos haber seguido el manual, tener nuestras herramientas de software listas, pretender usarlas, pero así y todo fracasar. Aunque aquí es necesario hacer un pequeño paréntesis, ya que no hay una fórmula del éxito (Aunque algunos quieran hacernos creer que sí existe) ya que aquello que le sirvió a uno para alcanzar ese éxito, puede ser totalmente irrelevante o contraria al mismo para otros; por lo que en lo que se refiere al fracaso, podemos hacerlo de tantas formas como podamos imaginar, aunque hay una que es una garantía: La falta de profesionalismo.

 

La manada indie

Y es que cuando hablamos de indies, por lo menos en estas zonas, es normal encontrarnos con un grupo de personas (2 o 3) que optaron por juntarse para hacer un videojuego. Muchas veces, sin experiencia en la producción de una cosa, más allá del haber trabajado de forma independiente sobre proyectos personales donde los tiempos no fueron medidos, las relaciones interpersonales no se ejercitaron, las costumbres no se afianzaron y así una larga lista de atributos que se requieren desde lo profesional y que nunca se pusieron en práctica. No somos más que un grupo de felinos que se juntaron momentáneamente para darle caza a un animal grande, pero que ninguno de los gatos involucrados ha cazado más que pequeños ratones.

Nos juntamos como una manda de individuos queriendo hacer que nuestras personalidades sean las que estén por arriba de las otras. Pretendiendo liderar al grupo cuando todos estamos pretendiendo lo mismo porque, en definitiva, el ratón que cazamos alguna vez nos pareció el más terrible adversario que jamás alguien haya cazado.

Por supuesto, esto es un camino al fracaso por obvias razones: Cada miembro del grupo pretendiendo que las cosas se hagan a su manera, desoyendo al resto.

Pero hay un fracaso aún peor: Que el proyecto salga relativamente bien.

Y es que, como decíamos al principio, puede que lo que funcione para unos no lo haga para otros y de igual forma en sentido opuesto. Tal vez el peor escenario, entonces, sea que un grupo sin experiencia alguna y con condiciones como las descritas tenga un relativo éxito. Al hacerlo, las malas prácticas se instaurarán y serán el patrón a seguir para futuros proyectos.

Imaginemos a un niño que mete sus dedos en el enchufe, pero en ese momento no había electricidad. Luego, toca un cable pelado, pero tampoco había electricidad. Este niño ha aprendido que tanto meter los dedos en el enchufe como tocar cables pelados no representan peligro alguno. Un día, decide tocar una línea de alta tensión sin fallas: El resultado es evidente.

 

El profesional

Tratando de no generar una fórmula sobre el “cómo ser profesional”, vamos a generar una lista de actitudes que podríamos considerar profesionales a la hora de encarar un proyecto, en especial, sobre las conductas. Pero como la idea es no tomarlas como LA FORMULA, todas son objetables y pueden ser tiradas a la basura con total tranquilidad.

1) Comunicar.

¿No compartes tus ideas y planes del proyecto con el resto del equipo? ¿Consideras que es más fácil hablar contigo que con los que te rodean? ¿Prefieres tomar las riendas con el cliente y luego avisarles al resto del equipo lo que hayas decidido (Sin consultar antes)?

Si respondes con un sí, o con un “a veces”, entonces estás en problemas. Si eres parte de un equipo, y el equipo también debe trabajar en el proyecto, pretender dejarlo de lado en decisiones en las que ellos también estarán involucrados, entonces no estás siendo profesional.

Imagina una situación en la cual estás muy tranquilo en tu casa, jugando a ese juego que tanto amas y repentinamente te desconectan tu consola o computadora y se la llevan. Cuando preguntas, resulta que tu compañero/a, amigo/a, esposo/a (Bueno, se entiende), decidió vender ese aparato porqué necesitaba el espacio para colocar la foto del perro (Vale aclarar que el marco de la foto es hermoso).

En un paralelismo, no te sentirías muy a gusto si alguien en tu equipo te avisara que estás atrasado en el proyecto simplemente porque él decidió, junto al cliente, que era mejor adelantar la fecha de entrega dos semanas. O, que tu decidiste, el último día, cuando había que entregar todo, que necesitas dos semanas más porqué te diste cuenta que no llegabas con los tiempos pactados.

2) Compromisos.

Así como una buena comunicación es parte del compromiso como profesionales, existen cientos de forma de faltar a los compromisos. Desde no cumplir con una fecha de entrega hasta no llegar a tiempo a una reunión.

Puedes poner a prueba que tan comprometido estás con el proyecto analizando cuantas veces has llegado a una reunión en el horario que se había estipulado. Aquí no hablamos de salidas nocturnas, casamientos o cumpleaños, donde no queremos ser los primeros en llegar y por lo tanto tendemos a aparecernos 30 minutos (O más, mucho más) más tarde que la hora pactada. El tiempo cuesta dinero, tanto dentro de nuestro equipo como para un cliente, por lo que esperarnos es un problema, así como lo es esperar a alguien.

Es común en la gestión de proyectos (Y dependiendo del marco de gestión utilizado) realizar reuniones diarias para sincronizar el equipo, el no asistir o necesitar que tu jefe, administrador, compañero, etc., deba buscarte para que asistas, es otra demostración de falta de profesionalismo.

3) Estimaciones.

Sumado a la idea anterior de compromiso, la ausencia de profesionalismo se denota en aquellos que al recibir una tarea comienzan desenfrenadamente a realizarla sin agotar dudas y peor aún, sin haber estimado el tiempo necesario para realizarla.

Parte de la gestión de un proyecto se centra en conocer el tiempo necesario para desarrollar parte o la totalidad de la cosa a producir. El tiempo es traducido a dinero. Si necesitamos mucho tiempo para producir algo, este tiempo requerirá de un volumen de dinero diferente a si tardamos poco. También, tardar mucho puede impactar en la salida al mercado donde competidores podrían obtener un producto similar antes y ganar clientes primero, lo que nos impactaría en nuestro bolsillo. Por último (Aunque hay más variantes), mucho tiempo estimado de producción pero una necesidad de salir antes al mercado con el producto, hace que se analicen las posibilidades de recortar el producto o de gastar más dinero por medio de más gente produciendo la cosa y que esta esté lista antes.

En definitiva: Saber estimar el trabajo es vital.

4) Calidad.

La calidad no se resume en que tan bien sabemos dibujar y pintar, o si nuestras líneas de código se ven armónicas. La calidad incluye otros factores más allá de las habilidades adquiridas con la práctica.

Si somos artistas, no realizar una revisión de lo pedido, si cumple con todos los puntos que el cliente espera; nombres de archivos, orden de capas en un PSD, haber entendido y aplicado todo lo descrito en los requerimientos. Es sinónimo de falta de profesionalismo.

De igual forma, en el código, el entregar funcionalidades incompletas o con errores, incurre en problemas similares. Por supuesto somos falibles y el cansancio después de horas de trabajo, distracciones cotidianas y demás hace que cometamos errores, y son esperables. De cualquier manera, existen límites dentro de esos errores.

5) No aprender.

Tal vez todo lo anterior es subsanable ya que con el error, con la equivocación aprendemos. El problema mayúsculo está cuando no aprendemos. Repetir una y otra vez las mismas acciones esperando que haya un cambio es una locura, pero también es clara señal de que no estamos aprendiendo de nuestros errores. Si no podemos aprender, no podremos cambiar nada de lo anterior.

Pero no siempre se debe a nosotros sino a ambientes que impiden equivocarse. Mejor dicho, que prohíben equivocarse. Si bien no es lo mismo equivocarse en algo que pueda causar una catástrofe a equivocarse en la cantidad de balas que salen de un enemigo en un videojuego. De cualquier manera, existen lugares, tanto en los que podemos estar como en los que podemos estar promoviendo, donde la equivocación se castiga de forma severa. Tan severa que genera estancamiento en las personas: Al tener un miedo terrible a equivocarse, nunca tomarán una decisión esperando que el castigador las tome por él.

Lo anterior impacta en prácticamente todo; no estimaré mi trabajo porque si me comprometo y me equivoco me castigarán; no comunicaré que estoy atrasándome debido a que tengo muchas distracciones porque me castigarán.

Dejar equivocarse es importante y al mismo tiempo entender en qué nos hemos equivocado es más importante aún.

En resumen

Por supuesto, hay muchos otros elementos que nos acercan al profesionalismo. Por otro lado, ser profesional no quita que nos podamos divertir y pasarla bien haciendo videojuegos, pero es necesario que nos tomemos seriamente el desarrollo de nuestro videojuego. No importa si somos un único individuo o si somos 10, mientras nos comportemos y actuemos profesionalmente. No hagamos que esa idea creativa sea manejada por una manada que se asocia casualmente, si no en un equipo que quiere conseguir un videojuego de verdad.


Nuevo libro sobre desarrollo de videojuegos

Mtapaucho tiempo sin publicar nada en el blog. El motivo: Estar escribiendo un nuevo libro durante los últimos 6 meses.

Este nuevo libro es sobre desarrollo de videojuegos con HTML5 y JavaScript. En este podremos aprender a crear nuestros propios frameworks, usar otros como Phaser, entender los conceptos detrás del desarrollo de videojuegos y mucho más.

El libro está pronto a salir (Mediados de Abril) y estará disponible en todas las librerías del país, así como en la mayoría de los países de habla hispana. Por supuesto, se podrá comprar online.


El juego de fin de año

Técnicamente, no es un juego nuevo. Por cuestiones de tiempo no he podido terminar uno que tenía en proceso de creación. Ese tiempo se ha consumido en un regalo que vendrá en unos meses ya que he estado escribiendo un nuevo libro, esta vez, sobre desarrollo de videojuegos.

De cualquier manera, durante la segunda parte del año sí he creado algunos juegos que no necesariamente he publicado aquí. Este juego en particular surgió en un Beers & Indies, y mutó hasta lo que es hoy. Se presentó en la EVAx y luego en Fenómeno Cósmico.

Les dejo: The Hunt for JongoJongo.

Para jugarolo: http://gamejolt.com/games/the-hunt-for-yongoyongo/83260


Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 1.526 seguidores