domingo, 29 de diciembre de 2013

Proyecto Picross: haciendo un videojuego HTML5 en Dart

Ya lo dije en mi anterior entrada sobre el lenguaje Dart: Dart está muy bien, puede suponer una revolución en la web y su futuro potencialmente es muy prometedor. Pero claro, una cosa es el posible futuro y otra es el presente. ¿Cuál es realmente el estado actual de la plataforma Dart?.

Por otra parte, otra tecnología que me llama la atención es la de los videojuegos HTML5. Sobre todo para videojuegos 2d, sencillos, que aparentemente ya deberían poder hacerse en la web. Con la gran ventaja de ser multiplataforma, que se puedan jugar en Android, en iOS, o hasta desde el Facebook, y en este último caso sin tener que instalar nada. ¿Están estas tecnologías suficientemente maduras?.



Con ánimo de comprobarlo y a la vez divertirme, me lié la manta a la cabeza, uní las dos inquietudes y me puse a hacer ¡un videojuego en Dart!. Y aquí cuento todo el proceso, que duró sólo una semana, pero que me dio para asistir a la Gameme5  e incluso participar en la PiWeek.


La GameMe5

Yo de videojuegos en HTML5, la verdad, ni idea. Afortunadamente, estaba apuntado a la GameMe5, un evento organizado por HTML5 Spain y Wimi5 en el que ofrecían un taller de programación de videojuegos en Javascript el Viernes y varias charlas el Sábado.

El taller lo daban Carlos Benítez (@EtnasSoft) y Sergio Ruiz (@serginator), y en él fueron explorando un juego que se habían currado aposta y que era muy muy completito, desarrollado enteramente en Javascript a pelo y sin librerías.

Fueron avanzando poco a poco en el desarrollo y cubrieron muy bien muchos aspectos del desarrollo de videojuegos en general y de Javascript en particular, desde los temas más básicos como el loop principal y el doble buffer hasta otros más complejos como las rotaciones, los fondos por trocicos (en mosaicos), los métodos de detección de colisiones, algoritmos de búsqueda (pathfinders), manejo de física y sistemas de partículas. Lo mejor del taller es que aparte de estos aspectos más o menos generales de los videojuegos, iban comentando también temas de rendimiento y problemas de Javascript. Dijeron que un buen juego JS puede llegar a estar a la altura de un juego de PS2, si es 2d, o entre PS1 y PS2, si es 3d. Pero además comentaron problemas que tenían los navegadores si querían hacer efecto espejo automáticamente en las imágenes, usar base64 o como no tuvieran cuidado con los arrays y el recolector de basura (al eliminar un elemento de un array no lo elimina de verdad, sino que lo deja pendiente de GC, lo cual puede llegar a causar un parón sensible en un videojuego).

En las charlas del día siguiente hubo de todo, pero me gustaría destacar sobre todo 3 que fueron especialmente interesantes. En la primera, José Javier García-Aranda de Alcatel-Lucent hablaba sobre un algoritmo en el que están trabajando para compresión de imágenes y vídeo, LHE (Logarithmical Hopping Encoding), y que puede ser muy potente para el Cloud Gaming y las videoconferencias, ya que se consiguen tiempos de codificación rondando los 2ms y una calidad decente a 0,1 bits por pixel. Fue una de esas charlas que destacan porque lo que se cuenta es muy interesante, se entiende muy bien y además el ponente es muy ameno.

En la segunda Jorge del Casar (@jorgecasar) hablaba sobre WebSockets, y nos hacía una demo con un Tetris multi-jugador.

Y por último Imanol Fernández (@MortimerGoro) de Ludei nos daba una apabullante lección sobre rendimiento de Javascript, haciendo una demostración de un pequeño programa que tardaba 600 veces más en su versión Javascript que en la versión C++, y luego le aplicaba muchos trucos hasta conseguir que fuera "sólo" 6 veces más lenta. Sobre todo se usaron técnicas para conseguir que el compilador JIT de Javascript hiciera "inline caching" de las funciones más importantes, ya que es muchísimo más rápido, con cosas tan aparentemente absurdas como borrar un comentario o borrar un try-catch. Por ahí rondaron conceptos como las "hidden classes" (que se crean cuando añades atributos nuevos en tiempo de ejecución, y que ralentizan bastante) y arrays de más de 64K (leeentos). Pero vamos, si os interesa el tema, lo mejor es que veais la presentación completa.

