Master J2EE de Oracle: Paso 5 de 12: Construir Software más Usable

Puede encontrar la versión original de este artículo en Inglés en:

http://www.oracle.com/technology/pub/articles/masterj2ee/index.html

Evitar una Reconstrucción Extrema

Llevar el analisis de usabilidad dentro del proceso de desarrollo de software ayuda a los arquitectos J2EE a evitar el problema "No podemos cambiar esto".

En el negocio de la construcción, cualquier trabajo de remodelación es mucho más fácil, cuando la infraestructura tiene los elementos correctos en el sitio adecuado para soportar los cambios deseados; el cableado y las tuberías deben cumplir las normas actuales de construcción y estár situadas en las localizaciones adecuadas para una remodelación de la cocina, o para añadir un cuarto de baño, por ejemplo.

De la misma forma, hacer software más usable es mucho más fácil si la arquitectura principal se diseñó con la usabilidad en mente.

Desafortunadamente, este no es el caso normal. Aunque la usabilidad es una cualidad importante en sistemas de software, normalmente no se corrige hasta el final del proceso de desarrollo. Los profesionales de la usabilidad evalúan las reacciones subjetivas de los usuario y usan sistemas en funcionamiento, y luego le dan a las desarrolladores una lista de cambios; algunos de los cuales se pueden incorporar fácilmente en el diseño existente, pero muchos de ellos podrían llegar a ser prohibitivamente caros.

Las investigaciones de usabilidad llaman a esto el problema: "We can't change that" (No podemos cambiar esto): a pesar del uso de arquitecturas de acoplamiento ligero explícitamente diseñadas para acomodar los requerimientos cambiantes, algunos cambios simplemente no se pueden llevar a cabo sin hacer cambios fundamentales (y costosos) a la base de la aplicación.

En este artículo describiremos cómo pueden prepararse mejor los arquitectos para el impacto de las peticiones de usabilidad.

¿Qué necesitan conocer los Arquitectos de J2EE sobre la Usabilidad?

Cuando se trata de usabilidad, los arquitectos deberían saber como evitar el problema No podemos cambiar esto, en vez de cear pantallas intuitivas o diseñar interfaces de usuario a los que los clientes responderán de forma emocional. Las peticiones de cambios de usabilidad relacionadas con la apariencia del UI raramente causan un trabajo excesivo, ya que incluso los desarrolladores novatos en J2EE saben utilizar el patrón MVC para aislar el código que dibuja la Vista del resto del codigo (el Modelo que contiene los datos de la aplicación, y el Controlador que maneja la entrada al procesamiento lógico). Los cambios en el flujo de trabajo o en requerimientos de datos también son poco problemáticos. En general, los cambios orientados a la apariencia requieren algúnos cambios en el código, pero normalmente no causarán una modificación de la propia arquitectura.

Por ejemplo, los marcos de trabajo MVC, como Struts o Spring, le permiten rediseñar fácilmente un flujo de trabajo para extraer datos adicionales desde el modelo, o cambiar las rutas de pantallas, sin cambiar una sóla línea de código.

Por otro lado, las peticiones de cambios que son problemáticas generalmente implican la interacción de la Vista con el Controlador y el Modelo, en vez de simplemente la apariencia del sistema. Dichos requerimientos no se pueden acomodar sin grandes cambios en la arquitectura. Afortunadamente, al menos algunos de los cambios que puedan romper la arquitectura del sistema se pueden predecir entendiendo algo más sobre los métodos de usabilidad. Exploremos algunos de ellos.

La Heurística de la Usabilidad trata con algunas peticiones de cambios predecibles

Si las peticiones de cambio de usabilidad fueran simplemente arbitrarias, los arquitectos no tendrían ninguna forma de anticiparse. Sin embargo, este no es el caso. Los arquitectos J2EE pueden estar mejor preparados para el impacto de las peticiones de usabilidad entendiendo cómo algunas de estas peticiones son el resultado directo de alguna heurística bien conocida, y cómo la implementación de dichas peticiones afectará a la arquitectura. Empezaremos describiendo algunas heurísticas de usabilidad, seguiremos las peticiones de características resultantes, y luego discutiremos como tratar el impacto arquitectural.

Heurística de Usabilidad > Petición de funcionalidad > Impacto arquitectural y patrón de diseño relevante.

Este marco enlaza usabilidad y arquitectura de software. Aunque no es una panacea para todos los problemas de usabilidad, podría ayudarle a protegerse de alguno de los dolores de las reconstrucciones de último minuto.

Los expertos en usabilidad evalúan los sistemas utilizando varias técnicas diferentes, dos de las cuales son las pruebas de usabilidad y el analisis heurístico. La mayoría de los ingenieros estárán familiarizados con las pruebas de usabilidad, pero no lo estarán con el analisis heurístico, que simplemente son las "reglas del pulgar" estándares de la industria que se han probado una y otra vez, en miles de proyectos, como útiles para mejorar la usabilidad. Aplicar esta heurística algunas veces nos trae alguna petición específica (y predecible) de características.

Un discusión en profundidad de la heurística más comúnmente utilizada va más allá del ámbito de este artículo; sin embargo, examinaremos dos casos (vea la siguiente tabla) para ilustrar el enlace entre las requerimientos de usabilidad y la arquitectura de software.

Características del Sistema Heurística Petición de Característica
Alta Latencia Mantener al usuario informado sobre lo que va a tardar una tarea. Botón de Cancel
Barra de progreso.
Alto coste de los errores Ayudar a los usuarios a tratar lo errores. Opciones de Undo/redo
Log de histórico

En nuestra experiencia (y también revisando las investigaciones relacionadas) estas dos heurísticas normalmente tienen que ver con cuatro solicitudes de características de usabilidad específicas; estas peticiones son disparadas por características específicas del sistema, como se explica más abajo.

 

Características de Usabilidad que mantienen informado al usuario:
Una baja respuesta del sistema puede marcar la experiencia del usuario, y los remedios requeridos para ayudar al usuario a anticiparse son los tiempos de respuesta o la cancelación de acciones. Tratar de forma efectiva el tiempo de respuesta del sistema puede motivar peticiones de funcionalidades como:
  • Un botón de Cancel: proporciona la forma de cancelar operaciones que podrían tardar más tiempo que el incialmente asumido por el usuario.
  • Barras de progreso: proporciona una barra de progreso cuando el sistema no responde que le dice al usuario cuando va a tener que esperar.

 

Características de Usabilidad que ayudan al usuario a recuperarse de errores:
Los usuarios comenten errores cuando utilizan cualquier sistema, por eso es crítico el soporte de recuperación de errores si el coste de los errores es alto (por ejemplo, si un click equivocado significa la pérdida de muchas horas de trabajo). Dos frecuentes solicitudes de funcionalidades relacionadas con la recuperación de errores que también impactan en la arquitectura son:
  • Undo / Redo (Deshacer/Repetir): permite al usuario deshacer y repetir la última acción.
  • Log de histórico: seguir las acciones del usuario en un log de forma que el usuario pueda ver lo que había hecho anteriormente.

Determinar si su sistema tiene (o tendrá) ocasionalmente una alta latencia y determinar el coste de los errores son puntos críticos para evitar el síndrome de "no poder hacer eso". La ingeniería y la arquitectura que pueden cumplir los conceptos de usabilidad requieren que tenga en cuenta consideraciones de la plataforma de desarollo, y consideraciones arquitecturales e importantes patrones de diseño, como se describe en la siguiente sección.

Consideraciones de la Plataforma de Desarrollo

En general, ambas familias de características de usabilidad tienen requerimientos arquitecturales relacionados. Por ejemplo, si implementa Undo/Redo, ya está más o menos en el camino de terminar implementando un log histórico. Y si implementa Cancel está en el camino de implementar una barra de progreso.

La elección de la plataforma de desarrollo puede ayudar (o estorbar) a su habilidad de implementar características de usabilidad. En general, cuando más características (deshacer/rehacer, botón de cancel, histórico o barra de progreso) necesite soportar, más seríámente debería considerar un interface de usuario basado en Java en vez de un interface de usuario basado en HTML.

Por ejemplo, sería díficil implementar la funcionalidad "Cancel" en una aplicación Web basada en el modelo Vanilla 2 de Struts: una vez que el usuario envía una petición (mediante http sin estado), el Controlador toma el control y el usuario no tiene más el control del UI durante la vida de ese comando en particular. Además, aunque la verdadera funcionalidad Undo/Redo es posible en una aplicación Web, normalmente no se implementa debido que el usuario cree que el botón back realiza un acción de deshacer (no lo hace, pero los usuarios no técnicos podrían no entender esto).

Por otro lado, un UI basado en ADF-JClient siempre está respondiendo a las entradas del usuario.

Además, la tecnología que utilice para su capa de persistencia también podría afectar a la viabilidad de implementar características como undo. Por ejemplo, los productos de Mapeo-Objeto-Relacional (ORMs), como Oracle TopLink, pueden facilitar la vuelta atrás de transaciones completadas, Oracle Toplink automáticamente actualiza los objetos de datos cuando se modifican los correspondientes registros en la base de datos (el API UnitOfWork.revertObject() de TopLink).

Consideraciones de Arquitectura y algunos Patrones de Diseño

Existen patrones de diseño asociados con la implementación de estas características (undo, history logging, cancel, progress bar).

Patrón para un Alto Tiempo de Respuesta (Barra de Progreso y Cancel)

La consideración principal cuando se construye la usabilidad en sistemas de alta latencia es asegurarse de que su Controlador siempre puede responder a las entradas del usuario. Por ejemplo, si un usuario detiene un comando después de haberlo enviado (como cuando la ejecución parece tardar demasiado) el Controlador puede ser capaz de volver el sistema a su estado anterior de forma educada.

Funcionalmente, esto significa empezar un nuevo thread por cada potencial comando de alta latencia que la Vista envíe al Controlador (algo que normalmente no querria a menos que determinara que la alta latencia sea realmente un problema).

Un beneficio de este patrón es que el thread del Controlador congelado puede calcular el tiempo que tardará la acción de alta latencia, y dar esa información al código del cliente, mostrando un barra de estado, por ejemplo. (Estimar el tiempo que puede tardar una acción es una funcionalidad complicada por si misma, y debería segregarse como un objeto separado, quizas informado por estadísticas de rendimiento del sistema en tiempo real).

Patrón para un Alto Coste de Errores (Deshacer y Registro de Históricos)

Si los errores tienen un alto coste para el usuario (por ejemplo: borrar horas de trabajo), entonces necesitamos proporcionarle mecanismos de recuperación y auditoría. Encapsular las comunicaciones entre la Vista y el Controlador en objetos Command hace posible almacenar las acciones del usuario en un orden temporal utilizando una pila, y deshacerlas luego en orden inverso (este es el familar patrón "Command"). El objeto Command es una implementación del interface Command, que dice que un comando sabe cómo execute() y undo() a sí mismo. Puede encontrar una excelente introducción a este patrón en la documentación del interface oracle.ide.ideaddin.Command.

Una pila de objetos Command puede servir como un Log Histórico de transaciones. Si sus usuarios requieren un registro histórico permanente (por ejemplo, para auditorias), entonces recomendamos copiar los objetos Command en una lista enlazada (o simplemente grabar los comandos, según se ejecutan, en una base de datos relacional).

Retro-Reparar un Aplicación

Las características de usabilidad como Undo son muy costosas de añadir a una aplicación existente que no fue diseñada con esa capacidad en mente. Se puede hacer, pero pagara un alto precio en tiempo de trabajo, igual que para un trabajo de remoledado que requiera actualizaciones de tuberías o cables eléctricos.

En breve, cambiar la forma básica en que se envían los comandos de usuario al modelo (permitiendo que sean deshechos o cancelados, por ejemplo) es un trabajo sucio que debería evitarse a toda costa. Y, como hemos apuntado anteriormente, es posible evitar, ya que el análisis heurístico revela las mismas prediciones de cambios, una y otra vez. Recomendamos que los expertos en interactividad y los directores de desarrollo interactúen en los primeros estadios del proyecto, incluso antes de escribir ningún código, y tomen decisiones claras sobre las funcionalidades a implementar. Para ilustrar este punto, usaremos una sencilla aplicación de hoja de cálculo para mostrarle el coste de añadir Undo en un estado posterior de desarrollo.

Como la mayoría de los ingenierios de software saben, implementar Undo es bastane sencillo utilizando el patrón Command. Consideremos la sencilla aplicación de hoja de cálculo implementada en Swing, mostrada en la figura 1:


Figura 1: Una sencilla hoja de cálculo.

La aplicación proporciona las funcionalidades mínimas de una hoja de cálculo, especificamente, permite al usuario poner valores en celdas, editar dichos valores y borrar el contenido de una celda.

Escenario 1: La Usabilidad viene al final

El equipo de desarrollo implementó esta aplicación sin proporcionar la capacidad undo. En la figura 2 puede ver el código de visualización de la aplicación básica.


Figura 2: Modelo de Objeto de una sencilla hoja de cálculo sin capacidad (undo), dibujada con el modelador de clases Java de Oracle JDeveloper 10g (10.1.3) Developer Preview.

La Vista llama a funciones específicas del Controlador, y el Controlador, a su vez, delega responsabilidades para llevar a cabo el comando adecuado llamando a funciones de las clases de ayuda dedicadas (CellAdderHelper, CellEditorHelper y CellDeleterHelper). Son estas clases de ayuda las que interactúan con el SpreadsheetModel y hacen los ambios relevantes en la clase SpreadsheetModel.

Las clases de ayuda tienen que ver con la misma clase padre (Helper), que contiene funciones comunes que hereda cada una de ellas. La respuesta del sistema ante una acción del usuario, como la edición de una celda, es simple y llanamante la delegación. La Figura 3 muestra el diagrama de secuencia:


Figura 3: Diagrama de Secuencia de la edición de celdas en una sencilla hoja de cálculo (sin capacidad undo).

Ahora que todo funciona, se llama al profesional de la usabilidad. El hace algunas recomendaciones sobre el aspecto y comportamiento de la hoja de cálculo, y también dice que sin la capacidad Undo no es utilizable.

En este punto, el arquitecto tiene dos alternativas, igualmene inapelables:

  • Rediseñar completamente la arquitectura para que la aplicación pueda proporcionar la funcionalidad Undo. Por ejemplo, deshacerse de las clases Helper que el sistema utiliza actualmente e implementar el Controlador utilizando el patrón Command.
  • Dejar el máximo de código actual tal y como está, pero añadiendo la funcionalidad Undo allí donde sea necesaria. Por ejemplo, implementar el patrón Command sólo para comandos undo discretos, como se muestra en la figura 4:


    Figura 4: Modelo de Objetos para una sencilla hoja de cálculo (con Undo añadido posteriormente), dibujado con el modelador de clases Java de Oracle JDeveloper 10g (10.1.3) Developer Preview.

Este patrón (también llamado "Half-Command") tiene menos riesgo que la primera aproximación, pero tiene el precio de incrementar la complejidad del sistema (embarulla todo el modelo de objetos ya que cada nuevo comando resulta en dos clases adicionales). Por otro lado, la primera aproximación ("derrumbar y reconstruir") puede ser más arriesgada (emplea mucho tiempo, costes, retrasos de lanzamiento, pérdida de oportunidades, etc.)

Esta arquitectura será costosa de mantener (porque será complicado que la aprendan los nuevos desarrolladores, y porque tiene un gran número de clases innecesarias). A pesar de todo, como puede implementarse rápidamente, y sin mucho riesgo, podría ser la única opción que tenga el arquitecto en esta situación.

La ejecución del sistema de comandos (y como deshacer los comandos) se visualiza en la siguiente diagrama de secuencias. Como puede ver, las clases Command y Helper acceden a la capa del Modelo, lo que requiere código que interactúe para que el Modelo esté presente en ambas familias de clases. El resultado es una sobrecarga significante de código y la posibilidad de cometer errores, así como los problemas de mantenimiento del código principal.


Figura 5: Diagrama de Secuencia de la editar/deshacer en una celda de una hoja de cálculo (con Undo añadido posteriormente), dibujado con el Modelador de Secuencias de Oracle JDeveloper 10.1.3 Developer Preview.

Escenario 2: La Usabilidad se considera al principio

Ahora veamos una implementación que fue construida con Undo como parte de la especificación original, basada en las recomendaciones de los expertos de usabilidad. Darse cuenta de que el coste de cualquier error en este sistema sería alto, los arquitectos del sistema anticipan la necesidad de una capacidad Undo. Diseñaron el sistema utilizando el clásico patrón Command, como muestra en la figura 6:


Figura 6: Modelo de Objetos para UndoableSpreadSheet, dibujado con el modelador de clases de Oracle JDeveloper 10g (10.1.3) Developer Preview.

Obviamente, este patrón de implementación tiene menos clases, el código es canónico (usted sabe lo que hace con sólo un vistazo).

El diagrama de secuencia del proceso editar/deshacer revela otra ventaja: los accesos al Modelo están restringidos a las clases Command (en vez de estar divididos entre las clases Command y Helper), lo que debería reducir los errores del desarrollador así como el tamaño del código resultante.


Figura 7: Diagrama de Secuencia de editar/deshacer en una celda de UndoableSpreadsheet, dibujada con el Modelador de Secuencia de Oracle JDeveloper 10.1.3 Developer

Incorportar Undo en el diseño inicial del programa de la hoja de cálculo ahorró a los desarrolladores una gran cantidad de trabajo al mismo tiempo que resultó una solución más elegante y mantenible

Conclusión

Dejando fuera las consideraciones de usabilidad arquitecturales, los desarrolladores de software asumen que si se descubren los problemas de usabilidad, se pueden corregir fácilmente. En la práctica, algunos problemas de usabilidad llegan demasiado profundo en la arquitectura como para ser resueltos a un coste razonable. Al igual que las otras cualidades que usted como arquitecto de software quiere para sus sistemas la usabilidad debe tenerse en cuenta desde el principio del proceso, y no dejarla para el final.

Las características que comunican información del estado del sistema en tiempo real o dan al usuario un control dinámico sobre la ejecución de comandos son difíciles de añadir a posteriori. El marco de trabajo delineado en este artículo podría probarse cómo útil al reducir el número de defectos de usabilidad que requiere una aplicación.

Próximos Pasos

Próximos pasos en Usabilidad:

  1. Descargue Download Oracle JDeveoper 10g (10.1.3)
  2. Visite el Usability Lab; donde los usuarios finales prueban productos.
  3. Obtenga Early Access Release of Oracle ADF Faces Components, un rico conjunto de componentes JSF. También puede visitar la lista de componentes ADF Faces.

Información adicional relacionada con la Usabilidad:

  • Oracle's Accessibility Program
    La accesibilidad tiene que ser parte del diseño básico para que las soluciones empresariales puedan acomodarse a los cambios que necesitan los usuarios.
  • On Using Oracle TopLink Transaction Framework: Unit Of Work
    En Oracle TopLink, las transaciones las encapsula el objeto UnitOfWork. Aprenda como este marco de trabajo le permite fácilmente revertir el estado de su modelo al inicio de la transación.
  • The Innovative Oracle Application Development Framework
    El buen diseño genera mejor calidad y las respuestas de los usuarios necesitan mas confianza. La arquitectura dirigida al modelo usa herramientas de modelaje para generar automáticamente código que implementa los requerimientos capturados en el momento del diseño. Las herramientas de desarrollo de Oracle soportan la aproximación MDA para el desarrollo de aplicaciones con herramientas de modelado UML y herramientas de diseño de Ingeniería de la Información tradicional.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP