Mejora Progresiva

By dedalo534

Introducción

En este artículo hablaremos de la diferencia entre dos formas de desarrollo: degradación elegante y mejora progresiva. Haciendo las cosas simples, a continuación las deficiones de trabajo:

Degradación elegante
Proveer una versión alternativa de la funcionalidad, o hacer al usuario consciente de una serie de atajos en un producto, como una medida de seguridad de que ese producto es usable.
Mejora progresiva
Se comienza con una base de funcionalidad usable, entonces se incrementa la riqueza de la experiencia de usuario, paso por paso, testeando el soporte de las mejoras antes de aplicarlas.

Se puede pensar que estos dos enfoques son bastante simuladres, y que ellos dan el mismo resultado, pero hay diferencias de las que hay que tomar nota, como veremos más adelante.

Empezaremos explicando la necesidad de esas dos técnicas. Entonces, iremos a una definición mas profunda, mostrando ejemplos de implementación, y seguiremos con una comparación y guia de cuando hay que usarlas. Pero antes, expliquemos porqué necesitamos técnicas especiales de desarrollo para el desarrollo web.

La estructura de este artículo es la siguiente:

“Mobilis in mobile” — moviéndose en un entorno en constante cambio

Justo como el Capitán Nemo en “20.000 leguas de viaje submarino”, los desarrolladores web se encuentran en constante cambio, y en un entorno que fluctua que puede ser muy hostil a lo que se trata de hacer.

La Web fue inventada y definida para ser usada con cualquier dispositivo, en cualquier lenguaje, donde quiera que deseemos. La una cosa que esperan los usuarios finales es que su dispositivo de navegación pueda alcanzar la web y entender los protocolos utilizados para la transmisión de información: — http, https, ftp y así.

Esto significa que no podemos esperar cualquier cosa de los usuarios finales. Tenemos que tener claro que nuestra experiencia de la web, como desarrolladores, es muy diferente de la de la gente a la queremos llegar.

No existe la obligación de actualizar las tecnologias para acceder a los contenidos en internet. La gente y las compañias se adhieren a un entorno definido, y no lo cambian o actualizan porque nosotros queramos que lo hagan. Mucha gente solo quiere utilizar la web, y son ajenos a las tecnologias que hay detrás — todos ellos esperan ser capaces de obtener el contenido que se le promete. Es a los sistemas operativos y a los desarrolladores de navegadores a quienes compete que los usuarios tengann su sistema al dia — así como los desarrolladores web no tenemos que decir nada en eso.

Todo esto desemboca en un entorno de desarrollo muy frágil, por ejemplo, son muy comunes oficinas donde, por defecto, hay un navegador de unos 9 años de antigüedad, con scripts y plugins desactivados (por razones de seguridad), bajas resoluciones de pantalla, y ordenadores que están al máximo utilizando software de oficina.

Podríamos ir ahora y clamar que compañias como esas han “perdido el barco” y que no hay razón para intentar mantener tecnologia anticuada. Pero esta actitud puede hacer que nos olvidemos que esa gente puede ser muy importante para el éxito de nuestros productos. En algunos casos, no tienen los permisos necesarios para cambiar su configuración técnica. Cuando no viene por temas de accesibilidad, que no son tan obvias, como usuarios disléxicos que no comprenden nuestras enrevesadas instrucciones, o usuarios ciegos, que no pueden “hacer click sobre el boton verde para continuar”, a pesar de que hemos especificado que es necesario para utilizar nuestro sistema.

Nosotros trabajamos en el desconocimiento, y necesitamos una forma de hacer el trabajo. Es por eso que tanto la degradación elegante, como la mejora progresiva entran en el juego.

Degradación elegante y mejora progresiva en pocas palabras

Ya hemos visto una simple definición más arriba; en esta sección veremos una definición más técnica, y echaremos un vistazo a lo que se necesita realmente para implementar estas metodologias.

Así que, la degradación elegante consiste en la construcción de la funcionalidad de una página web, de tal forma que provee un cierto nivel de experiencia de usuario en los navegadores más modernos, pero tambien permite una degradación elegante a un nivel más bajo de experiencia de usuario en navegadores antiguos. Este nivel más bajo no es tan agradable de usar para los visitantes del sitio web, pero aún así provee toda la funcionalidad básica que necesitan para utilizar ese sitio web; las cosas no se rompen para ellos.

La mejora progresiva es parecida, pero hace las cosas de otra forma. Se empieza por estabilizar un nivel básico de experiencia de usuario, que todos los navegadores serán capaces de proporcionar cuando muestren la página web. Pero además se construye una funcionalidad más avanzada que estará disponible de forma automática en los navegadores que puedan utilizarla.

En otras palabras, la degradación elegante comienza en una determinada complejidad, y trata de arreglar las cosas para las experiencias de usuario más bajas; y donde la mejora progresiva comienza desde una base que funciona de forma muy básica, y que permite extender de forma constante en futuros entornos. La degradación elegante significa mirar atrás, mientras que la mejora progresiva significa mirar hacia adelante mientras se mantienen los pies firmes sobre el suelo.

Un ejemplo de degradación elegante frente a mejora progresiva

Echemos un vistazo a un ejemplo mostrándolo desde la mejora progresiva y desde la degradación elegante.

Enlaces “Imprimir la página”

Se podría decir que los enlaces que permiten a los usuarios imprimir el documento actual son innecesarios — pinchar sobre el icono Imprimir del navegador hace lo mismo. No obstante, los test de usuario muestran esto como un ultimo paso en el proceso de generación (por ejemplo, en la web de una aerolínea), como una buena manera de indicar que hay que realizar una acción. Los usuario sienten tener el control de terminar aquello que empezaron.

La parte graciosa de los enlaces “imprimir la página” es que en HTML no hay forma de enlazar con el botón de impresión del navegador — se necesita JavaScript para hacerlo. En JavaScript es facil — el objeto window del navegador tiene un método print(), al que se puede llamar para iniciar una impresión. Probablemente, la forma más común de hacer esto es utilizando el siguiente seudo-protocolo de javascript:

<p id="printthis">
  <a href="javascript:window.print()">Print this page</a>
</p>

Esto funciona cuando JavaScript está disponible y activado, y el navegador soporta el comando print. De todas formas, si JavaScript no está disponible (por ejemplo, en determinados dispositivos móviles), entonces este enlace no funcionará — pinchando sobre él no hará nada en absoluto. Esto crea un problema, porque, como desarrollador de un sitio web, se ha prometido funcionalidad que no estará disponible. Cuando ellos pinchen sobre el enlace y no funcione como ellos esperaban, se sentirán confundidos y decepcionados, y seremos probablemente, destino de su ira por haber tenido una mala experiencia de usuario.

Para hacer esto menos problemático, los desarrolladores de los sitios web se decantan por la degradación elegante: le dicen al usuario que el enlace puede no funcionar, y el porqué de ello, y pueden sugerir una solución alternativa para que lleven a cabo lo que quieren hacer. Un truco muy común es utilizar el elemento noscript. Todo lo que contenga este elemento se mostrará al usuario final cuando JavaScript no esté disponible. En este caso, podría ser lo siguiente:

<p id="printthis">
  <a href="javascript:window.print()">Print this page</a>
</p>
<noscript>
  <p class="scriptwarning">
    Printing the page requires JavaScript to be enabled.
    Please turn it on in your browser.
  </p>
</noscript>

Esto se considera degradación elegante — se explica al usuario que algo no está funcionando, y como rodear ese problema. No obstante, esto asume que los visitantes de la página web:

  • Saben qué es JavaScript
  • Saben cómo activarlo
  • Tienen los permisos y la posibilidad de activarlo
  • Se sienten felices acerca de activar JavaScript para imprimir un documento

Una forma mejor de afrontar este problema podría ser la siguiente:

<p id="printthis">
  <a href="javascript:window.print()">Print this page</a>
</p>
<noscript>
  <p class="scriptwarning">
    Print a copy of your confirmation.
    Select the "Print" icon in your browser,
    or select "Print" from the "File" menu.
  </p>
</noscript>

Esto soluciona practicamente todos los problemas detallados anteriormente, pero asume que la funcionalidad de impresión de todos los navegadores es igual. Pero el hecho sigue estando ahí — el tema con este acercamiento es que se ofrece alguna funcionalidad sabiendo que puede no funcionar, teniendo encima que explicarlo. Técnicamente no hay necesidad para el botón —imprimir esto—, razón por la cual un acercamiendo de mejora progresiva no puede asumir que eso funcione.

Si tenemos que solventar este problema utilizando mejora progresiva, el primer paso sería encontrar si existe una forma de imprimir la página sin utilizar script. No existe, lo que significa que un enlace es la forma equivocada de elemento HTML para usar. Así que si se desea dar funcionalidad que solamente está disponible por medio de JavaScript, se debería utilizar botones: por definición, los botones soportan funcionalidad script . La especificación W3C dice:

botones: los botones no tienen comportamiento por defecto. Cada botón puede tener scripts asociados en el lado cliente, por medio de los atributos de eventos. Cuando un evento ocurre (por ejemplo, el usuario presiona el botón, lo libera, etc.) el script asociado se dispara.

El segundo paso es no asumir que el usuario tiene JavaScript activado, y que el navegador puede imprimir. En vez de eso, se le dice al usuario que tiene que imprimir el documento, y se deja el “cómo” a ellos:

<p id="printthis">Thank you for your order. Please print this page for your records.</p>

Esto funciona en cualquier caso. Para el resto de funcionalidad utilizamos JavaScript discreto para añadir un botón imprimir en aquellos navegadores que lo soporten:

<p id="printthis">Thank you for your order. Please print this page for your records.</p>
<script type="text/javascript">
(function(){
  if(document.getElementById){
    var pt = document.getElementById('printthis');
    if(pt && typeof window.print === 'function'){
      var but = document.createElement('input');
      but.setAttribute('type','button');
      but.setAttribute('value','Print this now');
      but.onclick = function(){
        window.print();
      };
      pt.appendChild(but);
    }
  }
})();</script>

Conviene tomar nota de cómo es de defensivo este script — no se asume nada:

  • Conteniendo toda la funcionalidad en la función anónima, y ejecutándola inmediatamente — esto es lo que hace (function(){})() — no dejamos ninguna variable global atrás.
  • Se testea por el soporte DOM, y se intenta acceder al elemento que deseamos para añadir el boton.
  • Entonces testeamos si el elemento existe, y si el navegador tiene un objeto window y un método print (testeando si la propiedad tipo es una función).
  • Si ambas son ciertas, nosotros creamos un botón y le asignamos window.print() como ejecución para el evento click.
  • El último paso es añadir el boton al párrafo.

Esto funcionará para cada usuario independientemente del entorno técnico. Y no se promete al usuario un elemento en el interfaz que no funcione — en vez de eso, se le muestra sólo cuando vaya a funcionar.

Cúando usar qué

Quizás se puede ser un idealista, pero la idea de la degradación elegante es la que menos gusta. Construyendo algo y haciendolo apenas funcionar en otros entornos (o indicando a los usuario actualizarse), se hace una gran cantidad de hipótesis acerca del entorno y de la habilidad de los usuarios para actualizar.

Por ejemplo, utilizando una Blackberry, cuando no puede encontrar una red wireless, uno se encuentra muy frustrado cuando productos web te dicen que necesitan JavaScript activado, y te exhortan a activarlo. No se puede, defendiendo los derechos de los usuarios de los productos — especialmente cuando se paga una cantidad de dinero por acceso a servicios como GPS o EDGE.

No obstante, la degradación elegante se vuelve viable en unas pocas situaciones:

  • Se está tocando un producto antiguo, y no se dispone de tiempo, acceso, etc, para cambiarlo o reemplazarlo.
  • No se tiene tiempo suficiente para finalizar un producto con total mejoras progresivas (comúnmente un signo de mala planificación o salirse fuera de presupuesto).
  • El producto es un caso extremo, por ejemplo, un sitio de mucho tráfico, donde cada milisegundo de rendimiento significa una diferencia de millones de dólares.
  • El producto es, por definición, tan dependiente de JavaScript, que hace ser más sensato mantener una versión “básica” que mejorar alguna (Mapas, clientes email, lectores de noticias).

En el resto de casos, la mejora progresiva hará ser más felices tanto al usuario como al desarrollador:

  • Independientemente del entorno y la capacidad, se entrega un producto que funciona.
  • Cuando un navegador nuevo llega, o una extensión de navegador es muy usada, se puede mejorar para alcanzar otro nivel sin tener que tocar la solución original — la degradación elegante requeriría modificar la solución original.
  • Se permite a la tecnología ser lo que se supone que debe ser — una forma de alcanzar un objetivo más rápido que sin ella, no un “ tener ” que alcanzar ese objetivo en primer lugar.
  • Si se necesita más funcionalidad, se puede hacer chequeando si está soportada en un cierto nivel, ó se puede añadir al nivel básico de funcionalidad, y después, mejorar para entornos más sofisticados. En cualquier caso, el mantenimiento sucede en el mismo lugar y no en lugares diferentes. Manteniendo un producto mejorado progresivamente en el tiempo, es menos trabajo que mantener dos versiones.

Resúmen

Se puede decir que tanto la mejora progresiva como la degradación elegante intentan hacer la misma cosa: mantener los productos utilizables por cualquier usuario. La mejora progresiva es más sofisticada, y al mismo tiempo, una forma estable de asegurarnos de ello, pero tomas más tiempo y dedicación. La degradación elegante se puede utilizar de forma más sencilla, como un parche para un producto existente; significa más mantenimiento a la larga, pero menos trabajo inicial.

Ejercicios

  • El artículo muestra como ejemplo un enlace de impresión, que puede utilizar cualquiera de los dos enfoques. ¿En qué otros ejemplos puedes pensar?
  • Digamos que se necesita utilizar JavaScript para asegurarnos de que un campo de un formulario contiene una direccion de email, antes de enviar el formulario. ¿Que diferentes enfoques y que otros problemas se podrían tomar en consideración?
  • Digamos que necesitamos mostrar un mapa, y deseamos utilizar mejora progresiva. ¿Cúal debería ser la funcionalidad base de la que deberíamos comenzar?
  • Pongamos que tenemos un interfaz que consiste en dos controles combox. Seleccionando una opcioón en el primero conseguimos cambiar las opciones disponibles en el segundo. ¿Cúal debería ser la base para este tipo de control? ¿Qué problemas puede haber con él?

Acerca del autor

Imagen del autor del art&iacute;culo, Chris Heilmann

Créditos: Bluesmoon

Chris Heilmann ha sido un desarrollador web durante 10 años, después de chapotear en el periodismo de radio. El trabaja para Yahoo! en UK, como formador y desarrollador principal, y supervisa la calidad del código en Europa y Asia.

Tiene un blog en Wait till I come y está disponible en varias redes sociales, como “codepo8”.

This article is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported license.

Comments

The forum archive of this article is still available on My Opera.

No new comments accepted.