All posts by El Javi

El Patrón Promise

El patrón Promise es precisamente nuevo, pero está creciendo en popularidad a raíz del gran uso que se hace de él en la API de WinJS, el wrapper JavaScript para hacer a la nueva API WinRT en Windows 8. El objetivo de este patrón es facilitar el modelado de procesos asíncronos, de forma que el código que consuma operaciones que no van a retornar inmediatamente sea lo más legible y fácil de escribir posible.

Escenario actual

La asincronía está de moda. La Nube, aplicaciones “responsivas”, etc. Todo parece empujar a los desarrolladores a hacer un uso cada vez mayor de este tipo de construcciones programáticas. Microsoft ha decidido hacer una apuesta decidida por la asincronía en las aplicaciones Metro con Javascript, por muchas razones.

En primer lugar hay que tomar en consideración también el hecho de que JavaScript sea un lenguaje de ejecución basado en un único hilo, lo que hace que cualquier tarea de larga duración congele la interfaz gráfica, con la consiguiente mala imagen para la aplicación frente al usuario. Además, la visión de Microsoft con respecto a las aplicaciones Metro se basa en fluidez, rapidez de respuesta y sensación de inmediatez, de ahí que la asincronía pase de ser una característica deseada a una obligación absoluta.

Por estas razones Microsoft ha decidido ofrecer versiones asíncronas de la gran mayoría de llamadas al sistema que WinRT pone a disposición de los desarrolladores. Estas llamadas van a implementar, en su gran mayoría, el patrón Promise, para simplificar su uso asíncrono.

Pero, ¿cómo es este patrón? ¿Qué características tiene y cómo podemos usarlo? Veámoslo.

El Patrón

Promises/A es el nombre del estándar detrás de este patrón. En él se propone que los objetos Promise tengan una propiedad then que será una función con tres parámetros:

  • Handler para gestionar el resultado satisfactorio.
  • Handler para gestionar los errores.
  • Handler para gestionar el progreso de la operación.

Al retornar un objeto promise la función estará “prometiendo” retornar un valor en algún punto del futuro próximo.

Esta implementación del estándar es exactamente la misma que ha hecho Microsoft en su librería. En el siguiente fragmento de código

myWebService.get("http://www.javierholguera.com")
    .then(
       function(result) { /* gestionar resultado correcto */},
        function(error) { /* manejar error */},
       function(progress) { /* informar sobre avances */}
     );

Para terminar uno de los principales beneficios del patrón es la facilidad para componer unos promises con otros. Por ejemplo, imaginemos que queremos realizar un proceso asíncrono A y cuando hayamos terminado dicho proceso satisfactoriamente, quedemos ejecutar un segundo proceso asíncrono B. Con el siguiente fragmento de código podemos ver cómo lo haríamos.

procesoA.ejecutar("http://www.javierholguera.com")
    .then(function(result) {
         // gestionamos el resultado de A ejecutando el proceso B
        // esta funcion retorna el promise del proceso B
        return procesoB.ejecutar(result);
    })
    .then(function() {
        // gestion del exito del proceso B
        console.log('B finalizo correctamente');
    }, function(error) {
        // gestion del error del proceso B 
        console.log('B finalizo con errores');
    });

Podemos apreciar en el código como el segundo .then está ejecutándose sobre el resultado retornado por el primer .then, que es en realidad el promise correspondiente al proceso B. En este caso he omitido, por claridad, el handler para el error en el promise del proceso A, pero podría haberse añadido perfectamente justo a continuación del manejador para el resultado exitoso del proceso A.

Conclusión

Promise es un patrón sencillo pero que nos ayuda a gestionar la asincronía de una forma fácil y limpia. Este patrón tiene una larga vida por delante, como parte fundamental de la API de WinJS en Windows 8, por lo que cuanto antes lo dominemos, antes empezaremos a escribir co´digo asíncrono como las aplicaciones Metro nos exigen.

Move y Merge en TFS

El equipo en el que trabajo está mejorando sus políticas de branching e intentando ser más riguroso a la hora de hacer Scrum.

