Alpha's Manifesto

A black and white figure's thought-hive

Pruebas con VS11: Día dos

async y await

Continuando con mi serie de posts e investigación sobre lo que VS11 ofrece (Parte 1), quisiera tomar una aproximación separada. Si bien la exploración es interesante, es poco apropiada cuando uno quiere aprovechar el tiempo.

Es por eso que comencé con las referencias en MSDN sobre qué hay de nuevo en VS11, que seguiremos de a partes. Pero a la vez quiero cumplir con mi promesa, por lo cual, si comenzamos sobre qué hay de nuevo en el lenguaje C# (lo siento VB, lo siento C++, soy del bando de C#), nos encontramos con la excusa para cumplir lo prometido.

Características nuevas de C#: await y async

Esto, bien sabemos, no es algo propio de VS11, sino de C# 5.0, que va de la mano con VS11 y .NET 4.5. Como MSDN lo indica, una de las primeras características es la habilidad de construir fácilmente código asíncrono. “We have to go deeper…”

Cabe aclarar que ya existía la posibilidad de escribir código asíncrono. Los callbacks y el multithreading no es nada nuevo, aunque esto es ligeramente distinto, ya que simplifican un poco la idea y esconden el trabajo sucio. Sin duda se logrará que en el futuro mucha gente no sepa cómo funciona los métodos asíncronos por detrás pero esconder complejidad es un buen paso para permitir innovación.

Digamos que tenemos un programa que factoriza números grandes, porque logramos un trabajo de criptoanalista para el FBI. Nuestro método recibe un parámetro long y nos devuelve un ISet<long> con el conjunto de factores primos que conforman este número original. Dejando de lado la matemática, sabemos que este proceso toma un rato en ejecutarse y queremos que nuestro programa lo trate de forma asíncrona. ¿Cómo se haría este trabajo de la forma tradicional?

Básicamente deberíamos definir un método que sirva de callback. El callback (también llamado continuación) es un método que el thread que trabaja en la tarea llama cuando termina para avisar que su trabajo terminó. De esta forma, podemos preparar nuestra tarea, enviarla a ejecutar, hacer otras cosas en el intermedio y ejecutar código extra cuando la tarea termina, como por ejemplo, trabajar con los resultados.

Async without async

(Ejemplo del código en Gist.GitHub: Async without async)

Esta aproximación tiene un problema muy claro: la complejidad. Estamos de acuerdo con que el código de FactorNumber debería estar separado en su propio método, pero la continuación de la llamada a FactorNumber y el resto de esa lógica son parte de una misma operación. El hecho de que estén separados en el código no es más que una obligación que debemos cumplir por las restricciones del framework para la instanciación de threads.

Las palabras clave async y await resuelven este problema.

Aquí podemos notar que la estructura del código ha cambiado un poco para dar soporte a esta característica. Por un lado, tuvimos que aislar el código que interactuará con métodos asíncronos, ya que los mismos deben devolver un tipo Task. Esto es porque devuelven un identificador de la tarea que está corriendo en background. En nuestro caso en particular, este será StartWork(), pero no estamos haciendo uso de su Task.

StartWork, siendo asíncrono, se ejecutará a la vez del resto del código, ya que no será bloqueante. Por tanto, el próximo Console.WriteLine se ejecutará, muy seguramente, al mismo tiempo que el procesamiento de StartWork ocurre. Dicho procesamiento hace una llamada bloqueante a FactorNumber, es decir, espera a que FactorNumber termine (lo cual nos permitió convertir la llamada en síncrona) y una vez que tenemos el resultado, se escribirá en consola. No era realmente necesario convertir esta llamada en síncrona de esa forma, una simple llamada a FactorNumber hubiera sido suficiente, pero de esta forma demostré que si bien el sistema espera por su respuesta suspendiendo el thread actual, sigue siendo asíncrono internamente. Eso significa que está ejecutando toda la tarea de callback que vimos antes de forma interna, y ahora nuestro código se lee fácilmente de arriba a abajo.

Confieso que debo trabajar un poco más en esto para no ensuciar tanto el código, pero por ahora parecería que el uso de las keywords exige modificar los valores de retorno y por tanto las llamadas a esos métodos deben ejecutarse de forma distinta. Eso no me agrada, porque inclina un poco la complejidad innecesaria para usar esto, pero sigue siendo una ventaja sobre la solución original.

Sálvenos del REST!

RESTful thinking

Someone save us from REST es el título de un curioso artículo de Rob Connery. Lo curioso es que por lo general REST es una buena práctica y es muy popular y deseado en cuanto a la organización semántica de nuestras aplicaciones web (o de los servicios que estas expongan).

La idea de REST es utilizar toda la complejidad que HTTP provee para dar un sentido más semántico a las operaciones que realizamos. De esa forma, pedir una página y enviar información deberían usar verbos distintos, e incluso deberían haber verbos distintos cuando esa información es nueva o se está modificando información existente. Al mismo tiempo, las URIs deberían ser identificadoras de recursos (de ahí su nombre) y no simplemente direcciones web. Ese es un pequeño resumen, pero la historia va mucho más profunda sobre la idea de darle un significado a las operaciones que se realizan en internet.

Rob Connery lo ve como las peleas grammar-nazi que ocurren en la internet. Es verdad lo que dice y pueden que tengan razón, pero realmente no es tan útil, y hay más discusión y confusión que verdad tras todo ello. Su punto de vista es que se están exagerando mucho las posiciones sobre esta discusión y que nadie tiene realmente una posición 100% clara de lo que REST significa, porque no hay un estándar al respecto.

Soy un zorrinito semántico.

Backbone.js

 Hace un tiempo ya que en nuestro equipo estamos integrando Backbone.js a nuestros proyectos. La idea tras backbone.js es, como su nombre lo indica, ser la columna vertebral del código javascript frontend, de forma que todo trabaje sobre una estructura centralizada y permita al código no ser un desastre auto-destructivo o conflictivo cuando los proyectos crecen. Esto se da mucho en aplicaciones con mucha interacción de usuario, y es importante para una aplicación compleja poder tener el código organizado. Backbone le da una estructura al código del tipo MVC en donde podemos diferenciar datos, de presentación de los mismos y de elementos que controlan la interacción entre ambos.

Ahora, el problema con backbone es que es un poco difícil de aprender. Tiene mucha estructura, poca documentación y no todo es obvio. Gracias a AM y a SC que me han compartido estos documentos útiles: Backbone Fundamentals y Backbone Patterns.

Toda esta temática queda muy acorde a The Seven Deadly Sins of JavaScript Implementation, en donde backbone.js se encarga de un par de pecadillos.

Soy un zorrinito frontend.

UPDATE: For English readers, you may check out this Backbone.js Introduction and Resources.