Una ¿pequeña? pausa

Antes de irme de vacaciones en agosto, estaba dedicandole bastante tiempo a sacarle punta a mis conocimientos de javascript. En el estudio estaban dejando de entrar projectos en los que el target era el reproductor de flash y eran cada vez más los clientes que pedían las funcionalidades de este, pero en aplicaciones programadas en javascript (ya sabéis: … ¿y esto no se puede hacer en HTML5? ….(sigh!) … sí claro que sí). Por eso me pareció oportuno darle un repaso a los fundamentos, a la vez que los compartía con mis compañeros y con vosotros.

A la vuelta de las vacaciones la situación cambió radicalmente. Tanto que, de momento, no voy a poder acabar la serie sobre javascript y los fundamentos de los prototipos. Espero poder hacerlo en un futuro próximo, y que los que habéis empezado el camino con mis articulos podais seguirlo con las referencias que incluyo en ellos.

Por un tiempo voy a estar estudiando C# y su uso en el entorno de Unity3D. Ya había tenido contacto con C#, pero sólo superficial. La verdad es que está resultando estimulante redescubrir el lenguaje, y no tardaré en compartir algunas sus joyas.

En este momento estoy disfurtando de este libro:

C# in depth por Jon Skeet.

Altamente recomendado para programadores iniciados o expertos.

Todos los objetos en Javascript son dinámicos

Arrays, funciones, constructores, prototipos, … Todos son dinámicos y si no tenemos cuidado sufriremos las consecuencias.
Todos los objetos en javascript son dinámicos, lo que quiere decir que en cualquier momento podemos añadir propiedades y métodos a nuestro objeto:

var persona = {
    nombre : 'persona',
    getNombre : function() {
        return this.nombre;
    }
};
// ...
persona.telefono:'91 XXX XX XX';

Las variables de tipo objeto son referencias a un objeto, y se pasan a las funciones por referencia, no por valor. Esto hace que para copiar un objeto nos tengamos que inventar algún que otro truco.
Pero sobre todo, nos obliga a ser especialmente cuidadosos:

var pedro = persona;
pedro.nombre = 'pedro';
console.log(pedro.nombre);    // >>> 'pedro'
// Pero, sorpresa !!
console.log(persona.nombre);  // >>> 'pedro'

La variable pedro es una referencia al objeto persona, al cambiar la propiedad nombre en pedro estamos cambiando, en realidad, el objeto persona.

Pregunta: ¿Dónde están las clases en Javascript? (I)

Respuesta: No hay.
Javascript es un lenguaje basado en prototipos, no en clases. Eso lo tengo claro. Lo que son los prototipos ya es otro cantar, y de eso es de lo que quiero hablar.

Antes de empezar debe quedar claro que estas líneas son el resultado de mi intento por entender el tema; y sin ser ningún experto y teniendo en cuenta que el cacao de tutoriales, guías y manuales que hay desperdigados por la red son en su mayoría una soberana $&@#~… espero que estas notas despejen algunas dudas. Al menos a mi me han ayudado a centrar mi compresión del lenguaje. Sobre todo para lo que era mi objetivo: ser capaz de hacer lo que ya era capaz de hacer en actionscript.

Para empezar, parece que la mejor manera de entender la herencia basada en prototipos es olvidarse de todo lo que sabemos de herencia basada en clases y empezar de cero.

Continuar leyendo “Pregunta: ¿Dónde están las clases en Javascript? (I)”

Interfaces en Javascript

