miércoles, 13 de noviembre de 2013

Aparta, Javascript. Llega... ¡DART!

Dos añitos se ha tirado la plataforma Dart de Google para conseguir alcanzar la suficiente estabilidad tanto en el lenguaje como en las librerías y herramientas, como para llegar a su primera versión estable, la versión 1.0, cuya salida según el equipo de desarrollo es inminente.

¿Y qué demonios es Dart?. Pues la forma más rápida de definirlo es que es un reemplazo de JavaScript. Un reemplazo que pretende aprovechar las virtudes de JavaScript, y a la vez superar sus defectos. Esto lo hace especialmente interesante cuando lo que se pretende desarrollar es una aplicación web (o de forma más general, un "rich client"), es decir, una aplicación con interfaz web y con mucho código en la parte cliente. No obstante, si pensamos más allá nos podemos dar cuenta de que sus posibilidades son aún mayores.

Te estoy viendo. Tienes serias dudas. ¿Cuántas veces te han vendido la moto del enésimo lenguaje de moda que todos deben usar porque es el más bonito e indudablemente el mejor, para finalmente darte cuenta de que no tenía nada especial y era lo mismo de siempre o, incluso, mucho peor?.

Lo cierto es que Dart cubre un hueco, tiene un propósito. Hoy por hoy no hay otro igual o del mismo estilo.

¿No me crees?. Sigue leyendo, a ver qué piensas al final del artículo...

Pero... ¡yo amo Javascript!

El bueno
JavaScript tiene indudablemente algunas virtudes. Es un lenguaje con un buen manejo de prototipos y con la posibilidad de usar funciones como valores dentro de variables. Pero también es un lenguaje muy guarro, especialmente si pretendes hacer una aplicación más o menos grande, algo que cada vez es más habitual con la evolución que han sufrido las tecnologías web. Se nota que el lenguaje está pensado "en pequeño".

Las variables son globales, y si quieres crear un espacio propio de nombres o modularizaciones adecuadas en general, te metes en problemas. No existe encapsulación, no se pueden tener elementos privados a nivel de clase (si aceptásemos que existen clases, quiero decir, cosa que no es cierta). El uso de this es para darle de comer aparte (cada vez que te ves obligado a hacer un var self = this, muere un gatito), los operadores son exageradamente casquivanos... cosas muy básicas del diseño de aplicaciones, y especialmente del diseño orientado a objetos.

El feo
Por supuesto, puedes diseñar y programar aplicaciones JavaScript correctamente, incluso orientadas a objetos, siguiendo varias recomendaciones sobre cómo organizar correctamente tu código, y qué características del lenguaje evitar. Hay un montón de libros y artículos sobre el tema, y es verdad que uno de los grandes problemas de Javascript es que durante mucho tiempo se ha considerado un lenguaje "para hacer chapucillas en la web". Y la gente que programaba en Javascript a menudo no eran programadores, lo que ha hecho que se haya extendido mucho código basura.

El malo
Pero también es verdad que el lenguaje no ayuda a estructurar mejor el código, sino todo lo contrario, ni tampoco ayuda a la legibilidad. ¿Por qué tengo que leerme un libro para enterarme de qué cosas del lenguaje debo evitar a toda costa y qué patrones debo seguir no para que mi código sea mejor, sino para que sencillamente no sea pura caca de vaca?. ¿Por qué tengo que leérmelo incluso para entender muchas cosas arcanas que lleva el lenguaje dentro, y que muchos programadores gustan de utilizar para demostrar todo lo que saben?.

En cualquier caso, si ya has superado ese umbral, tienes conocimiento sobre cómo diseñar de una forma legible y mantenible una aplicación JavaScript y, qué demonios, te encuentras cómodo con ello, entonces Dart no será para ti.

Lenguaje limpio, con clases y orientado a objetos 

Hoy por hoy, si quieres hacer una aplicación cliente en la web, en web "pura", se tiene que ejecutar en Javascript, ya que es lo único que los navegadores saben ejecutar. Dadas sus limitaciones, han ido apareciendo otros lenguajes de reemplazo, que compilan a Javascript, como por ejemplo CoffeeScript y TypeScript.

Dart va un paso más allá que estos dos, porque al contrario que ellos, el lenguaje no está basado directamente en Javascript. Se parece en algunas cosas, sí, porque la mayor parte de su "target" es la gente que está trabajando con Javascript, por lo que es conveniente que haya cosas que les resulten familiares.