Aparte de eso, también nos habló de CocoonJS, una herramienta que ha hecho que permite publicar tus videojuegos HTML5 en móviles, pero que al contrario que Phonegap, en lugar de utilizar los browsers que vienen de serie en las respectivas plataformas, utiliza uno propio, con su propia implementación de canvas, audio, webGL, etc., y con un rendimiento optimizado respecto a los otros (are we crazy? yes, but we're from Bilbao). La verdad es que tenía una pinta tremenda.



El videojuego: Picross

La verdad es que la GameMe5, en la práctica, sirvió a mi proyecto sobre todo para una cosa: acojonarme. Tanta optimización, tanto comportamiento extraño de los motores JS, tanto lío con los navegadores, tanta facilidad para quedarse sin memoria... y voy yo y le meto una capa más de riesgo por encima, Dart.

Así que decidí que ya tenía bastante cubierto mi cupo de riesgo y decidí hacer un juego sencillito, que no requiere gran rendimiento pero que a la vez escala muy bien, y da para ir añadiéndole cositas poco a poco. Y por supuesto, ¡muy divertido!.

Picross es un juego de tipo puzzle que se conoce por muchos otros nombres de los cuales el parecer el más oficial es "nonogramas".  Habrán salido millones de versiones del juego, tanto para ordenador como en papel, pero la que se hizo más famosa en su día fue la versión de Nintendo DS, o al menos esta es la que yo conocía y de la que me vicié hace años. Como buen juego de puzzles, se puede dejar el rendimiento un poco de lado y que siga siendo jugable, y eso es lo que a mi me importaba llegado a este punto. Sobre todo, porque tenía que tener una versión presentable en una semana, ya que me había presentado a la PiWeek.

El funcionamiento del juego es sencillo: hay una matriz de celdas, y cada una de ellas es un píxel, que puede ser blanco o negro. Todas juntas forman un dibujo binario que es el que hay que averiguar. Para hacerlo, cada fila y cada columna tienen una serie de números que indican los grupos de píxels negros que son consecutivos. Por ejemplo, si en una fila pone "3 2" significa que hay 3 píxels negros seguidos y luego separados otro grupo de 2 píxels negros. Entre medias, antes y después, hay un número indeterminado de píxels blancos. Combinando las pistas de las filas y las columnas, se va averiguando el dibujo.


La PiWeek

Kaleidos es una empresa de desarrollo que probablemente pueda presumir de tener el mayor ratio de densidad de geeks por metro cuadrado en toda España. Se definen como una empresa orientada a proyectos de innovación, así que tienen varias iniciativas muy interesantes orientadas a la innovación y la mejora. Una de ellas es la PiWeek ("Pi" de "Personal innovation"), una semana entera en la que paran por completo todos los proyectos que estén haciendo en ese momento para hacer... lo que le dé la gana a cada uno. Así, tal cual, lo que sea que le interese. Las únicas reglas son usar software libre para el desarrollo, y tener algo enseñable para una demo el Viernes.

La PiWeek tiene vocación abierta, y por tanto admite gente que no sean empleados de Kaleidos, ya sean individuos o empresas. El caso es que a mi me quedaba todavía una semana de vacaciones, sin ningún plan concreto, y de hecho tenía pensado dedicarla a este proyectillo, así que, ¿por qué no presentarme a la PiWeek, y así por un lado obligarme a hacer algo y por otro poder compartir proyectos con más gente?. Dicho y hecho, el Viernes anterior a la PiWeek se presentan propuestas de proyectos para formar equipos... y allí estuvo Picross.

Yo ya conocía a unos cuantos de Kaleidos, sobre todo a través del grupo de usuarios de Groovy Madrid GUG, pero la semana me dio la ocasión de charlar con todos, y la verdad es que es una gozada, en general son gente muy preparada y sobre todo derrochan pasión por la tecnología y el desarrollo. Entre los proyectos que se presentaron a la PiWeek había algunos como un clon de Twitter usando Redis y Spring integration, un visor de comics Android con detección de viñetas, un plugin de Chrome capaz de capturar pantallazos como GIF animados, un traductor de Python a Javascript (bautizado como CobraScript) o un aplausómetro hecho en Arduino, junto a otros más... rarunos, como un MUD hecho en Eiffel o una librería que permite crear parsers en Clojure. Salieron un montón de proyectos, pero todos tenían algo que contar. El ambiente que se crea durante la PiWeek es impresionante.


Haciendo el juego

Y llegó el momento de ponerse con el juego. Las primeras sensaciones con Dart son muy buenas, no es un lenguaje ni unas herramientas a las que estés acostumbrado, no son ni mucho menos tu "zona de confort", pero tanto las herramientas como el lenguaje y las librerías resultan cómodos e intuitivos. Esperaba encontrarme con alguna característica del lenguaje que echara de menos (el típico "no me puedo creer que esto no exista aquí"), pero no encontré ninguna.

Integración de Dart con Javascript
Mi primera intención era hacer un interfaz Dart para una librería Javascript de videojuegos. Después de estar echando un vistazo a unas cuantas me decidí por MelonJS, ya que había oído hablar bien de ella y era más pequeña y ligera que otras como Cocos2D. Después de varias pruebas básicas que aparentemente funcionaron, fui creando clases "proxy" que intermediaran con la librería, usando sólo lo que iba necesitando... hasta que de repente una prueba, justo después de haber hecho un montón de código, dejó de funcionar.

Tras un rato pegándome con ello, descubro que no podía llevar a cabo lo que pretendía. El caso es que Dart permite hacer llamadas a funciones y objetos Javascript sin ningún problema, y de una forma bastante cómoda, convirtiendo colecciones de una manera sencilla. También se le pueden mandar funciones Dart que sirvan de "callback" y se las llame desde JS. Sin embargo, la integración tiene una limitación importante, y es que no se puede llamar a objetos Dart desde código Javascript. Esto invalida por completo la posibilidad de usar un framework como es MelonJS, ya que en él todas las entidades del juego se definen como objetos a los que invoca el núcleo Javascript de la librería.

Un día entero perdido con la tontería. Y en realidad es culpa mía, porque lo ponía muy claro en la documentación. Odio los Lunes.

Problemas APIs HTML5
Como había oído que el sonido daba problemas, decidí usar la librería Howler para que ella se encargue de elegir el fichero de audio adecuado según el navegador, poniendo versiones de los sonidos en mp3, ogg y wav. En este caso al no tratarse de un framework no tuve ningún problema para encapsularla en clases Dart. Pensaba que con esto ya conseguiría que los sonidos y músicas sonaran en todos los navegadores modernos pero... craso error. Ni así. El tema del audio en los navegadores es un berenjenal de cuidado. He ido probando en varias versiones y nunca sabes si te va a funcionar o no, a veces incluso versiones del mismo navegador con muy poca diferencia entre ellas. Con Chrome por ejemplo, en Dartium no funciona la música pero sí los sonidos, y lo mismo en otras versiones de Chrome que he probado. Sin embargo, en mi Chrome y la mayor parte de versiones que he probado sí funciona también la música. En Firefox más de lo mismo, aunque aquí a veces me ha ocurrido lo contrario, que funcionaba la música pero no los sonidos.

Rendimiento
La verdad es que hasta ahora no he cuidado nada el rendimiento del juego, ni siquiera dentro de las limitaciones que pudiera tener usando Dart, pero aun así los resultados son curiosos. En Chrome en general el juego parece funcionar bastante bien, al menos en los ordenadores en los que he probado (imagino que en ordenadores antiguos le costará más). Curiosamente, parece que funciona igual de rápido en Chrome, es decir, ejecutando el código compilado a Javascript, que en Dartium, ejecutando el código de forma nativa. En Firefox, al menos en Linux, sufre mucho más, notándose mucha mucha diferencia según el tamaño del dibujo que se intenta averiguar. En Windows me pareció que funcionaba un poco mejor, aunque pudo ser por la máquina.

En el Chrome de mi tablet Android el juego funciona, justita de rendimiento, pero funciona. Parece sufrir bastante en cuanto tiene que usar cualquier sonido, lo cual me hace sospechar que los sonidos pueden ser causantes en buena parte de los problemas de rendimiento. Al final se acabó quedando colgado. En cualquier caso no me parece muy preocupante por el momento, porque como ya he dicho no he mirado todavía nada del rendimiento, y para la versión móvil probaré con el ya mencionado CocoonJS, que espero que no tenga problemas con el sonido (y si los tiene ya les vale).

Imagino que Dart debe estar ralentizando en general todo el código, y de hecho puede que la lentitud en Firefox sea por eso, aunque tampoco me extrañaría nada que fuera sencillamente un tema de rendimiento de las librerías HTML5, que no las veo demasiado optimizadas. Aunque la conclusión principal que saqué de charlas del GameMe5 es que el rendimiento de Javascript es muy muy muy sensible, y un pequeñísimo cambio puede causar de repente un gran aumento en la velocidad. En cualquier caso, en principio para este juego me vale.

Programando en Dart
Esperaba que Dart me diera algún problema: que las herramientas no funcionaran bien, que me encontrara con algún bug molesto en alguna librería, que no encontrara documentación sobre las librerías... Sin embargo, no ha sido así, todo ha funcionado como la seda.

El IDE funciona muy bien. A pesar de tener tipado opcional, hace una buena inferencia de tipos y permite autocompletar, buscar referencias, refactorizar o navegar por las clases incluso en variables sin tipo explícito declarado. Encontré algunos errores en esto, en cuanto a variables de las que de repente es incapaz de inferir el tipo aunque un rato antes sí lo hacía, pero lo considero errores menores e imagino que se arreglarán. También detecta errores de llamada a métodos o propiedades inexistentes, aunque al ser un lenguaje dinámico los marca como warnings en lugar de errores. Hubiera preferido lo segundo, pero me vale, e imagino que en el futuro permitirán esta opción.

Dartium, el navegador que incluye la máquina virtual Dart para ejecutar de forma nativa, funciona también muy bien, y el debugger tampoco me dio ningún problema. Incluso, me encontré alguna sorpresa agradable como que cuando el debugger te muestra los atributos de un objeto, te incluye también los valores de sus getters, es decir, de las propiedades que tenga que se calculan a partir de una función en lugar de devolver directamente el valor de una variable. Esto es comodísimo.

Me encontré muy cómodo también con el lenguaje. Me fastidia el que las reglas de estilo recomienden tabulaciones de dos espacios, que creo que hacen el código menos legible, y al venir yo de lenguajes de tipado estático me costó un rato hacerme a la idea de que no tenía por qué declarar tipos en variables locales (en propiedades de clases y parámetros de métodos yo que tú sí lo haría siempre). Todo lo demás me encantó desde el principio. No eché nada de menos al plasmar un diseño orientado a objetos, tiene sus clases, objetos, clases abstractas, e incluso modificadores de atributos interesantes para el control del código como const y final. Pero sobre todo el lenguaje tiene un montón de "azúcar sintáctico", con comodidades muy importantes como los getters/setters implícitos, las funciones lambda, los parámetros opcionales y/o nombrados en los métodos, los constructores con inicialización directa de propiedades con argumentos, el operador en cascada y el manejo de colecciones.

Las librerías estándar también son muy completas y están muy bien documentadas, existen clases para cualquier cosa básica que se te puede ocurrir a hacer y, también muy importante, se encuentra cualquier cosa muy rápido buscando en http://api.dartlang.org/. Si se quiere hacer algo más especializado (aunque a mi no me ocurrió), también existe un repositorio de librerías en el que es fácil buscar: http://pub.dartlang.org/ y gracias al gestor de paquetes incluido en Dart, pub, usar cualquiera de esas librerías es muy sencillo.

Lo más importante que puedo decir es que olvidé por completo la sensación de que estaba programando para el navegador. Creo que la separación entre programación "front" y "back", aunque tenga cierto sentido, es un poco artificial. Se ha hecho muy necesaria de unos años a esta parte en programación web porque programar para la parte cliente era un infierno, en el que contaba más conocer los truquillos y las compatibilidades en los navegadores que la programación real. Pero eso está cambiando mucho: con jQuery y demás librerías JS nos podemos olvidar de las incompatibilidades en el acceso al DOM, con Bootstrap (como ya comenté en otro artículo) y otras librerías de LESS y SASS nos podemos olvidar en buena parte de los dolores de cabeza con el CSS. Con Dart podemos dar un paso más y olvidarnos de la problemática de Javascript y sus librerías, comenzando a programar exactamente igual a como se hace en la parte back, al menos en mi caso, con un diseño orientado a objetos, con encapsulación, con librerías potentes, con tipado, con las facilidades de un buen IDE...


El resultado

Se puede acceder al juego online en esta direcciónhttps://googledrive.com/host/0B-qqsnsC2gHuS210TnQ4cENGSkk/index.html

Es completamente jugable, aunque sólo tiene 4 niveles y a veces le pasan cosas raras. Esta es la versión que presenté en la demo del Viernes de la PiWeek. Tampoco hay instrucciones, así que lo cuento aquí: botón izquierdo del ratón = negro, botón derecho = blanco (se ve como una X con sombras).

Mi intención es mejorarlo y convertirlo en un "juego de verdad". Se pueden hacer un montón de cosas, como:

  • Añadirle muchas más fases: una de las grandes ventajas (y también alicientes) de este juego es que añadir más fases es tan fácil como añadir un pequeño dibujo pixelado... y si empiezas a tirar del hilo de los juegos retro ¡hay un montón!. Tres de los cuatro dibujos de la demo están hechos así, uno de ellos incluso con un gráfico propio de un mono que era el sello de mi "marca" de juegos de Spectrum, ¡sniffffff!. ¿Reconoces los otros dos?.
  • Mejorar el código, sobre todo el loop principal del juego y la carga de recursos, ya que me basé en el código del taller de Gameme5 y no me gusta mucho cómo les quedó esta parte. Tengo localizada ya una librería para el loop y otra para la carga de recursos, ambas con buena pinta.
  • Versión para móviles (probando CocoonJS)
  • Modo "duelo" multijugador, que me permitiría también probar a hacer un mini servidor en Dart (y reutilizar clases de la parte cliente), y probar los WebSockets.
  • Conectarlo con Facebook y/o Google Play Games.

En definitiva: Dart me ha funcionado muy bien, HTML5 un poco más regular, y sobre todo me ha encantado la experiencia y me lo he pasado muy bien. Y lo mismo... hasta acaba saliendo como resultado un juego de verdad. Permanece atento a la pantalla.

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

viernes, 11 de octubre de 2013

Oda al informático vago

de desmotivar.com
Amigo cazatalentos, no le des más vueltas. Deja de estudiar la personalidad de tus candidatos desarrolladores de software: su positividad, su entusiasmo, su inteligencia, su liderazgo, su empatía, sus valores y todas esas zarandajas. Que sí, que pensabas que eso era importante, lo sé. Pero es mucho más sencillo que eso. Si estás buscando a los mejores informáticos, hay un aspecto que te mostrará de forma inequívoca quiénes son. Distinguirás al mejor porque será un vagazo. Un perraco. Un zángano de monte. Un gandul del abedul. Un oso perezoso. Un haragán sin cura posible. Un remolón irredento. Un indolente natural. Lo más holgazán que ha parido madre.

Ese y sólo ese será el factor que te hará reconocer a tu candidato uno entre un millón. El tío capaz de cambiar las cosas. El factor diferencial. El informático alfa.

No me crees, ¿verdad?.

Al fin y al cabo llevas toda la vida escuchando la importancia de la disciplina y el trabajo duro. Piensa en tu propia historia. Cuando eras un niño pequeño, te tirabas el día jugando, imaginando, creando. Llegaste al colegio y todo cambió. De repente no sólo tenías que estar todo el día escuchando el rollo macabeo que te contaba el profesor, y que te importaba un pimiento, sino que cuando por fin llegabas a casa tenías que... ¡hacer los deberes!. Deberes que estaban diseñados aposta de forma que fueran, bueno, un rollazo. Que no aportaran nada. Su único objetivo era moldearte de acuerdo a esos principios de la disciplina, trabajo, etc., o sea, que su único objetivo era que agacharas la cabeza y te acostumbraras a perder unas horas de tu precioso tiempo haciendo algo que ni te aportaba nada a ti, ni le aportaba nada a nadie, ni disfrutabas haciéndolo (bueno, quizá tú sí lo disfrutaras un poco... ¡y por eso no eres un informático alfa!).

de desmotivar.com
Ahora bien, retrocedamos unos años, y estudiemos la historia de Willi, el primer informático alfa. Willi estaba pasando a limpio uno de esos insufribles trabajos del cole con su máquina de escribir. Taka-taka-taka-ta-ka-takataka-kata¡CRACK!... ¡cagonlaleche!, ¡ya me he vuelto a equivocar!. Como buen vagazo, Willi no había comprado aún el típex, que le hubiera permitido corregir los errores (más mal que bien) y que se le había acabado hace dos años. Por supuesto, Willi no estaba dispuesto a volver a escribir la página entera, bastante se había aburrido ya preparando ese trabajo sobre las opciones reproductivas del berberecho silvestre en celo. Como no era la primera vez que no presentaba un trabajo (dos años sin típex dan para muchos trabajos sin presentar), Willi se encontró conque para aprobar el curso le habían puesto la condición de... preparar otro trabajo para Septiembre. A máquina, por supuesto (la letra de Willi era deslabazada y poco definida, como corresponde a todo buen informático alfa).

Como la necesidad aguza el ingenio, Willi pensó una solución a sus males. Cogió cuatro condensadores, unas resistencias, una caja de zapatos, una malla de las patatas, un gnomo del bosque (esto es sólo una leyenda urbana no verificada, al contrario que el resto del artículo), un cristal de la ventana y unos botones de camisa, se puso manos a la obra y creó... el primer ordenador. Gracias a él, cada vez que se equivocaba al pulsar el botón equivocado mientras escribía, podía apretar la goma de borrar (en un alarde de ingenio y originalidad Willi usó una goma de borrar Milán en lugar de un botón para eliminar la última letra escrita), y no tenía que volver a empezar cada vez que la cagaba. Willi celebró su hallazgo durmiendo una profunda siesta de 3 horas.

El día antes de la fecha límite de entrega del trabajo, Willi se dio cuenta de una cosa... tenía todos los bytes del trabajo guardados en el tambor de Colón floppy que le servía de almacenamiento, pero no podía llevar el trabajo así, porque el profesor no estaba preparado aún para tamaño avance (y aparte de eso, no tenía su dirección de email). Se puso manos a la obra y con unas agujas de coser, unas plastilinas y el líquido de siete latas de calamares en su tinta, creó la primera impresora, con la que pudo plasmar el trabajo en papel y entregarlo. Es verdad que tuvo suerte para que su madre tuviera la despensa llena de latas de calamares, y que estos no fueran en salsa americana (el mundo no estaba aún preparado para las impresiones en color), pero lo cierto es que esta es otra de las características que persiguen a los informáticos alfa: cuanto más acorralados parece que están, más suerte tienen.

de desmotivaciones.es
¿Por qué sucede esto?. Obviamente, es una cuestión evolutiva. La Naturaleza ayuda al ser humano a garantizar su supervicencia, y en los momentos importantes es capaz de dar un empujoncito para apoyar estos sucesos que nos hacen evolucionar. Dios no juega a los dados. Si Willi no hubiera sido más vago que la chaqueta de un guarda, hubiera escrito otra vez su trabajo, que tampoco era para tanto el sufrimiento, y por tanto no hubiera creado nunca un ordenador. Y la Informática no hubiera existido jamás.

El arma principal del informático alfa, que ya hemos visto en acción en la emotiva historia de Willi, es el detector de coñazos. El informático alfa tiene un detector natural que le hace percibir de forma inequívoca cuándo una tarea es automatizable y optimizable, y se debería buscar una forma diferente de hacerla, o de evitarla para que no sea necesaria. Y lo siente en forma de coñazo. Y lo siente tan fuerte, que recibe unas energías que hacen aumentar su ingenio y le ayudan a encontrar una solución que optimice el trabajo, y que por tanto le distinguen frente al resto de informáticos obedientes.

Ejemplos los tenemos a patadas. Toda la evolución de los procesos y herramientas de desarrollo de aplicaciones ha surgido a partir de informáticos alfa. Todas las herramientas de desarrollo las ha creado uno de ellos, como no podía ser de otra forma. Y las metodologías ágiles, por ejemplo, son resultado indudable de la agitada mente de un informático alfa, que supo usar su detector de coñazos para percibir que las metodologías estaban llenitas de ellos, que escribir documentación para los programas era un aburrimiento y no podía ser bueno, que las reuniones eternas con clientes en las que no se avanza nada no hay cristo que las aguante, y que las estimaciones y los planes definidos a largo plazo acaban llevando a hacer tareas poco lógicas, sin sentido y, claro, aburridas.

de himajina.blogspot.com
Quizá pienses que si el candidato es tan vago no hará nada y punto. Pero te equivocas. El informático vago disfruta trabajando para no trabajar. Y en el fondo es conocedor del importante papel que tiene en el desarrollo de la Humanidad, aunque no necesariamente de forma consciente. Su detector de coñazos le convierte en el mejor definidor y propulsor de buenas prácticas de desarrollo. Y ya hemos visto la importancia de todo esto para cualquier mínima evolución en el mundo de la Informática.

¿Me crees ya?.

Pues ahora escucha, amigo cazador de talentos. Si me haces caso, puedes resumir tus entrevistas de trabajo en una sola pregunta:

1.a. ¿Te definirías a ti mismo como un vagazo?

Ni siquiera hace falta hacerla en persona, puedes mandar un formulario a los candidatos, o una encuesta online. Y tendrás una efectividad del 100%.

Por tanto, con esto tienes en tu mano la oportunidad de convertirte en un pionero... de convertirte en EL PRIMER CAZATALENTOS ALFA VAGAZO.

Y pegarte la vida padre, ya puestos.

jueves, 22 de agosto de 2013

Nekromanteia, rituales de los muertos: novela negra no, ¡negrísima!

Introducción

Hoy hablamos sobre "Nekromanteia, rituales de los muertos", una escalofriante novela sobre espíritus y...


Ejem. Después de que Jen... la sensacional Hulka de John Byrne, que tan excelsamente publicó Marvel, y que cada día está más guapa... me haya interrumpido, nos ponemos serios y como decía... con todos ustedes, ¡"Nekromanteia, rituales de los muertos"!. Una novela que no es para tomarse a broma, como vamos a ver.

El Protagonista

No es fácil ser Etham Loss... tu obsesión por el estudio de los misterios que hay más allá de la muerte te ha llevado a no valorar a los vivos, y tu absoluta falta de empatía hace que ni tú mismo seas consciente de tus propios sentimientos y que los evites continuamente, convirtiéndote así en un grandísimo hijo de perra. No tienes amigos, y ni siquiera piensas que te importe. Conoces varias personas dentro del mundo de la nigromancia, sí, pero ninguno se puede considerar realmente un amigo. Ni siquiera tu maestra en dicho arte, Noa, siempre queriendo demostrar su superioridad a ti. Ni tampoco otros, como Erictho, esa falsa vidente, o como Margoth, esa hedonista chiflada con demasiado contacto con la magia infernal. Y no hablemos de Darren, ese asqueroso necrófilo idiota, que te es útil para conseguir algunos cadáveres, pero de quien piensas que realmente el mundo estaría mejor sin él. ¿Parejas?. ¿Judith? Muerta. ¿Mara?... Mara... se acaba de suicidar. Y eso te obsesiona, te obsesiona capturar su espíritu, preguntarle por qué ha hecho tal cosa, apresarla todo el tiempo que puedas.

Aparte de eso tienes tus libros, tus conocimientos, tus conjuros... y un puñado de espíritus que a menudo te vienen muy bien para ocupar el cuerpo de alguien y enloquecerlo o matarlo. Al fin y al cabo, uno tiene que tener sus diversiones.

La novela





Uno de los mayores logros que tiene el libro es precisamente conseguir que no chirríe con un personaje tan amoral y falto de empatía como este. Especialmente, cuando es un libro muy en primera persona, es decir, muy centrado en el protagonista, siguiendo continuamente todas sus acciones y pensamientos. Uno de los motivos por los que consigue que sintamos cierta empatía o identificación por él es que está rodeado en general de personajes aún más detestables.

La estructura del libro me recuerda mucho a la novela negra, la de detectives solitarios investigando un crimen y metiéndose en un enorme lío casi sin darse cuenta, normalmente instigados por mujeres malas y de voluptuosas curvas. Sólo que la ambientación cambia por completo. No es un detective solitario borracho y autodestructivo pero duro, sino un nigromante igual de solitario y autodestructivo, pero obsesionado con la muerte... y también duro, claro. No es una mujer mala de voluptuosas curvas la que engaña al detective de primeras, sino que lo que le mueve y le mete en el lío es su propia obsesión por invocar el espíritu de su amante suicida. Y por supuesto, casi sin querer se meterá en un lío, en un enorme lío. Y la mayor parte del tiempo no tendrá ni idea de qué está ocurriendo a su alrededor ni por qué le ocurren las cosas, e incluso muchas veces actuará sin tener muy claro por qué, e intentando coscarse de algo investigando como puede (ya sea hablando con vivos o con muertos, o haciendo visitas a lugares alegres como cementerios o iglesias abandonadas...).

Lo que cambia es el entorno, especialmente la ambientación esotérica. Con eso de tanto invocar espíritus, lo cierto es que lo de estar muerto no es para tanto. La muerte de primeras no es tan definitiva como en otros, y que un personaje muera no significa ni mucho menos que no vaya a volver a aparecer para tener unos momentillos de charla con nuestro nigromante favorito. Y claro, os podéis imaginar que muere un montón de gente. El protagonista no está asediado por un señor feo que le sigue, sino que lo que le acosan son espíritus o "larvas" que quieren adueñarse de su cuerpo. Por otra parte, el lío en el que se mete en el protagonista no es algo como un simple asesinato, sino que lo que tenemos son multitud de cuerpos muertos pululando por la ciudad cual zombies, y cargándose aún más gente. Y cómo no, con el diablo y la magia demoníaca de por medio. Hay momentos en el libro realmente brutos y asquerosillos (no es para todos los estómagos, vaya).

Es decir, que me recuerda a la novela negra, pero deja a aquella en pañales como un simple "gris clarito" y a esta la podemos catalogar como "novela negrísima".

El libro está bien escrito, tiene muchas descripciones realmente desasosegantes. Si se puede leer de noche y bajo la luz de una vela mejor... bueno, si luego somos capaces de dormir, quiero decir. Está muy bien documentado todo el tema esotérico de la nigromancia, los rituales, símbolos, demonios (¡viva Tetragramatón!), incluso con citas de los, esto, "grandes del género", al principio de cada capítulo. Por otro lado, la portada es impresionante. Es de esas que llama la atención, que te deja muy a las claras cómo es el libro (chicos, os presento a Mara, ¿a que es mona?), que invitan a comprarlo y a leerlo.

Aunque el escritor es un "casi novato" (es su segundo libro, más alguna historia corta), el guión está muy bien estructurado. La información va cayendo a cuentagotas, bien dosificada, y nos invita continuamente a averiguar más. El ritmo está bien medido, y la resolución no decepciona. Eso no quita que existan en mi opinión algunos aspectos mejorables. Hay momentos en que se echa de menos algo mas de tensión dramática, quizá todos los personajes sean demasiado parecidos en algunas cosas (básicamente, en ser todos unos hijos de perra sin corazón) y llegue un momento en que falte algo de sentimiento. Por otra parte no me acabó de convencer el principio del libro. Hay varios capítulos al principio que dan sensación al leerlos de ser prácticamente introductorios, que no acaban de meterse en la historia. Está hecho así con un propósito, es parte de la dosificación de la información, pero el problema es que llegas al tercer capítulo y todavía no acabas de tener muy claro qué te están contando, parece todo algo inconexo. No es grave, y lo mismo es sólo una impresión personal. En cualquier caso, luego el libro ya despega y no para.

En definitiva, si te gustan las novelas del género negro y además te atrae el ocultismo y los espíritus que hacen cosas como hablar y controlar un cuerpo para asesinarse a sí mismos, no dejes pasar este libro.

sábado, 27 de julio de 2013

Bootstrap 3 y el marcado semántico

Probablemente estés ya hasta las narices de Bootstrap. Artículos y artículos, herramientas que lo usan o generan código compatible, y lo peor de todo... muchas webs con lo que yo llamo "pestuzo Bootstrap", que no se molestan casi ni en cambiar el estilo que trae por defecto, así que son todas igualicas. Por otra parte, también es posible que no lo hayas usado jamás e incluso que ni sepas lo que es.

Acaba de salir la primera release candidate de la versión 3 de Bootstrap, una versión que imagino que puede ser polémica (igual es por eso que la han sacado un Sábado veraniego casi de Agosto), así que aprovecho la ocasión para escribir este artículo. Empezaré contando qué es Bootstrap y qué tiene de bueno, sobre todo para los que no lo conozcáis aún (¿en qué cueva os habéis metido?). Incidiré en cosas que no me gustaron de su planteamiento general, especialmente contaré cómo se puede ir más allá y mejorar la separación entre contenido y presentación, haciendo nuestro código más semántico. Finalmente, aprovecharé que llevo varias semanas usando Bootstrap 3 para contar qué puedes esperar de esta versión y por qué tiene algunos cambios realmente interesantes para el futuro, junto a otros frustrantes para los que ya estaban usando la versión 2.

¿Por qué Bootstrap?

No hay nada que haga a uno sentirse más como un perro apaleado que programar el front de una web. Desde los primeros años de la web, se ha maltratado sistemáticamente todo lo que tenía que ver con su programación, casi siempre por motivos comerciales. Primero la guerra entre Microsoft y Netscape hizo que cada uno usara el JavaScript que le daba la gana. Luego la guerra entre Microsoft y... el resto del mundo, hizo... que en general Micro$oft interpretara cualquier posible estándar de la web como le diera la gana. Programar JavaScript y CSS significaba, básicamente, perder días y días pegándose en dura batalla con los navegadores, fundamentalmente con todas y cada una de las versiones de IE, ya que era con diferencia el navegador más utilizado y encima ninguna versión era igual a la anterior (ni tampoco se acogía a los estándares).

de html5code.com
Perdón, ¿estoy hablando en pasado?. Me temo que eso aún no ha acabado. Internet Explorer 8, aún uno de los navegadores más usados, sigue haciendo lo que le da la gana con muchas cosas. No he probado aún lo suficiente IE9 para saber si también es así, aunque algo he oído de que avanza bastante respecto a las versiones anteriores en cuanto a su estandarización pero todavía no acaba de cuajar. ¿Quizá IE10?.

Los estándares intentan moverse, modernizarse. No es normal que después de tanta guerra estemos casi en el mismo punto que hace 20 años. Se crea HTML5, sí... y después de varios años, todavía es una "candidate recommendation" y cada navegador implementa las partes que quiere. CSS3... más o menos lo mismo, con la coña de que tiene partes aprobadas y otras que aún no.

El precio de todo esto es enorme. Hacer una aplicación web es muchísimo más costoso de lo que debería, y la web avanza mucho más lentamente de lo que sería normal.

Como ocurre a menudo, las soluciones las ha ido proporcionando la propia comunidad. No necesitamos estándares de iure, tengamos estándares de facto. Así, especialmente en el campo del JavaScript fueron surgiendo librerías que encapsulaban las diferencias entre los navegadores, fundamentalmente en el acceso a DOM: MooTools, Prototype... y sobre todo la que finalmente parece que se alzó como la ganadora, jQuery.

Sin embargo, la revolución real está ocurriendo ahora mismo. En cuestión de estos últimos meses. En estos momentos, Internet Explorer ya no es el rey, y está en un declive cada vez mayor. Y ahora están saliendo productos que crean una capa por encima de HTML-CSS-JavaScript. Productos con una pinta estupenda, y que facilitan la programación del front. Entre ellos, seguramente el más popular ahora mismo sea Bootstrap.

Primera impresión

La primera impresión es muy buena. Bootstrap utiliza un curioso sistema para facilitar muchísimo el diseño de la web. Lo que predica es lo siguiente: utiliza HTML5 estándar para hacer la web, y coloca estratégicamente determinados "class" en cada elemento para conseguir:
  • Un sencillo pero potente sistema de layout, basado en filas y columnas.
  • Varios componentes prediseñados. Algunos de ellos, con código JavaScript listo para hacer que esos componentes sean dinámicos, sin que tengas que hacer nada de primeras. Así tendremos botones, pestañas, menús con varios niveles, componentes de paginación... un gran número de elementos que HTML no incorpora, pero que se utilizan habitualmente como interfaz de usuario en muchas webs.
Este es un ejemplo de código HTML (de Bootstrap 2). Obsérvense los distintos class que tiene:

<div class="container">
   <!-- Main hero unit for a primary marketing message or call to action -->
   <div class="hero-unit">
     <h1>Hello, world!</h1>
     <p>This is a template for a simple marketing or informational website. It includes a large callout called the hero unit and three supporting pieces of content. Use it as a starting point to create something more unique.</p>
     <p><a href="#" class="btn btn-primary btn-large">Learn more »</a></p>
   </div>

   <!-- Example row of columns -->
   <div class="row">
     <div class="span4">
       <h2>Heading</h2>
       <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>
       <p><a class="btn" href="#">View details »</a></p>
     </div>
     <div class="span4">
       <h2>Heading</h2>
       <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>
       <p><a class="btn" href="#">View details »</a></p>
    </div>
     <div class="span4">
       <h2>Heading</h2>
       <p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p>
       <p><a class="btn" href="#">View details »</a></p>
     </div>
   </div>
</div> <!-- /container -->

Hacer una web con este sistema es realmente fácil, y aunque no toques apenas nada la web ya te quedará con una pinta bastante decente.

La distribución "normal" de Bootstrap trae un fichero .js y un fichero .css. Para personalizar los estilos, se supone que hay que añadir más reglas CSS, o al menos eso es a lo que parece que te invita.

Sin embargo, aunque esta es la forma de programar que propone Bootstrap, lo cierto es que no nos deberíamos conformar con eso. Eso sí, me gustaría recalcar que es una forma muy interesante y rápida por ejemplo para crear prototipos de una web. Pero si estamos haciendo algo serio podemos exigir más.

Personalizando con LESS

Modificar directamente el CSS tiene un problema, y es que estamos perdiendo una de las ventajas más importantes que realmente tiene Bootstrap, y es que está hecho en LESS. De hecho, Bootstrap se puede considerar una librería de LESS unida a otra de JavaScript.

LESS es un lenguaje que se construye sobre CSS, añadiendo características muy cómodas, fundamentalmente:

  • Anidamiento de reglas, que mejora mucho la legibilidad y te facilita el que haya un orden dentro del fichero (los ficheros CSS tienden naturalmente al caos más absoluto)
  • Variables: puedes meter valores comunes como colores, tamaños de padding, etc. en variables, y utilizarlas luego en otras reglas
  • Funciones y operaciones: también puedes crear valores que resulten de aplicar una operación sobre otro valor, como por ejemplo poner un color que sea un 20% más oscuro que otro (el cual puede estar, por ejemplo, en una variable).
  • Mixins: esto es lo más importante que aporta LESS. Los mixins son conjuntos de reglas que puedes usar en distintos sitios. Es decir, permite crear componentes reutilizables de CSS.

La librería LESS de Bootstrap está en general bien diseñada. Hay un fichero "variables.less" que tiene un montón de variables con las que se pueden controlar y personalizar muchísimos aspectos de la presentación por defecto: colores, fuentes, espaciados de márgenes y paddings... Otro fichero, "mixins.less" contiene un montón de mixins muy útiles de propósito general.

El resto de ficheros .less están dedicados a componentes o partes específicas: botones, tablas, barras de navegación, etc. En ellos se encuentran los estilos por defecto para todos estos tipos de elementos, junto a opciones de presentación de cada uno según sus clases.

Imagino que Bootstrap no incluye los ficheros LESS en la distribución normal porque intenta facilitar al máximo el que cualquiera pueda usarlo. Es decir, trata a los usuarios como idiotas. En mi opinión esta es un arma de doble filo, porque lo que está consiguiendo con ello es que mucha gente personalice muy poco lo que viene por defecto, consiguiendo así el efecto "pestuzo Bootstrap" que hay en tantas y tantas webs, y que comentaba al principio del artículo.

Créeme, trabaja directamente utilizando los ficheros .less, y creando otros less propios que redefinan las variables y pongan tus estilos. Es mucho más cómodo y a la vez mucho más potente (salvo que seas un idiota, claro).

Marcado semántico en Bootstrap

Hace muchos, muchos años, en una galaxia muy, muy lejana, el layout de las páginas se definía directamente dentro del propio HTML usando tablas. Entonces surgió la creación de layouts con CSS, la que se ha venido usando desde entonces. Lo cierto es que esta forma de crear los layouts era un coñazo integral porque cada versión de Internet Explorer interpretaba (y sigue interpretando) las propiedades CSS, y especialmente las que permiten formar layouts, como le daba la gana. A pesar de esto acabó triunfando, y una de las grandes ventajas que defendía el layout por CSS es que gracias a él se podía separar el contenido, la información que queremos mostrar, de la presentación de ese contenido. Se trataba de hacer marcado semántico, dentro de lo posible.

de coding.smashingmagazine.com
¿Cuál es el problema de la forma de hacer layouts que propone Bootstrap?. Pues precisamente esto, que volvemos a mezclar dentro del HTML el layout de la página con el contenido, aunque sea en forma de .class. Pues para eso volvemos a las tablas, ¿no?...

Es prácticamente imposible que el contenido de tu página sea semántico puro y no piense un poco en el layout. Ahí están los div, que sobre todo sirven para agrupar cosas que imaginas que pondrás luego juntas en el layout. Pero sí pienso que es bueno intentar separarlo lo máximo posible.

En mi caso es fundamental esta separación. Trabajo en un producto reutilizable, que se instala en varios clientes y que en cada uno puede cambiar la presentación. Tengo que intentar evitar al máximo el que tenga que modificar el HTML cuando lo único que necesite sea cambiar aspectos de presentación. Aparte de eso, aunque tu producto no sea reutilizable, pienso que en general es una buena práctica.

¿Entonces?. ¿Pasamos de Bootstrap?. No es necesario. Como ya he comentado antes, BS está basado en LESS. Y esa precisamente va a ser la solución.

Al principio descargué la última versión oficial de BS, la 2.3.2. Algunos de los class de Bootstrap se pueden considerar realmente semánticos: este div va a ser una barra de menú, o un elemento de paginación... Pero otros son claramente de presentación, como por ejemplo si un botón va a ser grande o pequeño, o si una barra de botones se va a poner alineada a la izquierda o a la derecha.

En seguida me di cuenta de que para la mayor parte de los casos, no era realmente necesario poner los class dentro del HTML, aprovechando las capacidades de LESS. Así, por ejemplo, si quiero que los botones de un formulario sean pequeños, no necesito poner el HTML así:

<form class="form-login">
   (...)
   <button type="button" class="btn btn-small">Ver cambios</button>
</form>


sino que puedo hacer esto otro:

<form class="form-login">
   (...)
   <button type="button" class="btn">Ver cambios</button>
</form>


y luego en el .less:

.form-login {
   .btn {
      .btn-small;
   }
}

Alegría, saltos, fiesta... pero espera... esto no ocurre para todos los casos. O mejor dicho, había un caso fundamental en el que esto no funcionaba: precisamente, el sistema de grid para el layout.

Escondidos entre los .less de Bootstrap encontré unos mixins que me podían ayudar: makeRow y makeColumn. Sin embargo, no funcionaban bien. No era lo mismo poner los class que usar estos mixins. Mi gozo en un pozo.

Cuando estaba pensando alternativas, encontré que estaba en desarrollo una versión 3. Miro los cambios y ¡bingo!, han cambiado enterito el sistema de grid. Ahora el sistema de grid es mobile-first, y no diferencia entre "filas fluid y no fluid", todas son fluidas. También han cambiado el nombre de los class.

Vuelvo a hacer la prueba y, esta vez sí, compruebo que funciona. Esto es un ejemplo de un grid en Bootstrap hecho con marcado semántico:

<div class="wrapper">
  <div class="content-main">...</div>
  <div class="content-secondary">...</div>
</div>

Y su LESS:
.wrapper {
  .make-row();
}
.content-main {
  .make-column(8);
}
.content-secondary {
  .make-column(3);
  .make-column-offset(1);
}

De hecho, aunque hasta hace poco no estaba y yo tuve que llegar a ello a base de hacer arqueología en el código, estos mixins y la forma de usarlos ya aparecen dentro de la propia documentación del sistema de grid (bueno, a mi me ha servido para copiar el ejemplo...).

No sólo esto, sino que la librería LESS está realmente mejor diseñada. No es sólo el sistema de grids, en general todos los componentes están mucho más basados en mixins, es mucho más fácil hacer marcado semántico ahora que en la versión 2.

Así que sí, querido lector, te lo puedo decir: se puede hacer marcado semántico con Bootstrap.

Bootstrap 3: qué más me voy a encontrar

Si ya eras usuario de Bootstrap 2, tengo una noticia realmente mala para ti: no es sólo que tu código anterior no sea compatible. Es que ha cambiado un montón, muchas veces en cosas muy pequeñas.

Lo primero que te vas a encontrar es que ha cambiado el aspecto por defecto. El diseño actual pretende ser más "aséptico", menos intrusivo. Los botones y otros elementos no tienen detalles como gradientes, es un diseño más plano, más "metro". Esto es fácil de ver, basta conque vayas a la página principal de Bootstrap, porque lo que se está mostrando ahí ya es la versión 3.

Lo segundo que te vas a encontrar es que han cambiado el nombre de un montón de clases y variables. La intención es hacer los nombres más homogéneos, y en verdad lo han conseguido. Pero olvídate de que tu código funcione con ellos, claro. Los más obvios son los del sistema de layout, cuando antes se ponían las columnas con elementos como "span3" y las filas muchas veces con "row-fluid", ahora hay que utilizar cosas como "col-3" o "col-lg-3", y las filas van siempre con "row". Pero hay que decir que no se han cortado nada, han cambiado muchísimos nombres.

En cuanto a los formularios, ahora los componentes ocupan por defecto el 100% del ancho disponible, y han cambiado por completo la forma de agrupar campos.

de soyouwanna.com
Los iconos también se han rediseñado por completo, ahora se dibujan con una fuente (es decir, son glyphicons). Bueno, y han cambiado los nombres de los class, claro.

Han desaparecido muchas opciones de presentación de los distintos elementos, muchos "-inverse" por ejemplo, y muchas formas de agrupar tipos de elementos. También han desaparecido elementos enteritos, como los thumbnails. A cambio, aparecen otros nuevos como los panels y los list groups.

Si además pretendes que tu código sea compatible con IE7 o Firefox 3.6, ni intentes actualizarte: BS3 ha dejado de ser compatible con ellos.

Pero bueno, lo mejor es que chequees tú mismo la gran lista oficial de cambios realizados para la versión 3.

Habrá que ver a partir de ahora qué harán todas esas webs que generan código Bootstrap de forma gráfica, o que venden temas ya prediseñados, y que al fin y al cabo pueden considerarse una de las ventajas de usar Bootstrap: su popularidad. ¿Se actualizarán?, ¿no se actualizarán?, ¿se mantendrán compatibles con las dos versiones? (posiblemente la mejor opción). Algunas de ellas son estas:


En definitiva, si eras usuario de Bootstrap 2, actualizar tu HTML a BS3 no será nada sencillo. A pesar de eso, opino que los cambios en general son para mejor, la librería está mejor organizada, es mucho más fácil hacer HTML más semántico, los nombres son más homogéneos, y se han eliminado muchas opciones que eran quizá demasiado intrusivas.

Aunque bah! la verdad es que todo eso me importa un pimiento. Como no llegué a usar nunca la versión 2, lo único que realmente quería es que me dejara hacer marcado semántico, y ahora... ¡se puede!.

cookie consent