Recientemente nos vimos en una situación que, aunque debería ser marginal, ocurre en todos los sprints (y probablemente en los de todos los equipos, para ser sinceros): un Product Backlog Item no se completó en el sprint.

Nuestra política de ramas es “un branch por característica”, por lo que tenemos tantos branches como PBIs. Además, para ser un poco más organizados, creamos carpetas padre para los PBIs que se hicieron en un sprint. Por eso, si el sprint es “Release 1 – Sprint 2”, tendremos una carpeta R1S2 que contendrá todos los branches correspondientes a los PBIs de ese sprint.

Solución 1: Llevar a Main

No podemos llevar el código inestable que hay en la rama original a Main y de ahí crear una nueva rama, puesto que estaríamos “rompiendo” Main. Además, tampoco tendría mucho sentido esta duplicidad.

Solución 2: Branch de Branch

Otra posible opción sería hacer un branch del branch original, en la nueva carpeta. Por ejemplo, hacer un branch de R1S2PBIXXX a R1S3PBIXXX, donde XXX es el ID del PBI no completado. El problema de esta solución es que, a la hora de llevar los cambios a Main, nos obligaría a ir hacia atrás en el tiempo, de la última rama a la anterior, y de ahí a Main. También nos obligaría a mantener “viva” la rama original, a la espera de recibir los cambios para poder, después, merguearse a Main y “morir”.

Solución 3: Move del Branch

Está creíamos que era la mejor solución: mover la rama de la carpeta original a la nueva. Por ejemplo, de R1S2 a R1S3. De este modo mantendríamos la rama “enganchada” a Main y podemos hacer el branch directamente desde la nueva posición.

Sin embargo, aquí viene TFS con las rebajas: al hacer el merge de vuelta a Main, interpreta TODOS los ficheros como mergeables, por haber sido movidos. Lo peor es que, si confirmamos el checkin, la historia de ese fichero refleja dicha entrada, aun cuando no hay diferencias reales en su contenido.

Parece ser que este comportamiento es premeditado y probablemente existan buenas razones para ello, pero a nosotros nos obliga a prescindir de esta solución, para no convertir el History de los ficheros en un pequeño caos.

Conclusiones

No existe una buena solución, pero tendremos que tirar con la Solución 2 porque es la única viable a día de hoy.

WebBrowser + Mango = IE9

El otro día me llegó al correo una pregunta que, como de costumbre, no supe responder. Me preguntaban si podíamos esperar que WebBrowser utilizara IE9 como navegador en Mango.

Lo primero que me sugería la lógica es que sí. WebBrowser había estado utilizando IE7 hasta ahora y, puesto que Mango trae como una de sus principales novedades IE9 como navegador, lo normal era esperar que fuera así.

Rebuscando por MSDN (ese sitio donde está toda la información pero es casi imposible encontrar nada), encontré un pequeño artículo sobre los cambios e incompatibilidades de Mango en el que, explícitamente, citaban a WebBrowser y decían lo siguiente (traducción de cosecha propia):

El control WebBrowser para Windows Phone se ha actualizado para soportar Internet Explorer 9. Las aplicaciones que usen este control deberían re-testearse para asegurar su compatibilidad con Internet Explorer 9.

Parecía suficiente, pero ya que tengo instalado Mango en el teléfono, decidí probarlo por mí mismo. Creé un proyecto en el que simplemente incrusté un WebBrowser y una caja de texto para meter una dirección. El resultado lo podéis en la siguientes imágenes, primero navegando a http://user-agent-string.info/parse para conseguir información sobre el User Agent String que está enviando el control WebBrowser.

MangoBrowser_7-31-2011_13.10.33.888

Y, en esta otra, navegando al test ACID3, que aunque no valga de mucho por ser muy poco exhaustivo, sí nos sirve para diferenciar entre IE7 e IE9.

MangoBrowser_ACID3_7-31-2011_13.14.50.684

En definitiva, WebBrowser en Mango SÍ funcionará sobre Internet Explorer 9.

Permisos a NetworkService en remoto

