Febrero de 2016

Volumen 31, número 2

Tecnología de vanguardia: arquitecturas derivadas de UXDD

Por Dino Esposito | Febrero de 2016

Dino EspositoHan pasado los años y me siento feliz si conozco y puedo recomendar una o dos formas eficaces de hacer la mayoría de cosas relacionadas con software. No deje que el énfasis que se pone en el marketing del software le engañe. El software mejora continuamente, pero no es el negocio principal de la mayoría de compañías. Esto significa que está más que aceptado que las compañías sigan usando el mismo software durante muchos años. Según el índice Tiobe.com, en el verano de 2014, Visual Basic 6 seguía entre los diez lenguajes de programación más utilizados. Y sin embargo un año y medio después, ha descendido unas cuantas posiciones. Esto parece confirmar la tendencia de que la mayoría silenciosa de compañías suele posponer las reescrituras completas de software lo máximo posible. Siendo realistas, la mayoría silenciosa de compañías tiene un trabajo pendiente de cinco años en cuanto a la tecnología del software que aún utiliza en sus negocios. Pero cuando llega el momento de que las compañías actualicen esos sistemas de trabajo pendiente, los arquitectos buscarán el software más sofisticado.

La arquitectura de software de hoy en día

En el mundo de la arquitectura de software, actualmente hay un par de palabras clave que están en boga. Una es "CQRS", que son las siglas de Command and Query Responsibility Segregation (Segregación de responsabilidades de comandos y consultas), y la otra es "polyglot persistence" (persistencia políglota). Ya hablé de CQRS recientemente en una serie de artículos de Tecnología de vanguardia. Como iniciación, le puede interesar leer "CQRS para la aplicación común" (msdn.com/magazine/mt147237) de la edición de junio de 2015 de MSDN Magazine. CQRS son una serie de instrucciones de arquitectura que sencillamente recomiendan mantener el código que modifica el estado del sistema separado del código que lo lee y notifica. En términos generales, la persistencia políglota se refiere a la práctica cada vez más habitual que consiste en usar varias tecnologías de persistencia en el contexto de la misma capa de acceso a los datos. La expresión, persistencia políglota, resume en dos palabras las complejas soluciones técnicas que han adoptado las redes sociales para hacer frente a la descomunal cantidad de datos que tienen que administrar todos los días. En esencia, la persistencia políglota consiste simplemente en usar la tecnología de persistencia que parezca ser ideal para el tipo y la cantidad de datos de que disponga.

Aunque tanto CQRS como la persistencia políglota tienen notables cualidades y ventajas potenciales, a veces es difícil ver su relevancia en el contexto de rescatar una aplicación empresarial compleja de las cenizas de un gran código base de formularios Web Forms, Windows Forms o Visual Basic 6. Y sin embargo, dicha relevancia existe y omitirla puede ser perjudicial a largo plazo para el proyecto y la compañía. Por otra parte, la arquitectura de software no es un acto de fe. CQRS puede parecer maravilloso, pero debe encontrar la perspectiva adecuada para que encaje en su escenario particular.

Aunque si observa la arquitectura de software desde el prisma de UXDD, podrá descubrir fácilmente una forma para que CQRS y la persistencia políglota encajen.

Diseño basado en tareas

Ya se están usando formas de flujos de trabajo de UXDD en compañías de todos los tamaños y he visto en primera persona versiones suyas en equipos pequeños de diez personas o menos, así como en empresas valoradas en miles de millones de dólares. Cuando esto sucede, existe un equipo de experiencia de usuario que desarrolla pantallas en colaboración con clientes finales, ya sean internos o externos. El equipo de experiencia de usuario crea unos artefactos coloridos en forma de archivos HTML o PDF y los envía al equipo de desarrollo. El problema es que la mayoría de veces el equipo de desarrollo ignora dichos artefactos hasta que la pila del back-end está diseñada y creada. Con demasiada frecuencia, el back-end se diseña sin tener en cuenta o valorando muy poco las tareas reales que se realizan a nivel de presentación. Como arquitectos, nos ocupamos de forma diligente de las tareas de lógica de negocios y pensamos en formas de optimizar y generalizar la implementación. No solemos preocuparnos lo suficiente por los cuellos de botella y la navegación y presentación de datos poco óptimas. Cuando llegamos a detectar que la experiencia que tienen los usuarios cuando trabajan con la aplicación es inferior a la ideal, normalmente es demasiado tarde para implementar cambios de una manera rentable, como se muestra en la Figura 1.

Diseño de un sistema de software de abajo a arriba frente a un diseño de arriba a abajo
Figura 1. Diseño de un sistema de software de abajo a arriba frente a un diseño de arriba a abajo

Seamos realistas. Mucho más allá de su indiscutible efectividad en el almacenamiento de datos, el modelo relacional es engañoso para la arquitectura de software. O, como poco, comenzó a ser realmente engañoso tras sus dos primeras décadas de vida. Ya a mediados de los 90, en el espacio Java, la discordancia entre los modelos de datos conceptual y relacional fue una cuestión que llevó a la experimentación con herramientas de asignación objeto-relacional. Generaciones de arquitectos de software (que ahora son jefes) crecieron con la idea de que lo realmente importante son unos cimientos sólidos de base de datos. No hay ninguna duda de que una base de datos sólida conforma los cimientos de cualquier tipo de software robusto. El problema es la complejidad y la cantidad de lógica de aplicación y dominio. No suponía un gran problema hasta que fue viable agregar partes de esa lógica en procedimientos almacenados. Más allá de ese umbral, los arquitectos de software evolucionaron hacia la clásica arquitectura de tres capas (presentación, negocio y datos) y, posteriormente, la arquitectura de capas con diseño guiado por el dominio (DDD): presentación, aplicación, dominio e infraestructura. Sin importar el número de capas, el diseño era esencialmente de abajo a arriba.

El diseño de abajo a arriba funciona estupendamente si se cumple al menos una de las dos condiciones siguientes:

  1. La interfaz de usuario ideal es muy cercana al modelo relacional.
  2. Los usuarios no son expertos y se muestran pasivos.

El diseño de software da la impresión de ser una ciencia exacta en esos tutoriales especialmente creados para promocionar una tecnología o un marco nuevos. Cuando se abandona el laboratorio aséptico y se entra en el mundo real, el diseño de software se convierte en el reino del miedo, las dudas y la incertidumbre; una tierra de nadie en la que solo existe una regla: depende.

UXDD sencillamente sugiere que no se comience ningún desarrollo serio hasta que se disponga de evidencias claras (véase estructuras de alambre) de la arquitectura ideal de la información y la interacción óptima entre los usuarios y el sistema. Un diseño de arriba a abajo que comience en las estructuras de alambre de la capa de presentación garantiza que se aproximará bastante a lo que los usuarios solicitaron. El riesgo de escuchar las viles palabras "esto no es lo que pedimos" se reduce enormemente. Tenga presente que si una estructura de alambre se etiqueta como errónea, nunca es una cuestión de preferencia, sino más bien empresarial. Si se ignora la información de las estructuras de alambre, probablemente lo que se conseguirá es crear errores intencionales en el sistema resultante.

En la Figura 2 se resume la discordancia de impedancia de la arquitectura de hoy en día. Disponemos de las estructuras de alambre que describen la capa de presentación ideal y tenemos el código que implementa la lógica de negocios tal y como se entendió. Lamentablemente, de forma habitual, ambas cosas no coinciden. Si los proyectos de software en rara ocasión están a la altura de las expectativas (especialmente desde un punto de vista financiero), ¿está seguro de que no se debe a una discordancia de la impedancia de la arquitectura?

Discordancia de impedancia de arquitectura
Figura 2. Discordancia de impedancia de arquitectura

Abordar la discordancia de impedancia de arquitectura

Un modelo de dominio completo que abarque todo el espectro de la lógica de dominio no tiene sentido alguno, por decirlo de forma amable. La idea de los modelos de dominio y el enfoque DDD completo surgió para solucionar la complejidad en el centro del software, pero esto fue hace más de una década. Han cambiado muchas cosas desde entonces y, aunque algunos elementos principales de DDD (en concreto las herramientas y los conceptos de diseño estratégico) tienen actualmente más valor que nunca, un modelo de dominio orientado a objetos que abarque completamente todos los aspectos de lectura y escritura de distintos contextos enlazados es muy complicado de crear y nada realista.

Al mismo tiempo, la idea de un modelo de dominio completo está en sintonía con una visión de abajo a arriba del software, donde comprende lo que los usuarios quieren, elabora un modelo, lo codifica y le agrega una interfaz de usuario. Aunque pueda parecer completamente irónico, un software exitoso es una experiencia de usuario eficaz y bonita por encima de una caja negra mágica (MBB).

Si comienza los trabajos de ingeniería por las estructuras de alambre, sabrá exactamente lo que la MBB deberá admitir realmente. Y también debe saber que mientras la MBB haga su trabajo, el sistema se acercará enormemente a lo que los usuarios pidieron formalmente. Prácticamente no hay margen para suposiciones de los desarrolladores y la mayoría de iteraciones con los clientes se agrupan en la fase inicial del proyecto. Los cambios son económicos y cuando se hayan superado las pruebas de experiencia de usuario, la mayor parte de lo que queda tiene la importancia de un detalle de implementación.

UXDD pone énfasis en las tareas y los eventos. En un diseño de arriba a abajo, el punto de inicio es una acción de usuario, como un clic o una selección. Cada acción de usuario está enlazada a un punto de entrada en la capa de aplicación. Como ejemplo, en ASP.NET MVC eso implica que todos los métodos de controladores (capa de presentación) se enlazan a un punto de entrada en una clase de la capa de aplicación, como se muestra en la Figura 3.

Figura 3. Controlador CQRS

public class SomeController
{  
  public ActionResult SomeQueryTask(InputModel input)
  {
    var service = new QueryStack.SomeService();
    var model = service.GetActionViewModel(input);
    return View(model);
  }
  public ActionResult SomeCommandTask(InputModel input)
  {
    var service = new CommandStack.SomeService();
    service.GetActionViewModel(input);
    RedirectToAction(...);
  }
}

Las dos clases SomeService son la sección de la capa de aplicación que está visible desde la parte de la capa de presentación que se representa mediante la clase SomeController. Las dos clases SomeService pueden formar parte del mismo ensamblado y proyecto físicos que el ensamblado o tratarse de ensamblados y proyectos diferentes. Tenga en cuenta que, en términos de arquitectura, la capa de aplicación va de la mano de la capa de presentación. Esto significa que si se requieren varias capas de presentación (es decir, web, web móvil y aplicaciones móviles), se pueden tener varias capas de aplicación con una reusabilidad posterior limitada de la lógica.

Tendrá un método de punto de entrada en la capa de aplicación de cada tarea que el usuario podría activar desde la interfaz de usuario aprobada. Si reproduce fielmente las estructuras de alambre que recibió, sabrá exactamente lo que entra y sale de cada pantalla. No es posible equivocarse. Tal vez pueda ser ineficiente o lento, pero nunca erróneo.

La capa de aplicación intercambia objetos de transferencia de datos con la presentación y organiza los flujos de trabajos necesarios para la tarea. Al hacerlo, la capa de aplicación normalmente necesita leer y escribir datos de algún almacén persistente, acceder a servicios web externos y realizar cálculos. Se trata simplemente de lógica de dominio, la cual no varía según los casos de uso. Si una presentación móvil o web lo solicita, la tarea de dominio de negocios ejecuta lo mismo y es completamente reutilizable. En resumen, la idea de la lógica de negocios es la separación en dos segmentos más específicos: la lógica de aplicación como la lógica necesaria para implementar casos de uso de presentación concretos y la lógica de dominio que no varía según las presentaciones y casos de uso.