Una de las primeras cosas que he echado de menos en javascript son las interfaces. Ya sé que la mayoría de los programadores de Javascriot no sabéis lo que son. Seguramente en algún rato libre escribiré sobre ellas con más detalle.
De momento, baste decir que son tremendamente útiles cuando ouno intenta implementar patrones de diseño como el Strategy o el Command. Y son, de hecho, una de las piedras angulares de la programación orientada a objetos en cualquier lenguaje.
En javascript no existen :-(. Pero hay formas, más o menos retorcidas, de implementar algo parecido. (Ver Pro Javascript Design Patterns, de Ross Harmes y Dustin Diaz, Apress 2007).

// Constructor.
var Interface = function(name, methods) {
    if(arguments.length != 2) {
        throw new Error("Interface constructor called with " + arguments.length +
            "arguments, but expected exactly 2.");
    }
    this.name = name;
    this.methods = [];
    for(var i = 0, len = methods.length; i < len; i++) {
        if(typeof methods[i] !== 'string') {
            throw new Error("Interface constructor expects method names to be "
                + "passed in as a string.");
        }
        this.methods.push(methods[i]);
    }
};
// Static class method.
Interface.ensureImplements = function(object) {
    if(arguments.length < 2) {
        throw new Error("Function Interface.ensureImplements called with " +
            arguments.length + "arguments, but expected at least 2.");
    }
    for(var i = 1, len = arguments.length; i < len; i++) {
        var interface = arguments[i];
        if(interface.constructor !== Interface) {
            throw new Error("Function Interface.ensureImplements expects arguments"
                + "two and above to be instances of Interface.");
        }
        for(var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++) {
            var method = interface.methods[j];
            if(!object[method] || typeof object[method] !== 'function') {
                throw new Error("Function Interface.ensureImplements: object "
                    + "does not implement the " + interface.name
                    + " interface. Method " + method + " was not found.");
            }
        }
    }
};

Para utilizarlas hay que instanciar primero la interfaz, pasando los métodos que ha de implementar cualquier clase que la utilice:


var IPajaro =  new Interface('IPajaro', ['anda', 'vuela', 'diAlgo']);

Cuando creemos la clase Pato deberemos implementar, como mínimo, los métodos especificados en el Array del segundo parámetro:


var Pato =  function () {	// Implementa la interfaz IPajaro
	var cuack = function () {
		// Implementación del método cuack
	}
	
	this.anda = function () {
		// Implementación del método andar
	};
	this.nada = function () {
		// Implementación del método nadar
	};
	this.vuela = function () {
		// Implementación del método volar
	};
	this.diAlgo = cuack;
}

¿Por qué querríamos hacer esto? Porque si queremos hacer nuestro código realmente flexible querremos utilizar cualquier tipo de pájaro en nuestro código, y querremos comprobar que cuando usemos un pájaro implemente realmente los métodos que queramos lanzar.
Si no utilizamos la interfaz, la única manera eficiente de hacerlo es comprobar si el presunto objeto pajaro es una instancia de Pato, o de Aguila, o de Cuervo,… mal asunto, porque podemos tener muchos pájaros definidos, ¿Los vamos a comprobar todos? ¿Tendremos que escribir código específico para cada uno de ellos cada vez que queramos utilizar una de sus instancias?…

Para eso sirve una interfaz: establece un contrato para la API de un conjunto de objetos con características comunes, de forma que todos los que implementan la misma se puedan utilizar indistintamente en las partes de nuestro código que no necesiten saber cuál de ellos es exactamente. Así que si queremos hacer volar cualquier pájaro (y en nuestro caso concreto lo que tenemos es un pato) sólo tendremos que hacer lo siguiente:

var vuelaPajaro =  function (pajaro) {
	// Lanza un error si pajaro no implementa los métodos de IPajaro
	Interface.ensureImplements(pajaro, IPajaro);
	pajaro.vuela();
};

var patitoFeo = new Pato();

vuelaPajaro(patitoFeo);

De esta forma la implementación de la función vuelaPajaro() no depende de si el pájaro es un Aguila, un Pato, un Grajo, etc. y al mismo tiempo nos estamos asegurando de que al menos implementa los métodos necesarios para poder utilizarlo como un pájaro.

Lo que la gente piensa que es el HTML5.

Cliente: ¿Y por qué no lo hacemos en HTML5? Así será compatible con todos los navegadores ¿no? Porque Flash es una mierda, ya lo decía Steve Jobs.

Programador: Sigh!

Pues sí, gracias Steve Jobs, por hacernos la vida un poco más complicada a los programadores, especialmente a los que nos hemos estado dedicando a la programación de front-ends en la web.

Poco sentido tiene ya lamentar la caterba de sinsentidos y estupideces que la gente argumenta en contra de Flash, el mal está hecho. Queramos o no, los que vivimos de esto ya nos hemos visto obligados a aprender HTML5 (+javascript +CSS).

Sólo quiero puntualizar una cosa respecto al pasado. Siempre han existido buenos programadores (los que se preocupan por entregar un trabajo bien hecho, por aprender y entender lo que hacen, y por hacerlo cada vez mejor) y chapuzas (la mayoría, siento ser así de pesimista). Juzgar una plataforma de desarrollo (Flash) y los lenguajes de programación asociados a ella (ActionScript y Flex) por los trabajos mal realizados en ella es muy triste.

Respecto al presente, tengo varias cosas que decir. HTML5 no es ninguna panacea. Más bien todo lo contrario (¿hay algún potencial cliente leyéndome?). No se pueden desarrollar aplicaciones en HTML5 por sí sólo. Necesitas combinarlo con CSS y javascript para convertirlo a algo que se parezca remotamente a lo que se puede hacer en Flash. Y por cierto, el nivel general de lo que se escribe por ahí en javascript es todavía más lamentable del que se ve en Flash.

Desde el punto de vista técnico estas son las desventajas:

  • HTML5 no es aún un estandar: Sólo lo soportan las últimas versiones de los navegadores más modernos. Cada uno de ellos lo implementa a su manera, y lo que funciona en unos , no funciona en otros, (o funciona distinto, que es casi peor)
  • Con CSS3 pasa tres cuartos de lo mismo.
  • Con javascript también. Añádase que es un lenguaje basado en prototipos y no en clases. Esto no es en sí una desventaja, pero sí que lo es que la mayoría de los programadores medianamente serios están formados en lenguajes basados en clases. Añádase que no soporta comprobación estricta de tipos (tampoco un gran problema, pero multiplica los errores y complica el desarrollo de aplicaciones complejas). Añádase que es un lenguaje interpretado y que el rendimiento de la aplicación depende del navegador que se utilice para ejecutarla… En fin, no sigo por que la lista es larga.

Concluyendo, y espero que esto sí que lo lea algún cliente, el tiempo de desarrollo se multiplica por un factor que va de 3 a 5, y por tanto el precio también (si es que se espera un mínimo de calidad en el producto).

A pesar de todo esto (y es que soy bastante pesado y cascarrabias) yo estoy feliz con el cambio. Estoy aprendiendo un lenguaje nuevo y eso me divierte. ¿Qué más se puede pedir? No, si al final le voy a tener que dar las gracias a Steve Jobs.

Yet another slideshow

Debe de haber cientos de códigos para descargar y hacerse un slideshow en flash. Pero, en parte porque quería practicar mis recién aprendidos patrones de diseño y en parte porque en Le Petit Kolhos necesitábamos uno que pudiera funcionar desde dentro de wordpress.com y usando su gestor de contenidos, decidí hacerme el mio. Esto último ha sido un poco trucoso pero está conseguido.
Aquí teneis una pequeña demostración:
[gigya src=”http://www.glantucan.com/LPKslideshow.swf” width=”260px” height=”226px” flashvars=”duration=5&transitionTime=.5&basePath=http://lepetitkolhos.files.wordpress.com/2010/11/&playList=ss_adultos2.jpg;ss_esquinica.jpg;ss_adultos.jpg;ss_plasti04.jpg;ss_plasti03.jpg;ss_plasti01.jpg;ss_plasti02.jpg;ss_adultos4.jpg;ss_fritanga.jpg;ss_medioambiental.jpg;ss_medioambiental2.jpg;ss_adultos5.jpg;ss_talleradultos01.jpg” wmode=”transparent”]

I+D+VS

La exposición I+D+VS en "La arquería", con nuestro interativo de fondo.

El grupo de invesgación NuTAC (Nuevas Técnicas, Arquitectura y Ciudad) de la UPM nos ha encargado a través de el descampao la programación de una proyección interactiva para la exposición I+D+VS. Futuros de la Vivienda Social en 7 Ciudades, que a través de ocho ejemplos de proyecto de vivienda social en diferentes ciudades.
Continuar leyendo “I+D+VS”