Hoy me he encontrado con una situación que, no siendo habitual, tampoco es tan extraña. Tenía una máquina con un servidor de aplicaciones IIS que hospedaba una aplicación web (unos servicios WCF, por concretar). El Application Pool sobre el que corría dicha aplicación web estaba utilizando la cuenta de Network Service de la máquina, y era preciso que accediera a una base de datos en otra máquina.

Parece fácil, ¿no? Pero, ¿cómo darle permisos a una cuenta que no está en nuestra máquina y que tampoco es una cuenta del dominio en el que se encuentran ambas máquinas? La primera pista la podemos encontrar en IIS.NET, en este post (en inglés). En él nos explican, entre otras muchas cosas, que cada cuenta Network Service de una máquina se convierte en una cuenta distinta cuando trata de acceder a recursos en máquinas distintas. Esta cuenta en la que se “transmuta” Network Service cumple el siguiente patrón:

<nombre_de_dominio><nombre_de_maquina>$

Con lo cual, si nuestra máquina XXX se encuentra en el dominio YYY, su cuenta “transmutada” sería: YYYXXX$. Fácil, ¿verdad? Ahora sólo haría falta dar permisos a dicha cuenta utilizando Management Studio, en el servidor de bases de datos al que queremos atacar. Sin embargo, aquí nos encontramos con otro pequeño problema: Management Studio no es capaz de reconocer dicha cuenta.

Por eso, en su lugar, tendremos que tirar de consola (o de una ventana de query del Management Studio) y ejecutar el siguiente procedimiento almacenado:

exec sp_grantlogin 'nombre_de_dominionombre_de_maquina$'

 

Y, ahora sí, refrescando la carpeta de Logins del servidor SQL Server, podremos a este nuevo login y configurarlo para que tenga los permisos necesarios para acceder a la base de datos que toca.

[WCF] Nombres de máquina incorrectos en WSDL

Nos había pasado anteriormente y nos ha vuelto a pasar: WCF nos generaba el documento WSDL con el nombre de la máquina, no con su dominio.

Esto hacía que, por ejemplo, una máquina con nombre XXX en un dominio YYY, aunque su WSDL estuviera accesible en http://XXX/Servicio.svc?wsdl, internamente las rutas del documento WSDL hicieran referencia a http://XXX.YYY/, lo que hacía el WSDL inservible.

Parece ser que, hasta WCF 4.0, la solución no era sencilla: había que parchear este "bug”, “feature” o como queramos llamarlo, tal como se explica en este KB de Microsoft: http://support.microsoft.com/kb/971842/en-us

Sin embargo, a partir de WCF se ha incorporado la corrección y ya podemos tirar directamente de XML y olvidarnos de DLLs. El fragmento sería tan sencillo como éste:

<behaviors>
  <serviceBehaviors>
    <behavior>
      <!-- Necessary to avoid problems with domain/computer names -->
      <useRequestHeadersForMetadataAddress>
        <defaultPorts>
          <add scheme="http" port="80" />
        </defaultPorts>
      </useRequestHeadersForMetadataAddress>
    </behavior>
  </serviceBehaviors>
</behaviors>

Con esto ya tendremos nuestros WSDLs enlazando internamente de forma correcta el resto de elementos de que se compone.

Rulesets y branches

Desde la versión 2010 de Visual Studio podemos configurar rulesets específicos para cada proyecto, que se guardan como ficheros con extensión .ruleset.

Esta nueva forma de gestionarlo es muy flexible y nos permite controlar cómo de estricto es Code Analysis a la hora de realizar el análisis estático de cada uno de los proyectos de nuestra solución.

Por supuesto, si todo el proyecto comparte unas mismas reglas, es perfectamente posible compartir un único fichero (la solución que, en mi caso, adopto el 99% de las ocasiones).

Puesto que los rulesets pueden definirse para cada proyecto, dicha configuración se refleja en el .csproj. de dicho proyecto. La buena noticia es que la ruta es relativa, con lo cual en el momento de crear nuevas ramas, no tendremos ningún problema. La nueva versión del .csproj en la nueva rama hará referencia directamente a la nueva versión del fichero .ruleset que también habremos brancheado (ojo con esto si estamos haciendo branches parciales).

