Los casos de uso (y V)

Alternativas al texto

Aunque el empleo del texto es la forma más legible y más sencilla de detallar los casos de uso, habrá ocasiones donde puede ser más conveniente expresarlos gráficamente. UML dispone de dos tipos de diagramas que son aptos para tal fin: actividad y estado1.

1 Los diagramas de secuencias también podrían utilizarse para detallas casos de uso. Sin embargo, decidí excluirlos para tal fin porque considero que la presentación gráfica de las extensiones contraviene uno de los principios que deben guiar el desarrollo de software: la sencillez.

Los diagramas de actividad

Un diagrama de actividad permite modelar un proceso como una actividad con el fin de comunicar un aspecto específico del comportamiento dinámico de un sistema a través de una colección de nodos conectados.

Aunque la semántica de UML para este tipo de diagramas ─como para todos los demás─ es extraordinariamente rica, se expondrá únicamente un subconjunto suficiente de la misma para detallar los casos de uso.

Pueden encontrarse tres tipos básicos de nodos en un diagrama de actividad:

  • Un y sólo un nodo inicial que indica donde empieza la actividad.
  • Uno o más nodos finales que indican donde termina la actividad.
  • Varios nodos de acción que representan un comportamiento que es atómico dentro de la actividad.

La representación gráfica de los tres tipos de nodos se muestra en la siguiente figura:

Nodos de un diagrama de actividad

Las flechas que unen los nodos se denominan flujos de control y representan cómo circula el control a lo largo de la actividad. En la figura puede verse cómo el nodo inicial pasa el control al nodo de acción y éste al nodo final.

Empleando únicamente los nodos y los flujos de control es posible escribir la secuencia de acciones del escenario principal de cualquier caso de uso. No obstante, debería reflexionarse si hacer algo como esto realmente aporta algún valor con respecto a la forma textual.

Un diagrama de actividad puede resultar más útil si es capaz de mostrar las extensiones. Para hacerlo es necesario presentar un nuevo nodo denominado nodo de decisión.

Un nodo de decisión adopta la forma de un rombo y tiene como entrada un flujo de control y como salida dos o más de ellos. Actúa como un cruce de caminos donde el flujo debe tomar aquel camino que cumpla con la condición enunciada en el nodo.

Un nodo de decisión

La condición se evalúa una vez que el control pasa al nodo de decisión. Aquel camino que cumpla con ella será el seleccionado para pasar el control al nodo de acción correspondiente. Los flujos de salida del nodo de decisión se etiquetan con guardas (cualquier texto escrito entre corchetes) para indicar las restricciones y condiciones que determinarán el flujo de la actividad.

La contrapartida al nodo de decisión es el nodo de fusión ─también representado por un rombo─, el cual tiene como entrada dos o más flujos de control y únicamente uno como salida. Su semántica es extremadamente sencilla: los flujos de entrada se combinan dando lugar al flujo de salida.

Habrá ocasiones en las que sea necesario mostrar actividades concurrentes como aquellas vinculadas a extensiones que sucedan de forma asíncrona. La extensión «E01. El usuario no responde» del caso de uso «Efectuar reintegro» es un ejemplo de esto. Los diagramas de actividad disponen de un par de nodos para tratar la concurrencia: el nodo fork y el nodo join.

El nodo fork divide un flujo de control en dos o más flujos concurrentes, los cuales puede tener una guarda. Por el contrario, un nodo join sincroniza todos los flujos entrantes en un único flujo de salida. Ambos se representan mediante una línea gruesa horizontal o vertical.


El nodo fork (arriba) y el nodo join (abajo)

En este sencillo ejemplo, el producto se diseña primero, se pone en el mercado y se fabrica concurrentemente, y se vende únicamente después de que ambos procesos hayan terminado.

Conociendo los nodos principales junto con los de decisión, fusión y concurrencia, se puede detallar prácticamente cualquier caso de uso. La figura 4.10 muestra el caso de uso «Leer tarjeta» con todas sus extensiones empleando un diagrama de actividad. El nodo que aparece a la izquierda, representado por una especie de reloj de arena de trazo muy simple, no es más que un nodo de acción empleado para aceptar un evento temporal, es decir, responde al transcurso del tiempo generando un evento.

Dejo a su elección si verdaderamente compensa utilizar esta notación gráfica frente a la versión en texto.

Detalle del caso de uso «Leer tarjeta»

Los diagramas de estados

Los diagramas de estados ─al igual que los diagramas de actividad─ modelan aspecto del comportamiento dinámico de un sistema, pero tienen semántica y propósitos muy diferentes, algo que no era así en los principios de UML2. Los diagramas de estados tienden a utilizarse para modelar el ciclo de vida de un objeto reactivo ─que responde a eventos─ mediante una máquina de estados finita, es decir, con un número concreto de estados. La máquina transita entre los estados en respuesta a eventos bien definidos.

2 A partir de UML 2 la semántica de los diagramas de actividad cambió al basarse en las redes de Petri.

En el marco de los casos de uso, los diagramas de estados podrían emplearse en aquellos de nivel subfunción que describan la interacción con un objeto reactivo como puede ser un lector de tarjetas de banda magnética.

Los tres elementos clave de las máquinas de estados son los estados, los eventos y las transiciones:

  • Un estado es una situación de la vida del objeto durante la cual se cumple una condición, realiza alguna actividad o responde a algún evento.
  • Un evento es un suceso localizado en el tiempo.
  • Una transición es el paso de un estado a otro en respuesta a un evento.