En contraposición a Javascript, la palabra que mejor define a Dart es que es limpio. Tiene funciones, que también se pueden asignar a variables, pero también tiene clases, lo que facilita que se haga un diseño orientado a objetos. Permite crear librerías, versionarlas e importarlas en otro proyecto con un espacio de nombres propio, para evitar colisiones. Tiene la posibilidad de crear propiedades y métodos privados dentro de una clase.

Además, de esto, el lenguaje tiene mucho "syntantic sugar", es decir, muchas formas sencillas de declarar las cosas en pocos términos. Para que un elemento sea privado, basta con hacer que su nombre empiece por "_". Los getter y setter son opcionales, y se les llama automáticamente al usar la propiedad, de forma que desde el punto de vista del que los llama no sabe si existen o no (sí, sí, encapsulación poco trabajosa). Se pueden declarar métodos sencillos que devuelvan un valor o una operación de forma rápida usando "=>". Se pueden concatenar llamadas consecutivas a un objeto con el operador "..". Se pueden declarar fácilmente funciones anónimas para pasarlas como parámetro. Se pueden declarar datos de colecciones de forma sencilla usando literales [] y {}...

El lenguaje Dart tiene tipado dinámico, aunque a ellos les gusta más llamarlo "tipado opcional". Puedes declarar el tipo de cualquier variable, o no hacerlo. Dart tiene un modo de ejecución llamado "checked mode", que es el que se recomienda para desarrollo, y que es más lento pero da error ante manipulaciones erróneas de variables sin tipo declarado según su valor actual. Por ejemplo este código no daría error en "modo producción", pero sí haría saltar una excepción en el modo checked, al tratar una cadena como si fuera un booleano (lo de los undefined, null, etc. como false dentro de las condiciones no se ha heredado de JS; en las condiciones sólo pueden ir booleanos):

var name = 'Bob';
if (name) {
  print('You have a name!'); // Prints in JavaScript, not in Dart.
}
No sé muy bien por qué, pero el editor de Dart no es tan listo como eso, aunque sí que es listillo. En el código anterior no daría ninguna advertencia, pero si pulsamos autocompletar en "name." sí que nos dará una lista con todos los atributos y métodos públicos de la clase String (lo que me hace pensar que lo anterior también es alcanzable). También es capaz de hacer cambios de nombre en clases, propiedades o métodos propagando el cambio a todos los que lo usen, así como hacer otros tipos de refactorizaciones. Por tanto, los que se encuentren más cómodos con lenguajes estáticos (entre los que me incluyo) podrán mitigar un poco esa incomodidad gracias a esta posibilidad de hacer refactorizaciones y renombrados. Por supuesto, en los sitios en los que las variables o los parámetros sí que los declaremos con su tipo, se detectará cualquier manipulación errónea.

En definitiva, sí, el lenguaje se parece a... muchos otros lenguajes que ya existen. Tiene bastantes puntos en común con Groovy, por ejemplo. Pero tiene una diferencia importante respecto a ellos: se puede ejecutar en el navegador.

"Mundo real": Rendimiento, compatibilidad, conectividad

Todo esto es muy bonito, pero la vida real no vive sólo de lenguajes. Consideremos otros aspectos fundamentales a la hora de tomar una decisión:

    de 11870.com
  • Rendimiento. Este ha sido el objetivo número uno del equipo de Dart una vez definido el lenguaje. Es obvio que el rendimiento es importantísimo, el compilador de Javascript debe generar código que sea suficientemente rápido y pequeño, o si no no merecerá la pena. En cuanto a la velocidad, Google afirma que su lenguaje actualmente puede llegar a ser incluso más rápido que si haces la aplicación directamente en Javascript. Los datos se pueden encontrar en este benchmark. Sea verdad o no (ya se sabe que los benchmarks son como las encuestas de los políticos), la verdad es que los ejemplos que he visto sí me han parecido suficientemente rápidos. En cuanto al tamaño, Dart optimiza la carga de librerías, de forma que sólo se compila a JS el código que realmente se utiliza dentro de la aplicación. Ahora mismo hay alguna librería que al utilizarse sí que aumenta mucho el tamaño, pero teniendo en cuenta que se trata aún de una versión 1.0 de la plataforma y que el rendimiento es el objetivo principal actualmente, es de esperar que se hagan optimizaciones. Habrá que ver hasta dónde se consigue llegar.

  • Compatibilidad. El código generado es compatible con todos los navegadores actuales... excepto con Internet Explorer 8 o inferiores. En Octubre del 2013 el uso de IE8 según StatsCounter es del 9,56%, todavía alto. Por otra parte, las herramientas de Dart no funcionan en Windows XP, sistema operativo que todavía según la misma web tiene un uso del 20,06%. Mi interpretación es que este es uno de los aspectos en los que se nota que Dart sabe que su momento no iba a llegar este año... pero puede que sí el que viene, ya que es de esperar que ambas estadísticas y especialmente la de IE8 desciendan durante los próximos meses.

  • Conectividad. Desde Dart se puede llamar a librerías Javascript sin ningún tipo de problema. El enfoque sugerido es hacer una librería Dart que encapsule las llamadas, y en general es así como se está haciendo. Por otra parte, a pesar de lo pronto que todavía es para Dart, existen ya librerías para acceso a bases de datos como MySQL, PostgreSQL o MongoDB. Por supuesto, el margen de mejora en cuanto a librerías es todavía grande.

Librerías de acceso al navegador

Para acceder al navegador tenemos la librería html, una librería bastante grande que encapsula el acceso al DOM del navegador, HttpRequest, WebSockets, y las múltiples nuevas APIs que están surgiendo en HTML5 (almacenamiento local, sonido, WebRTC, etc.). También tenemos la librería js que permite acceder a JavaScript.

Luego sobre ellas se construyen algunas librerías que facilitan la creación de la web según estándares modernos y modularizables, pensando especialmente en la creación basada en componentes. La librería que se considera "base" para esto es polymer, basada en el proyecto Javascript del mismo nombre, y que permite definir elementos y atributos propios dentro del DOM o extender otros ya existentes, enlazar automáticamente con datos de los objetos Dart, incluso con enlazado doble, si cambia el elemento HTML cambia el objeto Dart y viceversa, y crear estructuras condicionales y bucles.

La cosa no se queda ahí ya que también se está creando un port del cada vez más popular AngularJS, llamado AngularDart. Este proyecto va más allá que polymer, ya que es un framework MVC más completo.

Hay que tener en cuenta que toda la parte del cliente, incluyendo estas librerías, al final se acaba convirtiendo en JavaScript. Es decir, nada de SEO (o sea, fundamentalmente nada de aparecer en buscadores) ni de accesibilidad (me refiero a la accesibilidad tradicional WAI WCAG-AA, que se sigue exigiendo en muchos proyectos de la administración pública, no a la más moderna WAI-ARIA). Por eso dije al principio que Dart es ideal fundamentalmente para aplicaciones web, no para sitios web públicos que queramos que aparezcan al buscar en Google.

Se puede ejecutar en el servidor

La aparición de node.js supuso una pequeña revolución, ya que permitía ejecutar Javascript no sólo en el navegador, sino que también la parte de servidor se hiciera en el mismo lenguaje. Dart ha tomado también este modelo, y desde el principio se ha preparado para poder ejecutarse en un servidor web. La diferencia fundamental entre la parte de cliente y la de servidor es que esta última no se compila a Javascript, sino que se ejecuta directamente en la máquina virtual de Dart. Además no podrá utilizar, obviamente, las librerías de acceso al navegador, y a cambio tendrá las suyas específicas que no podrán usarse en el cliente (muchas otras serán comunes para los dos lados).

La librería principal del servidor es io, que permite acceso al sistema de ficheros, sockets, cliente y servidor web, etc.

Para esta primera versión 1.0 el equipo de desarrollo se ha planteado como prioridad el compilador de Javascript y su rendimiento, y la ejecución en la parte del cliente en general, dejando para más adelante las optimizaciones en el servidor. Esto quiere decir que el soporte de Dart en el servidor, aun siendo completo, sólo lo veo recomendable por el momento para aplicaciones que no tengan muchas complicaciones en el lado del servidor. Un API que acceda casi directamente a una base de datos, por ejemplo. Si no, para valientes.

Algunos ejemplos de incidencias o mejoras que se han pospuesto tienen que ver con la velocidad de la propia máquina virtual y de la concurrencia. Concurrencia que en Dart se ofrece en forma de isolates, elementos de ejecución que no comparten memoria y se comunican entre sí por medio de mensajes, para evitar la existencia de errores chungos al gestionar la sincronización. Aparte del modelo de concurrencia, Dart permite ejecución asíncrona mediante Futures, que no se ejecutan simultáneamente sino uno detrás de otro, pero que permiten establecer el orden de las ejecuciones de una forma un poco particular. Son similares a las promises de Javascript. Siendo interesantes a priori ambas propuestas (aunque no tengo una opinión demasiado firme sobre ninguna de los dos por el momento y ambas me chocan un poco), lo cierto es que les queda trabajillo para facilitar la programación en el servidor, tanto en los isolates como en los futures (los futures se usan también en el cliente habitualmente pero entiendo que ahí no tienen por qué complicarse demasiado y me da que basta con lo que hay). Incluso la mismísima serialización de objetos con JSON, que debería ser importantísima en Dart para la comunicación cliente-servidor, entre isolates o usando sockets, está aún poco trabajada (aunque hay soluciones para crear y leer JSON automáticamente, pero ya las contaré otro día).

Sin embargo, el que tanto el cliente como el servidor se puedan crear en el mismo lenguaje Dart tiene ventajas muy interesantes. Es obvio que podríamos compartir código entre ellos, incluyendo los propios objetos que se serialicen en la comunicación cliente-servidor, pero puede ser aún más interesante si creamos interfaces comunes para determinadas partes que son similares en el cliente y el servidor en cuanto a concepto aunque su implementación sea completamente distinta. Especialmente el cliente HTTP, aunque también posiblemente los sockets / websockets. Esto nos permitiría poder trasladar código de cliente a servidor y viceversa con mucha facilidad, haciendo que por ejemplo podamos trasladar cosas fácilmente de acuerdo al rendimiento, la seguridad o simplemente cambios de requisitos.

Incluso, se me ocurre que potencialmente podríamos hacer un framework en el servidor que reemplazara la librería de acceso al DOM y creara los elementos en memoria usando el mismo Polymer o cualquier otro sistema de plantillas que usemos en el cliente, y devolviera el HTML resultante al cliente para partes de la web que queramos que aparezcan en buscadores. Sí, quizá después de todo el SEO sí que sea posible.

Es de esperar que Google vaya con fuerza a por el servidor después de la versión 1.0, e incluso que le dé soporte en AppEngine, de forma que podamos tener con cierta facilidad un hosting básico gratuito.

Yendo un paso más allá

Al ser Dart un proyecto de Google, se pueden adivinar intenciones que tiene la empresa para el lenguaje. Se puede adivinar que pronto la versión oficial de Google Chrome va a ejecutar Dart de forma nativa (bueno, además es que lo han dicho ellos mismos). Al fin y al cabo, ya existe una máquina virtual que ejecuta Dart directamente, la DartVM, y ya existe una versión de Chromium que también ejecuta Dart de forma nativa, Dartium. No olvidemos que Chrome tiene un uso actualmente del 40,44% (nuevamente StatsCounter, Octubre 2013).

Al hacer esto Google va a conseguir una jugada a varias bandas: por un lado, esta vez seguro que sí, las aplicaciones Dart serán más rápidas que las aplicaciones Javascript. Por otro lado, las aplicaciones Dart serán más rápidas en Chrome que en el resto de navegadores. Y por otro lado, las aplicaciones Dart podrán tener un rendimiento comparable a las de escritorio, por lo que se aumentará la tendencia de aplicaciones hacia las tecnologías web. Triple win para Google.

Además de esto, no olvidemos que HTML5 + JS se está utilizando actualmente en otros ámbitos, no sólo aplicaciones web. Por ejemplo, para hacer aplicaciones móviles multiplataforma, o para videojuegos. Y vaya hombre, Google también está detrás de Android, por lo que es de esperar que finalmente también consigan que las aplicaciones hechas en Dart funcionen mucho mejor en Android que en IOS (y ya van cuatro wins). En este sentido, existen ya librerías específicas para hacer aplicaciones móviles en Dart, especialmente Rikulo.

Conclusiones

¿Y ahora?. ¿Estás ya convencido de que esto no es lo mismo de siempre?. ¿Ves no sólo lo que ya aporta, que es mucho (aunque algunas cosas estén aún un poco verdes), sino en lo que puede llegar a convertirse, en lo que se está convirtiendo?. Te invito a que dejes un comentario con tus impresiones. ¿Piensas como yo que supone un nuevo paso en la propia evolución de la web?.

Pues corre, vete a la página de Dart, ¡y dale duro!.

¡La web te necesita!

de panicposters.com

cookie consent