Sin embargo, hay un comportamiento no deseado: cuando se mueve un proyecto, la ruta relativa no se actualiza. Por lo tanto, deja de hacer referencia a nada que exista, al haberse desplazado la posición del fichero .csproj.

En este caso, al compilar en Visual Studio, recibiremos un warning avisando de que, al no haber podido cargar el ruleset para el proyecto, no se ha ejecutado Code Analysis.

La solución es fácil: abrir las propiedades del proyecto y volver a seleccionar el ruleset correspondiente a la rama en la que nos encontramos. Pero ojo al realizar esta operación, puesto que en el combo de seleccionar, por defecto, no vamos a ver ese fichero.

ruleset

En su lugar, sí nos va a aparecer una entrada relativa al fichero original, aquél del que hemos hecho el branch, y es muy sencillo no percatarnos de ellos y elegirlo (puesto que, al ser nuestro branch una copia, tendrá el mismo nombre).

En definitiva, los rulesets y los branches funcionan perfectamente, pero debemos tener cierto cuidado en caso de que movamos alguno de nuestros proyectos. En tal situación, actualizar las propiedades del proyecto con cierto cuidado de no elegir el ruleset equivocado.

CollectionAssert.AreEqual vs CollectionAssert.AreEquivalent

Como parte de mi trabajo diario tengo que hacer bastantes tests unitarios. Por esta razón me he ido familiarizando con las distintas clases que el framework de testeo de Visual Studio nos ofrece al respecto.

Una de las últimas que descubrí pero, por otra parte, de las más útiles, es CollectionAssert. Esta clase permite realizar aserciones sobre colecciones y listas, como su propio nombre indica.

Dos son los métodos que más frecuentemente utilizo, pero cuya semántica es lo bastante parecida como para merecer una explicación un poco más detallada:

  • AreEqual: este método compara dos colecciones y se asegura de ambas tienen los mismos elementos, en el mismo orden y la misma cantidad.
  • AreEquivalente: este método, sin embargo, simplemente comprueba que ambas colecciones tengan los mismos elementos y en la misma cantidad, sin importar el orden en que se encuentren.

Por lo tanto, AreEqual no es más que una versión más restricctiva de AreEquivalent, útil si queremos hacer una aserción más precisa en nuestras pruebas.

Estudio sobre IE9 y los nuevos estándares

IE9image

Como dije en la presentación del “Estudio sobre Internet Explorer 9 y los nuevos estándares web” que he elaborado, no siempre me queda el tiempo que me gustaría para poder actualizar periódicamente el blog.

Hoy vuelvo después de un par de meses sin escribir nada, poniendo a disposición de quien esté interesado este whitepaper. La temática del mismo es analizar, en primer lugar, todo lo que tiene que ver con estándares web, sus organismos, sus etapas de madurez etc.

El whitepaper hace un especial énfasis en todo lo que tiene que ver con el testeo y prueba de los nuevos estándares, particularmente HMTL5. Este tema está sujeto a un alto grado de desinformación, por lo que me parece muy importante tener claro qué podemos considerar información útil y qué simple FUD.

También se analiza en detalle el papel que está desempeñando Microsoft en el proceso de publicación de estos nuevos estándares web, tanto desde el punto de vista de colaboración con el W3C como en la implementación que se ha hecho de ellos en IE9. En este sentido, se aporta información profunda y detallada de cada estándar implementado así como las características soportadas del mismo.

Por último, aún cuando no es estrictamente un tema relacionado con estándares, se dedican unas cuantas páginas a analizar las mejoras de rendimiento de IE9 y la nueva característica de “Sitios Anclados” (Pinned Sites en inglés), que facilita un altísimo grado de integración de los sitios web con el sistema operativo, consiguiendo que su experiencia de uso se asemeje a la de una aplicación de escritorio.

Espero que os guste y, por supuesto, son bienvenidos todos los comentarios, tanto los laudatorios como los críticos (estos nunca faltan :) )

