Una sinfonía en C#

Un pequeño aporte a la comunidad de habla hispana.

Javascript Hoisting, scope de variables

Una característica de Javascript difícil de comprender (sobre todo comprender si es un bug o un feature) es el scope de las variables declaradas dentro de una función.

El intérprete de Javascript mueve las declaraciones al principio de la función.

Esto quiere decir que si yo declaro una variable por la mitad del código de una función su declaración (no la asignación) se mueve al principio, veamos un ejemplo:

var a = 'hola';

function saludar() {
	console.log(a);
	var a = 'chau';
	console.log(a);
};

saludar();

image

En este caso esperamos que le primer mensaje en imprimirse diga “hola” sin embargo dice “undefined” ¿por qué? simple: para el interprete la declaración está al principio de la función, es decir, que lo que en realidad se ejecuta es esto:

var a = 'hola';

function saludar() {
	var a;
	console.log(a);
	a = 'chau';
	console.log(a);
};

saludar();

En definitiva lo importante es tener en cuenta este comportamiento o poner todas las declaraciones al principio.

Nos leemos. Leonardo.

Taller sobre AngularJs en Buenos Aires

Este jueves 6 de Noviembre voy a estar una vez más en las instalación del Microsoft User Group en Buenos Aires, esta vez con un taller sobre AngularJs.

Ejemplos prácticos

El taller se desarrollará a través de 50 ejemplos prácticos, los mismo quedarán publicados en Github.

Le idea es ir avanzando paso a paso con ejemplos para que una vez terminados los dos encuentros tener las herramientas básicas para empezar a trabjar con Angular.

Dejo el link con la información para anotarse. Nos vemos!

Taller en Buenos Aires: Desarrollo ágil con JavaScript. Prácticas, técnicas y herramientas.

El próximo Jueves 5 de Junio estaré en la ciudad de Buenos Aires dando un taller todo el día sobre desarrollo de aplicaciones en un ambiente ágil utilizando JavaScript.

La motivación

Después de leer un interesante post del Tío Bob sobre “La verdadera corrupción de la agilidad” y sumado a esto este hilo en la lista de Ágiles pensé en qué herramientas, prácticas y técnicas del día a día me ayudan a mí en el desarrollo ágil, cómo las adoptamos en el equipo, qué ventajas encontramos, qué limitaciones, cómo se combinan entre ellas y con las metodologías como Scrum, o Kamban.

¿Quiénes puden participar?

Idealmente programadores con conocimientos de JavaScript o que participen en equipo que trabajen con alguna metodología ágil.

¿De qué vamos a hablar?

  • Agilidad, Scrum, XP, Kamban, etc.
  • TDD, Pair programming.
  • UI Test
  • SOLID.
  • Automatización
  • Herramientas como templating, MVC, modularización
  • Git, cómo nos ayuda a gestionar los cambios
  • Más sobre automatización.

¿Por qué JavaScript?

Los últimos dos años trabajé prácticamente todo el tiempo con JavaScript y es un lenguaje cómodo para muchas cosas por su naturaleza dinámica, además no se necesita un entorno particular para ejecutarlo.

¿A qué apuntamos?

La idea es repasar cómo estás técnicas, herramientas y prácticas nos ayudan a soportar los procesos de desarrollo ágil, cuáles son los puntos claves, cuáles los problemas y cómo las adoptamos.

¿Vamos a hacer algo con la máquina?

Sí, vamos a hacer algunos pequeños ejemplos de las herramientas más interesantes.

¿Qué herramientas?

  • Qunit
  • Requirejs
  • Bower
  • r.js
  • Backbonejs
  • Git
  • Rivetsjs
  • underscorejs
  • jquery
  • blanket
  • Phantom

Intentaremos introducir algunas de ellas utilizando Pair programing, Pomodoro technique y TDD.

Ah, y sobre todo vamos a hablar mucho de automatización, automatización, automatización, etc. Guiño

¿Qué queremos llevarnos?

  • Intercambiar opiniones, experiencias y puntos de vista sobre el desarrollo ágil
  • Conocer algunas herramientas que tal vez hayamos escuchado nombrar, sus ventajas, sus limitaciones.
  • Compartir experiencias haciendo desarrollo ágil.
  • Entender cómo nos ayudan las técnicas y herramientas a trabajar de manera ágil.

Entonces la cita está hecha, será el próximo jueves 5 de Junio de 9:30hs a 17:45 en el Microsoft User Group en Buenos Aires Argentina, dejo el link para anotarse en la charla, nos leemos.

Automatic html binding con Rivetsjs

Muchos frameworks nos ofrecen binding automático, two-way binding y cosas así out-of-the-box, en ocasiones no tenemos la necesidad de agregar un framework gigante a nuestra aplicación o simplemente no queremos o es impracticable, en tal caso existe una pequeña pero poderosa utilidad para binding: Rivetsjs.

¿Qué es Rivetsjs?

Es una pequeña utilidad para solucionar un único problema: binding automático, es simple de usar pero tal vez la documentación sea su punto más débil, así que vamos a los ejemplos directamente:

Primero ejemplo, binding simple:

<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script type="text/javascript" src="js/vendor/rivets/dist/rivets.js"></script>
<script type="text/javascript">
	$(function(){
		//definimos un modelo simple, con algunas propiedades
		model = {
			name: "Ariel",
			lastname: "Ortega",
			age: 34
		};
		//indicamos el elemento DOM donde rivets debe bindear el modelo
		rivets.bind($("#view"), model);
	});
</script>
</head>
<body>
<div id="view" >
	<!--los atributos rv-* indican una relación directa entre el modelo y el elemento HTML -->
	<div rv-text="name" ></div>
	<!-- rv-text indica que la propiedad que rivets debe setear es text -->
	<div rv-text="lastname" ></div>
	<!-- en este caso rivets colocará el valor de la propiedad age del model en el text de este elemento-->
	<div rv-text="age" ></div>
</div>
</body>
</html>

Esto no es una gran cosa se puede lograr lo mismo con cualquier motor de templating como underscore por ejemplo (si quisiéramos acceder a un objeto dentro del modelo podemos usar la notación modelo.subobjeto.propiedad), en caso de querer imprimir directamente sin usar un elemento html usamos la siguiente notación:

{propiedad}

(el prefijo de los atributos rv y los delimitadores {} son configurables)

Esto está muy bien pero la parte más interesante es la interesante es lo siguiente.

Escuchar cambios en el modelo

No hay que hacer nada, por defecto rivetsjs ya está escuchando los cambios en el modelo, para comprobarlo vamos a la consola del navegador y comprobamos

image

Como vemos con cualquier cambio que hagamos en el modelo rivetsjs se encarga de actualizar el texto de cada div asociado, estos atributos especiales que usamos para vincular propiedades del modelo con el html se llaman binders en rivertsjs y tenemos varios por defecto:

  • text
  • html
  • enabled
  • disabled
  • checked
  • unchecked

Estos “setean” propiedades en el html, hay otros que sirven para controlar si un elemento se muestra o no, por ejemplo

<div rv-if="show">La propiedad show es true</div>

En este caso si la propiedad show del modelo es true se muestra el elemento, en otro caso no, existen un par de atributos para hacer cosas similares

  • show
  • hide
  • unless

Listas con rivetsjs

Si tenemos un listado y queremos mostrarlo y que, por supuesto, se actualice hacemos:

<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script type="text/javascript" src="js/vendor/rivets/dist/rivets.js"></script>
<script type="text/javascript">
	$(function(){
		//definimos un modelo simple, con algunas propiedades
		model = {
			name: "Ariel",
			lastname: "Ortega",
			age: 40,
			show: false,
			clubes:[{nombre: "River Plate", goles: 80},
				{nombre: "Valencia Club", goles: 9},
				{nombre: "UC Sampdoria", goles: 8},
				{nombre: "Parma FC", goles:3},
				{nombre: "Fenerbahçe SK", goles: 5},
				{nombre: "Newell's Old Boys", goles: 11},
				{nombre: "Independiente Rivadavia", goles: 4},
				{nombre: "All Boys", goles: 0},
				{nombre: "Defensores de Belgrano", goles: 5}
			]
		};
		//indicamos el elemento DOM donde rivets debe bindear el modelo
		rivets.bind($("#view"), model);
	});
</script>
</head>
<body>
<div id="view" >
	<!--los atributos rv-* indican una relación directa entre el modelo y el elemento HTML -->
	<div rv-text="name" ></div>
	<!-- rv-text indica que la propiedad que rivets debe setear es text -->
	<div rv-text="lastname" ></div>
	<!-- en este caso rivets colocará el valor de la propiedad age del model en el text de este elemento-->
	<div rv-text="age" ></div>
	<div rv-if="show">La propiedad show es true</div>
	<div>Clubes y goles:</div>
	<ul rv-each-club="clubes">
		<li><span>{club.nombre}</span><span>:{club.goles}</span></li>
	</ul>	
</div>
</body>
</html>

de este modos, si vamos a la consola y hacemos

var club = model.clubes.pop();

Se actualiza el html, lo mismo si hacemos ahora

model.clubes.push(club);

image

Excelente.

Eventos y two-way binding

La otra mitad del poder de rivertsjs está dada por la capacidad de actualizar el modelo, algo así:

<input type="text" rv-value="age" />

en este caso si cambiamos el valor del input por otro vamos a ver que el resultado se refleja en el modelo.

La otra parte es poder asociar eventos a funciones en el modelo, del siguiente modo

<input type="button" rv-on-click="gritar" value="probar" />

sencillo, con el atributo rv-on-click asociamos el evento click a un método en el modelo, entonces agregamos en nuestro modelo el método gritar y éste será invocado al presionar el botón

Formatters

Los formatters sirven para manipular el modo en que mostramos en el html los valores del modelo, por ejemplo, un valor numérico con decimales, vemos un ejemplo.

<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script type="text/javascript" src="js/vendor/rivets/dist/rivets.js"></script>
<script type="text/javascript">
	$(function(){
		//definimos un modelo simple, con algunas propiedades
		model = {
			name: "Ariel",
			lastname: "Ortega",
			age: 40,
			clubes:[{nombre: "River Plate", goles: 80},
				{nombre: "Valencia Club", goles: 9},
				{nombre: "UC Sampdoria", goles: 8},
				{nombre: "Parma FC", goles:3},
				{nombre: "Fenerbahçe SK", goles: 5},
				{nombre: "Newell's Old Boys", goles: 11},
				{nombre: "Independiente Rivadavia", goles: 4},
				{nombre: "All Boys", goles: 0},
				{nombre: "Defensores de Belgrano", goles: 5}
			]
		};
		
		//agregamos el formatter como un nuevo método a los que ya tiene
		rivets.formatters.clubformatter = function(club){
			return club.nombre + ": " + club.goles;
		};

		rivets.bind($("#view"), model);
	});
</script>
</head>
<body>
<div id="view" >
	<div rv-text="name" ></div>
	<div rv-text="lastname" ></div>
	<input type="text" rv-value="age" />
	<div>Clubes y goles:</div>
	<ul rv-each-club="clubes">
		<li><span rv-text="club | clubformatter"></span></li>
	</ul>	
</div>
</body>
</html>

Básicamente definimos un función y con el pipe (|) dentro de la expresión rv-text indicamos, primero el nombre del modelo (en este caso club, el nombre de cada ítem dentro de la iteración) y a continuación el formatter, lo interesante es que podemos poner varios unos tras otro, agregando más pipies.

En caso de necesitarlo podemos pasar parámetros a los formatters del siguiente modo:

<span rv-text="club | clubformatter param1, param2">

Y el formatter lo recibe así:

clubformatter(param1, param2)

 

Usando propiedades calculadas

En lugar de usar propiedades comunes para asociarlas a elementos del DOM podemos utilizar funciones, por ejemplo:

fullName: function(){
	return this.name + " " + this.lastname;
},

y después lo referenciamos en el html

<!-- el nombre completo está asociado a una función -->
<div rv-text="fullName"></div>

y con eso es suficiente, ahora, hay un detalle, si actualizamos el modelo la función fullName no se volverá a ejecutar, nosotros debemos indicar a rivetsjs que esta función tiene que volver a ejecutarse cuando cambie algo del modelo, en nuestro caso como la función depende del nombre le vamos a indicar que cuando detecte cambios en el nombre la ejecute nuevamente

<!-- el nombre completo está asociado a una función -->
<!-- el símbolo < indica dependencia --->
<div rv-text="fullName < name"></div>

Ahora sí va a cambiar cuando el nombre cambie, en este caso dependemos de el nombre y el apellido así que podemos indicarle todas las dependencias que queramos

<!-- el nombre completo está asociado a una función -->
<!-- el símbolo < indica dependencia --->
<div rv-text="fullName < name fullName"></div>

Como vemos rivetsjs es una linda utilidad para tener en nuestra caja de herramientas, dejo el ejemplo completo acá, nos leemos.

Backbonejs: Rutas

Dijimos que Backbone es especialmente útil para aplicaciones SPA (single page applications) así que vamos a ver un componente que nos ayuda con este tipo de aplicaciones.

¿Qué es una SPA?

Son aplicaciones que transcurren en la misma página, sin ir de una página a otra, un ejemplo típico de Gmail, cuando estamos en la bandeja de entrada vemos un listado de mails, hacemos click en uno de ellos y seguimos en la misma página pero si mirando con atención vamos a notar que parte de la URL ha cambiado, es decir, permanecimos dentro de la misma página pero, de algún modo, hemos ido a un lugar dentro de ella.

Cuando estamos en la bandeja de entrada vemos esta URL

https://mail.google.com/mail/u/0/?pli=1#inbox

Cuando vemos un mail vemos la siguiente

https://mail.google.com/mail/u/0/?pli=1#inbox/145511f0ec63a6d4

Lo que ocurre que por más que cambiemos algo de la URL posterior al numeral ( # ) no se ejecutará la navegación pero nosotros podemos saberlo desde Javascript (y decidir hacer algo), llamamos a esto navegación por anclas.

Navegación por anclas

Un ejemplo muy sencillo de navegación podemos verlo con referencias dentro de la misma página, vamos a Wikipedia para comprobarlo. Ingresamos a la URL del artículo sobre Backbonejs escribiendo esto en el navegador

http://en.wikipedia.org/wiki/Backbonejs

Hasta ahora todo normal, pero si agregamos al final de la URL el numeral y una referencia vemos que el navegador cambia de sitio dentro de la página

http://en.wikipedia.org/wiki/Backbonejs#References

Lo que hicimos no fue más que ir hasta un elemento dentro de la página llamado References, esto es automático, lo interesante es que podemos poner cualquier cosa después del numeral y además si presionamos el botón volver del navegador volvemos a la misma URL tal como era antes, con lo cual podemos navegar estando siempre en la misma página.

Nosotros desde Javascript podemos saber de estos cambios en la URL y hacer cosas, en esto se basa el modelo de rutas de Backbone, vamos a ver un ejemplo:

<html>
<head>
	<script type="text/javascript" src="js/vendor/jquery/jquery.js"></script>
	<script type="text/javascript" src="js/vendor/underscore/underscore.js"></script>
	<script type="text/javascript" src="js/vendor/backbone/backbone.js"></script>
	<script type="text/javascript">
		//creamos una clase Router extendiendo la clase base de Backbonejs
		var Router = Backbone.Router.extend({
			//definimos las rutas
			routes:{
				"": "home", // la url por defecto va a llamar a la función home
				"accion1": "funcion1" //la url #accion1 va a llamar a funcion1
			},
			home: function(){
				console.log("estamos en casa");
			},
			funcion1: function(){
				console.log("la acción 1 ha sido llamada");
			}			
		});
		
		//creamos un router
		var router = new Router();	
		//iniciamos el motor de navegación
		Backbone.history.start();	
	</script>
</head>
<body>
<a href="#accion1">Ir a la acción 1</a>
</body>
</html>

Básicamente cargamos este html en el navegador se escribe en la consola “estamos en casa” y cuando presionamos el link (que apunta a #acccion1) “la acción 1 ha sido llamada”, entonces con Backbone es muy simple escuchar estos cambios en la URL y llamar funciones a partir de ello.

Pasar parámetros a las rutas

Hay muchas cosas que se pueden hacer con las rutas, por ejemplo pasar parámetros, del siguiente modo:

<html>
<head>
	<script type="text/javascript" src="js/vendor/jquery/jquery.js"></script>
	<script type="text/javascript" src="js/vendor/underscore/underscore.js"></script>
	<script type="text/javascript" src="js/vendor/backbone/backbone.js"></script>
	<script type="text/javascript">
		//creamos una clase Router extendiendo la clase base de Backbonejs
		var Router = Backbone.Router.extend({
			//definimos las rutas
			routes:{
				"": "home", // la url por defecto va a llamar a la función home
				"accion1": "funcion1", //la url #accion1 va a llamar a funcion1
				"accion1/:parametro1": "funcion2" //la url #accion1 va a llamar a funcion1
			},
			home: function(){
				console.log("estamos en casa");
			},
			funcion1: function(){
				console.log("la acción 1 ha sido llamada");
			},
			funcion2: function(parametro1){
				console.log("se llama a la acción con el valor de parámetro: " + parametro1);
			}
		});
		
		//creamos un router
		var router = new Router();	
		//iniciamos el motor de navegación
		Backbone.history.start();	
	</script>
</head>
<body>
<a href="#accion1">Ir a la acción 1</a> </br>
<a href="#accion1/valor1">Ir a la acción 1 y pasar un parámetro</a>
</body>
</html>

Mágico, para no extenderme más con detalles que se pueden ver en la documentación los dejo por ahora con un link a un gist de este código, nos leemos.