El siguiente diagrama muestra la máquina de estados de una puerta con cerradura:

Máquina de estados simple

La puerta tiene tres estados que se representan mediante rectángulos con esquinas redondeadas: Abierta, Cerrada y Candada. Como en toda máquina de estados, también está presente el estado inicial ─representado mediante un círculo negro─ que indica el primer estado de la secuencia. Realmente, el estado inicial es un pseudoestado pues éste pasa inmediatamente al estado real Abierta; es un simple indicador para localizar el inicio de la máquina.

A no ser que la máquina describa un ciclo sin fin ─como es el caso─ debe tener uno o más pseudoestados finales que indiquen el fin de la secuencia. El símbolo del pseudoestado final es exactamente el mismo que se utiliza para los nodos finales de los diagramas de actividad: un círculo negro con una circunferencia concéntrica.

Las transiciones se denotan con flechas entre los estados y los eventos es el texto que aparece junto o encima de ellas.

La semántica de la máquina de estados es extraordinariamente sencilla. Una puerta «Abierta» transita al estado «Cerrada» en respuesta al evento «cerrar» y desde éste transita al primer estado en respuesta a «abrir». En el estado «Cerrada» transitará al estado «Candada» si se produce el evento «candar» (cerrar con llave) y volverá desde «Candada» a «Cerrada» cuando se dé el evento «descandar».

Aunque la sintaxis de las transiciones puede limitarse a los eventos, lo cierto es que es mucho más potente. La siguiente figura muestra la sintaxis completa:

Sintaxis de una transición

Toda transición tiene tres elementos opcionales:

  • Eventos: sucesos que activan la transición como «evento 1» y «evento2».
  • Guarda: una y solo una expresión lógica que debe ser verdadera para que se pueda realizar la transición. Por tanto, la llegada de un evento no implica la transición de estado a no ser que se cumpla la guarda. Por otra parte, como los eventos son también opcionales, se pueden producir transiciones entre estados simplemente por el cumplimiento de una guarda. Dado que las guardas son expresiones lógicas pueden usarse los operadores relacionales =, <>, <, <=, >, >= y los operadores lógicos and, or, not y xor.
  • Acciones: el efecto asociado a la transición cuando ésta ocurre.

La transición de la figura puede leerse como «ante evento1 o evento2, si guarda es verdadera entonces ejecutar acción1 y acción2 y pasar al estado B».

Para terminar, existen dos elementos que pueden ser útiles para aumentar la legibilidad de un diagrama de estados porque evitan dibujar un exceso de transiciones que siempre complicarán la lectura: el pseudoestado de unión y el pseudoestado de opción.

Un pseudoestado de unión representa un punto donde las transiciones se unen o ramifican. Se representan con un círculo negro a donde llegan una o más transiciones de entrada y de donde parten una o más transiciones de salida. En el siguiente ejemplo tiene una sencilla unión donde confluyen las transiciones de los estados A y B en respuesta a los eventos evento2 y evento3.

El pseudoestado de unión

En este ejemplo sólo parte una transición de salida del pseudoestado de unión. En el caso de que haya más de una, la presencia de una guarda mutuamente exclusiva en cada una de las transiciones es obligatoria para poder discernir qué camino tomar.

Para mostrar una sencilla ramificación sin una unión, debería utilizarse el pseudoestado de opción el cual permite seleccionar una o más transiciones en función del valor de sus guardas.

El pseudoestado de opción

Las guardas deben ser mutuamente exclusivas y existe la posibilidad ─en este caso y en todos los demás─ de usar la guarda [else], que será la elegida en el caso de que todas las demás se evalúen a falso.

Habiendo visto una parte de la semántica de los diagramas de estados, aunque se cree suficiente para detallar casos de uso, se procederá a modelar el caso de uso «Leer tarjeta con banda magnética». Recordará que éste es una variante tecnológica del caso de uso abstracto «Leer tarjeta» y, como tal, debe incluir detalles relativos a cómo opera un lector de este tipo. Podemos suponer que hemos leído el manual del lector y que, básicamente, acepta peticiones mediante una serie de órdenes y notifica eventos mediante códigos y los datos de la tarjeta siguiendo un formato concreto a través de algún puerto de comunicaciones como un puerto USB.

Como siempre, debería preguntarse si crear una máquina de estados para detallar un caso de uso merece la pena. Si hacerlo ayuda a entender un caso que modela el comportamiento de un objetivo reactivo complejo, seguramente sí lo merezca. De lo contrario, es preferible usar el texto como en la mayoría de los casos de uso.

Detalle del caso de uso «Leer tarjeta con banda magnética»

Bibliografía recomendada

Ivar Jacobson, Magnus Christerson, Patrik Jonsson y Gunman Övergaard. Object Oriented Software Engineering: A Use Case Driven Approach. Addison Wesley, 1992.

Alistair Cockburn. Writing Effective Use Cases. Addison Wesley, 2001.

Steve Adolph y Paul Bramble. Patterns for Effective Use Cases. Addison Wesley, 2002.

Kurt Bittner y Ian Spence. Use Case Modeling. Addison Wesley, 2002.

Ivar Jacobson, Ian Spence y Kurt Bittner. Use Case 2.0. The Guide to Succesing with Use Cases. Ivar Jacobson International, 2011.

Entradas relacionadas