Update: La gente de Microsoft ha tenido el detalle de colgarlo en sus servidores, así que también podéis descargarlo en formato PDF y en formato XPS.

HTML5: Primeros pasos

Es la tecnología del momento, y probablemente del futuro: HTML5.

En este primer post voy a empezar por lo más básico: algunas de las nuevas etiquetas que han aparecido con el nuevo (futuro) estándar. En concreto, estas nuevas etiquetas han surgido con la idea de dotar de una mayor semántica a la Web. Hace unos años la gente de Google realizó un estudio sobre los “class names” más populares. En el Top-20 aparecieron términos como “footer”, “header” “nav” o “sidebar”. No es, en realidad, nada sorprendente si tenemos en cuenta que muchos sitios web siguen una misma estructura.

Con HTML5 sus creadores han pensado que, en lugar de seguir utilizando etiquetas <div> sin ningún tipo de semántica para definir estas partes de las páginas web, resulta mucho más interesante poder definirlas con etiquetas específicamente pensadas para ellas, que ayuden a identificar sin ninguna duda que el contenido es una cabecera, un pie, una barra lateral, etc. Sin embargo, nos debemos confundir semántica con estructura. Es decir, cuando estemos utilizando una de estas etiquetas, estaremos indicando que lo que contienen es una cabecera, pie, etc, pero no su posición o aspecto en ningún modo.

Veamos estas nuevas etiquetas y el uso recomendado de ellas.

 

Etiqueta <header>

La etiqueta <header> está pensada para definir, como su nombre indica, cabeceras de elementos. No está restringida sólo a su uso a nivel de página. Es decir, que podemos encontrar etiquetas <header> como cabecera de otros elementos, como podría ser el título de un artículo en un blog o el encabezado en una lista de secciones.

No es una etiqueta obligatoria y su uso más habitual será como primer elemento de la página, conteniendo el título de la página, logos o elementos de navegación comunes a todo el sitio.

<header>

  <h1>Esto es una cabecera.</h1>

</header>

 

Por otra parte, la etiqueta <header> también puede contener los típicos enlaces navegacionales que se comparten entre todas las páginas web y que, semánticamente hablando, también forman parte de la cabecera del sitio.

 

Etiqueta <nav>

La etiqueta <nav> está pensada para destacar una sección en la página que contenga enlaces a otras páginas o a la misma, lo cual no significa que cualquier conjunto de enlaces sean candidatos a ir contenidos dentro de una etiqueta <nav>. En la misma especificación se propone un ejemplo de enlaces que no se envuelven en una etiqueta: los enlaces que aparece en el pie de página, apuntando a información legal, copyright, etc; en este caso basta con envolverlos en una etiqueta <footer> (de la que hablaremos más adelante).

Como ocurre con la etiqueta <header>, es posible hacer uso de más de una etiqueta <nav> en una misma página. Otro ejemplo típico de esta posibilidad es una página en la que tengamos enlaces a la navegación a través del sitio en la cabecera (en este caso la etiqueta <nav> muy probablemente irá insertada dentro de una etiqueta <header>), mientras que en el contenido de la página podemos tener una serie de enlaces apuntando a secciones dentro de ese contenido.

<header>

  <h1>Mi sitio web</h1>

  <nav>

    <h2>Enlaces del sitio:</h2>

    <ul>

      <li><a href="default.aspx">Portada</a></li>

      <li><a href="articulos.aspx">Articulos</a></li>

      <li><a href="contacto.aspx">Contacto</a></li>

    </ul>

  </nav>

</header>

 

En este ejemplo podemos ver las etiquetas <header> y <nav> juntas. La etiqueta <nav> no es más que un contenedor, es decir, no sustituye a las etiquetas <ul> y <ol> a la hora de definir una lista de enlaces. Por otra parte, los enlaces pueden presentarse en otro formato que no sea una lista, si se considera oportuno.

 

Etiqueta <footer>