La lógica de dominio puede diseñarse según diversos patrones, entre los que se incluyen el script de transacción y el módulo de tabla. En estos casos, las reglas de negocio son un cuerpo externo insertado en las clases que utiliza. Normalmente, las reglas de negocio conforman una calculadora que puede invocar para obtener una respuesta sobre la viabilidad de una acción. El patrón del modelo de domino, que a menudo se interpreta de forma equivocada como la verdadera esencia de DDD, es simplemente un patrón que sugiere que se creen clases que se comporten como las entidades reales e incorporen posteriormente las reglas de negocio, y oculten su aplicación en los métodos que ofrecen. No hay una forma correcta o errónea de diseñar la lógica de domino, se trata simplemente de una cuestión de actitud y eficacia.

En un diseño basado en tareas, verá de inmediato si la acción modifica el estado del sistema o informa de él. Con un diseño CQRS, se separan de forma natural los comandos de las consultas y, si se disponen en pilas separadas, se obtienen las evidentes ventajas de su escritura y optimización de forma independiente sin riesgo de regresión, incluso con la posibilidad de una escalabilidad simplificada. CQRS encaja perfectamente en un contexto UXDD.

Persistencia por fin.

Si se procede de arriba a abajo, la persistencia es inevitablemente la última de las preocupaciones. No me malinterprete: todas las aplicaciones deben poder conservar los datos y permitir que se puedan consultar de forma eficaz. Que sea la última de las preocupaciones no significa que se deba desatender; simplemente implica que en un sistema interactivo orientado al usuario, el diseño de la persistencia adquiere una mayor importancia cuando otros aspectos (en concreto la experiencia de usuario y la lógica de domino) ya se han resuelto. Y sencillamente por este motivo, no tiene restricciones respecto a la tecnología de base de datos que debe utilizar. Además, si tiene un diseño CQRS, puede disponer de varias capas de persistencia, una para los comandos y otra para las consultas, hacer que se administren de forma independiente e incluso, si resultara útil, que estén basadas en diferentes paradigmas y tecnologías de almacenamiento. Por ejemplo, si sabe que en algún momento deberán realizarse informes de análisis en la interfaz de usuario, quizá quiera adoptar un marco de abastecimiento de eventos y realizar un seguimiento de cada actualización y acción relevante como un evento. Esto le dará un registro completo de lo que ha sucedido en el sistema y se podrá usar en algún momento como el punto de inicio de análisis de inteligencia empresarial propio. Al mismo tiempo, si necesita servir rápidamente datos preparados al usuario, simplemente debe mantener el almacén de eventos sincronizado con una proyección de los datos que cubra sus necesidades de presentación. Una proyección de datos en este contexto es el estado generado después de una lista de acciones. Es lo mismo que querer conocer el saldo de la cuenta bancaria (la proyección) que resulta de una lista de transacciones (eventos). La pila de eventos normalmente está compuesta sencillamente de vistas de SQL Server simples, mientras que la pila de comandos podría basarse en tablas relacionales, un almacén de eventos o NoSQL, o una combinación de los anteriores.

Esto es lo que a veces se conoce como persistencia políglota.

Resumen

Nos guste o no, los usuarios valoran un sistema principalmente a partir de la sensación que perciben de la experiencia directa. Hoy en día, el factor clave para ahorrar dinero en proyectos de software es garantizar que se cree inmediatamente lo que usuarios quieren exactamente. No se trata de hacerlo bien, sino de hacerlo bien y de inmediato. Con UXDD conoce lo antes posible la salida para la que creará el sistema, lo que reduce las correcciones que deberán aplicarse cuando implemente el sistema y a los usuarios no les guste del todo. Además, con un diseño de arriba a abajo, la experiencia de diseño se lleva de forma natural a los patrones modernos, como CQRS y la persistencia políglota que, más allá de estar de moda, son prácticas probadas para crear software eficaz.


Dino Espositoes el coautor de "Microsoft .NET: Architecting Applications for the Enterprise" (Microsoft Press, 2014) y "Modern Web Applications" (Microsoft Press, 2016). Esposito, evangelizador técnico para las plataformas Android y Microsoft .NET Framework en JetBrains y orador frecuente en eventos del sector en todo el mundo, comparte su visión de software en software2cents.wordpress.com y en Twitter en @despos.

Gracias al siguiente experto técnico por su ayuda en la revisión de este artículo: Jon Arne Saeteras