Mostrando las entradas con la etiqueta javascript. Mostrar todas las entradas
Mostrando las entradas con la etiqueta javascript. Mostrar todas las entradas

14 agosto 2012

Jugando con jQuery Deferred


El objeto Deferred es una característica poco conocida de jQuery que permite escribir menos código. Veamos como aprovecharlo.

Todas las funciones AJAX en jQuery retornan un Deferred, y por lo tanto:

$.ajax({url:'/api/users', success:function(d){console.log(d)}});

se puede escribir como:

$.ajax({url:'/api/users'}).done(function(d){console.log(d)})

El cambio es sutil pero simplifica algunos casos engorrosos. Por ejemplo esperar el resultado de multiples llamadas AJAX:

var usersRequest = $.get('/api/users');
var settingsRequest = $.get('/api/settings');

jQuery.when(usersRequest, settingsRequest).done(function (users, settings) {
    console.log(users);
    console.log(settings);
});


O simplificar código mediante null objects:

var request = (shouldUpdate) ? $.post('/api/user', userData) 
                             : jQuery.Deferred().resolve();
request.done(function() { doSomething() });

04 abril 2012

Amber Smalltalk

Después de mucho tiempo volvi a ver el blog de James Robertson, donde me encontre con Amber Smalltalk: una implementación de Smalltalk hecha en JavaScript.

Seguramente la pregunta práctica es: ¿A quien le puede interesar interpretar Smalltalk con JavaScript?

Más alla de la respuesta obvia de: a los fanáticos de Smalltalk; hay algunos buenos casos donde Amber resulta interesante:

<modalidad-fanatico-smalltalk>
  • Enseñanza: Uno puede incrustar un classbrowser junto con una pagina tutorial, y usarlo para dar clases de programación orientada a objetos: los alumnos solo necesitan un browser.
  • Producción: Si existiesen las herramientas apropiadas, uno podría usar un entorno de objetos para desarrollar y luego exportar todo a un JavaScript minimizado y listo para usar con NodeJS o en un browser. (El gran obstáculo: las diferencias de sintaxis JavaScript/Smalltalk, JObjectProxy luce feo para quienes están acostumbrados al encadenamiento de mensajes en jQuery o el syntax sugar de CoffeScript).
</modalidad-fanatico-smalltalk>

De vuelta en mi modalidad realista.

Por ahora es un lindo experimento para ver, que demuestra una vez más como JavaScript se esta convirtiendo en el "assembler" de la web. 

Hay dos características de Smalltalk que lo convierten en un lenguaje unico, y son también su maldición:
  1. El "ambiente de objetos". Para que cualquiera que haya trabajado un tiempo considerable con Smalltalk volver a los archivos y las herramientas de build es como volver a la pre-historia.
    Sin embargo es una maldición por que aparta al lenguaje de todo el resto del mundo: usar herramientas existentes de versionado o editores comunes se vuelve doloroso y poco práctico.
  2. La sintaxis de message keywords es una camino de ida :)  y es una de las cosas que más extraño en otros lenguajes orientados a objetos: realmente ayuda a pensar en términos de objeto/mensaje.
    El lado negativo es que la diferencia de sintaxis complica la interoperabilidad con lenguajes tipo C como JavaScript.
    Creo que en este sentido los smalltalkers fueron muy conservadores: la sintaxis de Smalltalk es uniforme y genera cierto orgullo. Orgullo que debería dejarse de lado: las características menos elegantes de Groovy o Ruby resultan mucho más prácticas.
Mientras tanto voy observando la evolución de Dart, quien sabe quizas con sus snapshots logre lo que Smalltalk no pudo: lograr una tregua entre el ambiente de objetos y las herramientas basadas en archivos.

03 febrero 2012

Tips de Chrome para desarrolladores web

Trabajando en unas páginas web, descubrí una funcionalidad de Google Chrome que lo convierte en mi browser favorito para el desarrollo web.

Suelo retocar y probar cambios de CSS en el "inspector" de la solapa "Elements".  El problema es copiar los cambios de vuelta al código fuente: no solo es incomodo, si no que a veces me olvido que elementos cambie.

En todo este tiempo no le había dado importancia a la solapa "Resources". La usaba de vez en cuando para ver que un archivo no se se este cargando del cache y cosas por el estilo.

Ayer por casualidad descubrí que los archivos se pueden editar directamente (haciendo click en el botón del lápiz que pueden ver  en la imagen).

Pero lo bueno recién comienza: si hacen cambios estos se ven de forma instantánea en la pagina; si "graban" (Ctrl-S o Cmd-S en Mac) van a poder ver la historia en el editor que además muestra los cambios con colores.




Obviamente el archivo no se guarda en el servidor, pero haciendo botón derecho pueden hacer un "Save As..." y guardarlo.

Probablemente no sea algo nuevo, pero descubrirlo me ahorro tanto tiempo que me dieron ganas de bloggearlo :)

Nota: Firebug también tiene una funcionalidad similar, aunque sin historial de cambios y con una UI un poco más incomoda a la hora de editar.

14 septiembre 2011

Herencia en JavaScript

JavaScript es en esencia un lenguaje basado en prototipos, que sufre de personalidades múltiples: tiene algunos operadores y comportamientos de un lenguaje con clasificación.

Para entender esto olvidemos por un momento a JavaScript.

Un lenguaje orientado a prototipos -como por ejemplo Self- se basa en que uno obtiene nuevas instancias a partir de la clonación de otras, por ejemplo en un "pseudo-JavaScript":

var auto = {
     acelerarACienEnUnSegundo: function() { return 'No puedo'; },
     arrancar: function() { return 'brummm... :)' }
};

var ferrari = clonar(auto);
ferrari.acelerarACienEnUnSegundo = function() { return 'fiuuummm'; };
ferrari.arrancar(); // retorna brummm....

¿Donde esta la esquizofrenia de JavaScript? Esta en que contamos con un operador new que simula comportarse como si estuviésemos trabajando con un lenguaje con clasificación, por ejemplo:

var auto = new Auto();
function Auto() {
     this.arrancar = function() { return 'brummm....'; };
}

¿Qué hace new?
Cada función que uno define en JavaScript es un objeto que tiene asociada una propiedad prototype.
Es como si cuando uno escribe function Auto() {} escribiera:

var Auto = {
    prototype: {}, 
    constructor: function() { /* cuerpo de la función Auto */ } };

Cuando se usa el operador new JavaScript lo que hace es:

  • Clonar el objeto prototype
  • Después evaluar la función en constructor usando la nueva instancia como contexto (es decir this es el clon de prototype)

Es por eso que uno podría escribir la función Auto como:

function Auto() { console.debug(this.arrancar); }
Auto.prototype.arrancar = function() { return 'brummm....'; }; 

Esto es muy confuso, por que pareciera que una función se puede comportar como si fuese una clase. De hecho genera más confusión aún cuando uno quiere compartir implementación usando algo similar a la herencia.

Sin embargo el problema es más simple de resolver: no hay clases ni tipos, solo tenemos que agregar los métodos que necesitamos compartir, por ejemplo:

var agregarComportamientoDeAuto = function(obj) {
      obj.arrancar =  function() { return 'brummm... :)' };
}

¿Como creamos un objeto que se comporte como un auto?

var ferrari = function() {
      var nuevaInstancia = {};
      agregarComportamientoDeAuto(nuevaInstancia);
      nuevaInstancia.acelerarACienEnUnSegundo = function() { return 'fiuuummm'; };
};

Quizás no luzca muy elegante, pero en mi opinión es mejor que simular un lenguaje con clasificación donde no lo hay.
La ventaja de este método es que es muy fácil crear mixins o tener variables privadas (en el ejemplo podríamos pasar argumentos adicionales a agregarComportamientoDeAuto y aprovechar las clausuras).

También es posible simular delegación estilo "super", la próxima voy a dar un par de ejemplos de eso, pero adelanto que es una solución muy poco elegante.

09 abril 2011

Juego de la vida (2da parte: implementación)


Hecha la introducción sobre el juego de la vida de Conway en el post anterior, paso a contarles algunos detalles de implementación.
No voy a referirme al algoritmo: es el primero que me salió,  en cambio vamos a ver algunas cosas interesantes para aprender de JavaScript y HTML5.


Doctype 
La primer duda que me surgió a la hora de escribir el HTML5, es ¿Qué DOCTYPE uso?
Quienes recién comienzan con HTML quizás no entiendan esta duda, es una larga historia resumida de forma excelente en "Dive into Html 5": http://diveintohtml5.org/semantics.html#the-doctype .

En pocas palabras, el DOCTYPE que debe usarse en HTML5 es simplemente: <!DOCTYPE html >


Progressive Enhancement
Progressive enhancement es una técnica que consiste comenzar con el contenido, usando los tags de HTML para estructurarlo (títulos, párrafos, listas, etc) y luego ir agregando el diseño y "comportamiento" mediante CSS y JavaScript.

Pueden encontrar una buena introducción en este articulo.

Claro que en la pequeña aplicación JavaScript no hay contenido :), en fin el objetivo era aprender y practicar técnicas útiles para el desarrollo web.


CSS
Los stylesheets son sumamente engorrosos de mantener. Afortunadamente existen lenguajes de macros que permiten generar stylesheets usando constantes y funciones.
Uno de ellos es LESS, que lo elegí por dos razones: pueden usar JavaScript en el cliente para hacer pruebas y para aplicaciones Java cuentan con un servlet.
Otra alternativa para quienes usan Ruby es Sass.


Canvas y gráficos dinámicos
Para los gráficos comence usando un Canvas.
Lamentablemente el API de Canvas es en cierto sentido de "bajo" nivel: provee primitivas para dibujar directamente, pero carece de algunas abstracciones convenientes.
Luego de frustrarme (por alguna razón que no pude encontrar, los gradients en el stylesheet que uso modifican el estilo de dibujo del Canvas... algo muy engorrozo que me paso tanto Chrome como en Firefox) decidí buscar algun framework JavaScript que me facilite las cosas.
Entre los frameworks que estube mirando me encontré a gusto con raphaeljs.
No usa Canvas si no SVG (que al parecer no esta disponible en algunos browsers para smartphones).
Pero el API me pareció simple e ideal para hacer visualizaciones en HTML.


Local storage
Guardar y retornar información local en HTML5 es extremadamente fácil:

localStorage.setItem("key", "hello");
var value = localStorage.getItem("key");

Claro que este "map" es bastante rudimentario, hay otras opciones pero funcionan solo en ciertos browsers.
Aunque no lo use en este ejemplo, también pueden proveerle al browser información de que archivos mantener localmente para que la aplicación funcione offline.


Debugging y profilling
Con la ayuda de Diego Camera, conoci algunas herramientas de debugging y profiling de Google Chrome.
Tanto si usan Chrome o no, cuentan con la extensión FireBug que les agrega un API de consola extremadamente útil para hacer debugging y profiling (en Chrome no necesitan instalar una extensión para acceder a este API).

Para destacar: console.dir(object) les permite inspeccionar rápidamente el objeto pasado como parámetro.

Una cosa que me gusta de trabajar con estas herramientas es que me dio casi la misma sensación que en Smalltalk: uno puede inspeccionar y modificar en "entorno" en cualquier momento. Quizás en algún momento con proyectos como Ace (antes Mozilla Bespin/Skywriter) y  Eclipse Orion se llegue a lo que hacían los entornos de Smalltalk hace más de 20años ;-)

Para terminar....
Este post solo tiene algunas "puntas" a mirar para aprender más sobre JavaScript y HTML5.

Si están interesados en hacer algo para aprender, la implementación del juego de la vida que presente en el post anterior tiene muchas cosas pendientes, y con distintos niveles de complejidad:
  • Cada celda tiene su propio event handler, se podría usar un unico event handler para ahorrar recursos.
  • Las celdas se pintan haciendo click, lo cual es bastante incomodo si quieren pintar más de una celda. Se podrían cambiar los event handlers para permitirlo.
  • La función de "Save/Load" solo permite grabar una instancia, se podria modificar para soportar mas de una.
  • Seria útil poder insertar patrones de celdas predefinidos
  • Se puede cambiar la implementación para usar el tag canvas en lugar de raphaeljs
  • ... y si son unos "grosos" de los algoritmos, podrían simular que el "mundo" es infinito en lugar de hacer la simplificación que hice

05 marzo 2011

Juego de la vida (1ra parte)


Hace poco, conocí a través del libro "El gran diseño" de Stephen Hawking, el "juego de la vida" de Conway.

Este "juego" -entre comillas- me resultaba conocido, ya que en alguna vieja distribución de Linux, había visto algo similar. Pero hasta hace unos días no tenia ni la menor idea de que se trataba.

Pero basta de misterios, les cuento muy brevemente de que trata.

La idea es que uno tiene una gran grilla con celdas. Las celdas tienen una configuración inicial: vivas (activadas) o muertas (desactivadas). A partir de esta configuración inicial se deja correr el tiempo -que son pasos discretos. A cada paso se determina que celdas nacen o mueren según unas reglas muy simples:


  • Si la celda esta viva pero no tiene vecinos: , en la siguiente generación muere:   
  • Si la celda esta viva pero tiene entre 2 o 3 vecinos: , en la siguiente generación permanece viva: 
  • Si la celda esta muerta pero tiene 3 vecinos: , en la siguiente generación se transforma en una celda viva: 
  • Si la celda tiene más de 3 vecinos, muere.

Notar que cuando se evalúa el estado de las celdas, es como si se sacara una foto: las reglas se evalúan en base al estado de esa foto.

Hasta acá nada interesante, ¿Donde esta la gracia de todo esto?
La gracia esta en que dependiendo de la configuración inicial, si uno deja correr el "tiempo" las celdas cobran vida. Hasta el punto que es posible simular una maquina de Turing!

El aprendizaje de todo esto, es que "formas de vida" muy simples pueden dar lugar a comportamientos muy complejos. Algo que menciona Douglas Hofstadter en su libro Gödel-Escher-Bach cuando hace la analogía entre las neuronas y las colonias de hormigas.

Como ven esto es algo muy interesante y simple de implementar a la vez :)
Por eso lo use como excusa para hacer algunos experimentos con JavaScript, experimento que pueden bajar de este link.

Nota:
El link contiene un WAR (Java Web Application Archive) que no es más que un archivo .zip.
Pero no necesitan Java, ni Tomcat o Jetty para probarla.
La razón por la que use un WAR es la siguiente: quisé hacer tambien el experimento de usar LESS (un lenguaje de macros para CSS -altamente recomendable).
LESS incluye una version JavaScript que pueden usar en el cliente... pero desafortunadamente usa un XMLHttpRequest para bajar el CSS, y por razones de seguridad browsers como Chrome lo filtran.
Por eso termine haciendo una aplicación web, que usa un servlet para LESS (tenia otras opciones, pero quería probar LESS y esta opción era más sencilla que instalar Node.js en Windows).
El uso de LESS no es necesario, pueden jugar con el ejemplo sin necesidad de levantar una aplicación web: abran directamente el archivo index.html dentro del war.
En el próximo post les cuento como desarrolle esta pequeña implementación (que usa jQuery, Raphael y local storage).

Mientras tanto les recomiendo jugar con patrones como este (pueden usar la opción de Save/Load para guardar/recuperar el patrón del local storage):