La etiqueta <footer> representa un pie para varios tipos elementos de una página y no sólo la página en sí misma. Algunos de estos elementos son elementos <article>, <nav>, <aside>, <section>, <blockquote>, etc. En general, es posible tener un pie en cualquier elemento “sectioning content” y “sectioning root”. Podemos intuir, por tanto, que es posible tener más de un elemento <footer> por página.

En estos elementos <footer> normalmente incluiremos información sobre la sección a la que se asocian; información como quién la escribió, enlaces a documentos relacionados, copyright, etc. (según se define en la especificación).

<body>

  <header>

    <h1>Mi sitio</h1>

  </header>

  <article>

    <h2>Mi articulo>

    <p>Contenido del articulo</p>

    <footer>Pie del articulo</footer>

  </article>

  <footer>

    <h3>Pie de la pagina</h3>

    <p>Informacion de copyright</p>

  </footer>

</body>

 

En este ejemplo podemos ver juntas etiquetas <footer> como pie de un elemento (en este caso el elemento <article>, que veremos más adelante) y como pie de la página web entera.

 

Etiqueta <section>

La etiqueta <section> ha sido creada con la idea de representar secciones de contenido relacionado en un documento, normalmente con una cabecera. Esta definición resulta lo suficientemente genérica como para que algunos se hayan aventurado a apuntar a esta etiqueta como el sustituto de la etiqueta <div>.

Sin embargo, en la especificación se nos previene específicamente contra este mal uso, indicándonos una regla para poder discernir cuándo elegir una de las dos. Una traducción “libre” de la documentación sería ésta:

Cuando un elemento se crea para darle estilo o para realizar scripting sobre él, se debe utilizar una etiqueta <div>. En general, la etiqueta <section> es conveniente si va a aparecer explícitamente listada y visible en el documento.

Otra controversia de esta etiqueta es con dos parientes “cercanos”, nuevas etiquetas también, que veremos más adelante: <article> y <aside>. La razón es su similitud semántica, especialmente con la primera de ellas. Sin embargo, en la especificación se define un modo sencillo y directo de diferenciar entre ambas etiquetas:

Se debe utilizar <article> en lugar de <section> cuando tiene sentido la sindicación del contenido del elemento.

Un ejemplo de uso de <section> y <article> combinados podemos verlo en el siguiente punto.

 

Etiqueta <article>

La etiqueta <article> está diseñada para representar elementos “auto-contenidos”; es decir, son elementos que pueden ser distribuidos o publicados (mediante sindicación) de forma independiente. Los ejemplos más típicos son posts de un blog, comentarios, respuestas de un foro, artículos, etc.

Esta etiqueta permite anidar en su interior otras etiquetas <article> iguales. Tomando los ejemplos anteriores, podríamos definir una entrada de un blog como <article> y hacer lo propio con etiquetas <article> anidadas para cada uno de los comentarios de dicha entrada.

<article>

  <h2>Mi nueva entrada</h2>

  <p>Este es el contenido de la nueva entrada en mi blog</p>

  <section>

    <h3>Comentarios</h3>

    <article>

      <p>Mi comentario a tu entrada</p>

      <footer>

        <p>Por usuario1</p>

      </footer>

    </article>

    <article>

      <p>Otro comentario a tu entrada</p>

      <footer>

        <p>Por usuario2</p>

      </footer>

    </article>

  </section>

</article>

 

Etiqueta <aside>

La etiqueta <aside> nos permite representar el concepto de “sidebar” o barra lateral. Sin embargo, no debemos pensar que necesariamente estará situada en una posición determinada. Como con todas las etiquetas presentadas en este artículo, su contenido es meramente semántico, no estructural o posicional.

La definición que nos aporta el estándar describe este elemento como una sección del elemento con contenido tangencial al mismo, relacionado pero separado. Entre los ejemplos que podemos encontrar, destacan las clásicas barras laterales que aparecen en muchas páginas web, así como otros menos intuitivos los “pullquotes” (textos destacados dentro de un artículo para enfatizar). En ambos casos es posible su eliminación sin afectar al contenido.

<aside>

  <h1>Datos HTML5</h1>

  <p>Aquí podríamos indicar un hecho relevante sobre HTML5 pero no relacionado con este articulo</p>

<aside>

 

Conclusiones

Hemos visto algunas de las nuevas etiquetas que se han añadido a HTML5 con la idea de dotar de mayor semántica al lenguaje a la hora de definir los contenidos. Sin embargo, no debemos perder de vista que estas etiquetas sólo aportan semántica; es decir, no nos indican ni la estructura ni la posición ni el orden de los elementos que, con ellas, estamos definiendo. Por tanto, no debemos pensar que sólo existirá un <header> o un <footer> en una página, o que deberán aparecer al principio o al final de la misma, o que los elementos dentro de <aside> deben colocarse en un lateral.

 

BIBLIOGRAFÍA

IE9 y el Dead Code Elimination

Llevamos muchos años oyendo que Mozilla Firefox es el navegador más rápido. Unos cuantos menos oyendo que Google Chrome es aún más rápido. Y aún más oyendo decir que Internet Explorer era el más lento de todos. Se ha convertido en una especie de mantra, de verdad fundamental e incuestionable. Casi tan incuestionable como que los ingenieros de Microsoft son todos borderline.

Pero resulta que en el último año los borderline se han puesto las pilas con Internet Explorer 9 y llevan un año mostrándonos como, Platform Preview tras Platform Preview, IE9 iba poco a poco reduciendo la diferencia que le separaba de Firefox y Chrome en muchos aspectos, especialmente en el capítulo de soporte a estándares y rendimiento.

En cuanto al primero, asistimos a un ejercicio curioso de manipulación. Cualquiera que esté mínimamente informado sabrá que HTML5 no es un estándar, sino un borrador de trabajo (Working Draft) sobre un futuro estándar. Borrador de trabajo que, por cierto, algunos estiman que no será aprobado como estándar de forma oficial hasta… ¡2022! (no lo digo yo, ni Microsoft, lo dice el editor del estándar, empleado de Google para más señas).

Pues esta verdad con respecto a HTML5 y al hecho de que no es más que un borrador, no impide a algunos atacar a otros bajo la ofensa de no haber implementado características del borrador que no son, ni mucho menos, estables. Sentencia: se sigue sin ser respetuoso con los estándares (a pesar de no existir como tales).

La Noticia

Pero si el proceso resulta bastante evidente con respecto al soporte a estándares, no menos lo es en lo que respeta al rendimiento. Está claro que no resulta sencillo aceptar que las cosas están cambiando. A todos nos pasa, damos algo tan por sentado que cuando deja de ser así, preferimos mirar para otro lado o rebelarnos ante ello. Esto último está pasando con la reciente noticia de que IE9 Platform Preview es el navegador más rápido en el test de SunSpider. No voy a hablar de aceleración por hardware, porque si nos metemos en ese terreno la ventaja es tan abrumadora que nadie podría poner en duda que IE9 es, hoy en día, líder indiscutible en prácticamente todos los aspectos.

EL FUD (Fear, Uncertainty and Doubt)

El FUD, ese viejo conocido. Si preguntas a cualquier persona que pertenezca al software libre o que tenga antipatía de algún modo por Microsoft (puedes entrar en Barrapunto o Meneame y elegir al azar), te dirá que lo inventó Microsoft.

Puede que sea verdad, pero lo que es indudablemente cierto es que ha hecho aparición para amortiguar el efecto mediático que habría supuesto que IE9 fuera más rápido que ningún otro navegador, en un microbenchmark creado por la competencia (Sunspider es obra de la gente de WebKit, motor de Safari y Chrome entre otros).

El resultado ha sido muy satisfactorio. Acceder a Google, poner los términos Internet Explorer y Sunspider, no nos devuelve ningún resultado la primera página relacionado con el éxito de IE9, sólo nos habla del posible (para algunos indudable) asunto de las “trampas” en el microbenchmark. Es decir, hemos pasado de una publicidad positiva basada en hechos objetivos, a una publicidad negativa basada en un supuesto no demostrado y en la viralidad que cualquier crítica, justificada o no, adquiere cuando el objeto del chismorreo es Microsoft. Si esto no es FUD de manual, ya me diréis.

El Chismorreo

El chismorreo empezó como empiezan estas cosas, con una opinión legítima: un desarrollador de Mozilla se preguntaba porqué Chackra, el motor de Javascript que lleva IE9, no ejecutaba una función parte de uno de los tests (math-cordic) que se ejecutan en Sunspider. En principio se planteaba si era posible que se debiera a la detección de ese método como candidato a una Dead Code Elimination.

Una optimización de este tipo busca código que no tiene ningún efecto de un programa y lo elimina. Cuando trabajamos con entornos sin análisis estático del código, es relativamente sencillo no darse cuenta de que, probablemente por un error de programación, estamos ejecutando código que no produce ningún resultado. Un ejemplo burdo:

public int Multiplicar(int operando1, int operando2)
{
    int resultado = 0;
    for(int i=0; i<operando2; i++)
    {
        resultado += operando1;
    }

    return operando1 * operando2;
}

En este ejemplo, el bucle es un candidado a ser eliminado, puesto que no realiza ningún función práctica. Exactamente lo mismo ocurría con el método cordicsincos() objeto de esta polémica.

A partir de aquí, el revuelo cuando alguien decidió sugerir que esto no era una simple característica nueva en Chackra sino una optimización específicamente pensada para mejorar los resultados en Sunspider y colocarse primero. “Cheat” y “Microsoft” juntos en la misma frase, resultado esperado: el rumor se extendió por la pólvora. La base para tal afirmación estaba en el hecho de que, modificando el código y manteniendo un fragmento candidado a ser eliminado, el sistema de análisis del DCE no lo descubría y no lo borraba.

De poco ha valido la explicación que ha aportado la gente del equipo de IE9 en su blog: DCE es una nueva característica, está en desarrollo y no cubre todos los escenarios, además de ser necesario mantener un balance entre la cantidad de análisis que se hace sobre el código JS antes de compilarlo, y el rendimiento. Obviamente este tipo de análisis no son triviales y requieren de un tiempo que puede, en definitiva, no merecer la pena cuando va a resultar más rápido ejecutar directamente el código innecesario.

Con lo que el escenario en que ahora mismo nos encontramos es que la noticia con respecto a IE9 no es que sea tanto o más rápido que sus competidores en este microbenchmark, sino que un ingenierio de la competencia descubrió que el nuevo sistema de DCE de un código que no es ni siquiera una beta, no es capaz de detectar todos los posibles escenarios, pero sí lo hace con uno concreto que forma parte de un microbenchmark (al que tanto Microsoft como gente de Mozilla han restado importancia puesto que no se asemeja al funcionamiento de los sitios web del mundo real).

Mi conclusión

Creo que no hace falta que la aporte, porque ya se desprende de mi tono en el artículo. Mi experiencia profesional es limitada y también mi conocimiento de los navegadores. No viví la famosa guerra de los 90, ni la forma en que se regía y comportaba Microsoft en aquellos años. No dudo que fuera el “evil” en el que, supuestamente, Google no quiere convertirse.

Pero desde que yo estoy en esta profesión, apróximadamente 2006, no he visto ningún movimiento por parte de Microsoft que haya sido mejor o peor que los que ha llevado a cabo Google, Apple o cualquiera de las grandes compañías en el sector. Sin embargo, mientras a Apple se le ríen las gracias (ayer mismo compré un cable para mi Touch que, por no ser de Apple, no lleva un chip y resulta totalmente inútil, 13 euros a la basura), a Google se le permite que gestione nuestros datos personales con mucha alegría y poca gente habla de lo que está haciendo Oracle con MySQL y Java, a Microsoft se la mira con una lupa lo suficientemente potente como para distorsionar la realidad y ver oscuras conspiraciones donde no hay más que un fragmento de código que no es lo suficientemente completo y maduro como para cubrir todos los escenarios posibles.

Flaco favor nos hacemos los unos a los otros si el escenario de “batalla” se desplaza de la mera destreza técnica a las más burdas tácticas propagandísticas.

Bibliografía: