Archivo para la categoría Casos de Uso

Flujos de eventos alternativos

En un caso de uso, los flujos de eventos se refieren a los pasos que alternativamente van realizando los actores y el sistema en el contexto del requisito funcional capturado en el caso. Dichos pasos por claridad, se separan en el flujo principal y los flujos alternativos; de forma tal que en el flujo principal representamos el día feliz, donde todo ocurre sin problemas y en los flujos alternativos lidiamos con las situaciones de error y el comportamiento esperado del sistema en respuesta a dichos errores.

Es necesario entonces contar con una aproximación sistemática sobre como disponer los flujos de eventos principal y alternativos, de forma que capturen en forma clara y precisa cada condición que el flujo del día feliz ha asumido como libre de error pero que es a su vez, el punto de inicio de un flujo alternativo.

La idea aquí es la de indicar el paso del flujo principal y la condición precisa que de violarse hace que se ejecute el flujo alternativo. De ser posible la condición ha de estar expresada en términos del modelo de dominio de forma tal que facilitar su traducción al sistema software.

Los pasos del flujo alternativo han de tener una enumeración propia de forma tal que no choquen los unos con los otros ni con los pasos del flujo principal. La forma exacta en que vamos a enumerar es cosa de cada quien, por lo que es un punto a documentar como parte del Plan de Gestión de Requisitos, documento este que suele ser parte del Plan de Desarrollo de Software.

Un ejemplo de todo lo anterior puede ser visto como parte del ejemplo de caso de uso en este blog. En el ejemplo referido se hace mención al caso de uso “llamada de voz” y se ha señalado la condición de error “número incorrecto”. Veamos una versión ligeramente modificada del caso de uso de ejemplo para discutir como se puede implementar los flujos alternativos:

Código: CS-0100.
Nombre: Llamada de voz.
Actores: Usuario.
Descripción: El usuario del teléfono levanta el auricular y marca el número de destino. Al completar la secuencia de dígitos la conexión se realiza. Por medio de tonos particulares el sistema indica el estado de error y de progreso en la conexión.
Precondición: El teléfono está colgado.
Postcondición: Ninguna.
Diagrama:

Sencillo Modelo de Casos de Uso

Flujo Principal:
Paso 1 – Usuario:
Levanta el auricular.
Paso 2 – Sistema: Da el tono de marcado.
Paso 3 – Usuario: Indica el número de teléfono.
Paso 4 – Sistema: Realiza la conexión. Da tono de aviso en tanto se levanta el teléfono del lado contrario de la conexión. Permite la conversación al hacerse efectiva la conexión.
Paso 5 – Usuario: Conversa y al finalizar esta, tranca el teléfono.
Paso 6 – Sistema: Termina la conexión.

Flujo alternativo: Número incorrecto
Paso 3 – Sistema:
Presenta tono de error. El caso de uso termina.

Flujo alternativo: Desconexión inesperada
Paso 5.1 – Sistema:
Detecta un fin inesperado de la conexión. Indica todo de error.
Paso 5.2Usuario: Tranca el teléfono.
Paso 5.3 – Sistema: Registra error. El caso de uso termina.

Tabla 1 – Ejemplo de caso de uso con flujos alternativos

Como ya dije, este ejemplo es una modificación del ya visto en el post ejemplo de caso de uso, donde ahora se han considerado dos flujos alternativos, uno para la condición de número incorrecto y otro para la desconexión inesperada.

La condición ha sido indicada en términos abstractos, comprensibles desde una perspectiva técnica y luego se ha indicado el paso en que dicha condición se puede violentar. En el flujo alternativo del número incorrecto el paso es el tres y en caso de problemas las acciones a tomar son solo una: el sistema presenta tono de error.

Otro tanto puede ser dicho en el segundo flujo alternativo. La desconexión inesperada sin embargo a dado lugar a tres pasos. El sistema detecta un fin inesperado e indica tono de error. El usuario entonces tranca el teléfono. Finalmente el sistema registra el error. Estos tres pasos han sido enumerados con la secuencia 5.1, 5.2 y 5.3, de forma de hacer referencia a que son un flujo alternativo del paso cinco del flujo principal al tiempo de mantener una secuencia numerica propia.

, , , , , , , , ,

7 comentarios

Todo requisito debe ser preciso y legible

La especificación de un sistema es un trabajo retador. En él participan no solo los desarrolladores de aplicaciones, sino también los clientes. Esto significa que la especificación de requisitos, ya sea como casos de uso o como declaraciones tradicionales tipo “el sistema debe…” ha de ser entendida a la vez, por lo clientes y por los desarrolladores. Dicho en otras palabras: la especificación contiene detalles técnicos que los clientes luchan por entender, a la vez que incluye información sobre el negocio que es nueva y potencialmente confusa para los desarrolladores.

Esta situación nos obliga a luchar por dos atributos básicos en todo nuestro sistema de requisitos: la claridad y la precisión.

Precisión de un requisito. Un requisito es preciso cuando indica sin ambigüedad lo que se desea especificar. Debe ir directo al punto y evitar todo adorno en el lenguaje. Debe documentar solo un aspecto del sistema y lo debe de hacer en forma exacta.

Y también

Claridad o legibilidad de un requisito. Un requisito es legible cuando el lenguaje en el que esta escrito es fácil de entender, tanto por los clientes como los analistas. La legibilidad se extiende no solo a la especificación escrita, sino también a los formalismos gráficos como los diagramas de casos de uso.

Es curioso observar que en los cursos universitarios sobre el tema, los profesores tengan la presión de explicar métodos y técnicas avanzadas, como las relaciones de extensión e inclusión de casos de uso, forzando al estudiante a adoptar estar técnicas en forma demasiado temprana. Esto causa una deformación profesional en el estudiante, quien sale del curso con la creencia que es mejor una especificación sofisticada que haga uso de todo lo visto en el curso, en lugar de una aproximación más informal y relajada que puede en verdad ser entendida por el cliente.

El lugar correcto para la extensión y la inclusión, así como para todas las técnicas de modelado de requisitos más sofisticadas, es en aquellos dominios de aplicación donde los requisitos reales sean muy complejos. Es decir por lo tanto, que en la práctica el analista ha de hacer esfuerzos por mantenerse sencillo, normalmente no vale la pena la complejidad del modelo de requisitos.

También es de hacer notar, que en mi experiencia la mayoría de los clientes intentan hacer otro tanto. Ellos suelen expresar lo que necesitan en la forma más directa que tienen disponible, sin embargo dado que los clientes son a su vez profesionales en un área especifica, la forma correcta en la ellos se expresan suponen tensión a los desarrolladores, quienes deben luchar por desarrollar un vocabulario común con el cliente para poder comprender sin errores lo que este pide.

En conclusión: lo sencillo se entiende más y la especificación de un sistema ha de entenderse bien. Cuan sofisticado hagamos nuestro modelo de casos de uso o nuestro documento de especificación, no es ni de lejos lo que en verdad importa. Es mucho mejor un caso de uso sencillo pero que captura valor de negocio, que uno sofisticado que haga un uso abundante de las técnicas más esotericas de modelado.

, , , , , , , , , , ,

2 comentarios

Casos de Uso: Flujos de Eventos

Un caso de uso es un escenario de interacción entre el sistema y un ente externo; es decir: es la descripción de una funcionalidad del sistema, visto desde el punto de vista de un ente externo que demanda dicha funcionalidad.

Al ente externo le llamamos actor por cuanto un caso de uso puede ser visto también como un guión, que a la manera de los guiones de una obra de teatro, dice paso a paso lo que el actor ha de hacer.

Es mucho lo que podemos decir de un caso de uso: nombre, descripción, pre condiciones, etc. Sin embargo, el aspecto más interesante de un caso de uso luego de la descripción del mismo es sin duda el flujo de eventos.

Al flujo de eventos lo podemos relacionar con un dialogo. Línea a línea, el flujo de eventos indica quien habla y qué dice. La secuencia se suele iniciar con algo dicho por el actor, y se continua intercalando sucesivamente lo hecho por el sistema con lo dicho por el actor. A cada una de estas líneas o indicaciones, le podemos llamar paso.

Un buen flujo de eventos recoge con detalle la identidad de quien realiza el paso, expresando sin ambigüedad la acción realizada. Es decir, que un buen paso ha de ser siempre una oración con sentido completo, escrita en voz activa, iniciando con el nombre del actor o bien del sistema que realiza la acción e indicando exhaustivamente los elementos de información que se intercambian.

Dichas oraciones con sentido completo, sin ambigüedad y demás características ya mencionadas, no son difíciles de redactar. Son de hecho la forma más directa de decir lo que hay que decir. Y es que a la hora de redactar un flujo de eventos debemos evitar recurrir a formas de redacción en prosa típicas de nuestros textos comunes. No vale sustituir el nombre del actor por un pronombre o demostrativo que le haga referencia. A la larga, dicha omisión del nombre del actor va a ser una fuente de ambigüedad y nos puede traer problemas.

Si bien para quienes acostumbran a redactar con estilo, estas normas para los flujos de eventos pueden sonar extrañas, son normas muy comunes para cuando queremos redactar documentos de requisitos. Básicamente estamos aplicando aquí los mismos consejos que se dan para redactar bien un requisito tradicional, del estilo “el sistema debe…” por lo que en Internet abundan los detalles sobre este particular.

Finalmente, la prosa tiene su refugio en la descripción breve de un caso de uso; y dado que es esta descripción breve la parte más importante del caso de uso, podemos decir que a la final todos vamos a poder estar contentos. Quienes quieren una redacción con estilo van a encontrar lo que buscan en la descripción breve y quienes necesitan los detalles operativos del caso de uso lo van a encontrar en los pasos del flujo de eventos.

, , , , , , , , ,

5 comentarios

Casos de uso: preferir la amplitud a lo detallado

Un caso de uso es la descripción de un escenario de interacción -un uso- entre un actor y el sistema. Dicho escenario captura el requisito funcional que el sistema ha de cumplir y documenta lo que se ha discutido entre el equipo de desarrollo y el cliente en una forma simple, de fácil lectura y razonablemente exacta.

Todo bien hasta aquí.

En sistemas reales, es inevitable encontrarse con las siguientes dos situaciones:

  1. Algunos requisitos quedan sin descubrir y se convierten en riesgos.
  2. Algunos requisitos muy especificados jamás encuentran un lugar en el desarrollo.

O en otras palabras, si no tenemos cuidado, tendremos casos de uso que especifican en detalle algo que esta por fuera del alcance del proyecto en tanto uno o más puntos importantes habrán quedado en el anonimato y nos atacaran en castigo a nuestro olvido.

Ambas situaciones son peligrosas y aún si las controlamos representaran costos imprevistos que pueden hacer peligrar el proyecto.

¿Como podemos evitar estos problemas? Sin querer decir que es una receta mágica, lo que la experiencia nos enseña es que un modelo de casos de uso (y quizás todo sistema de requisitos) ha de preferir documentar primero a lo ancho, cubriendo áreas cuanto más amplias mejor, del sistema a desarrollar, antes de descender a los detalles de las partes de mayor interés.

Si suponemos un desarrollo cualquiera, este consejo de ir primero a lo amplio y luego a lo detallado, significa que tendremos muchos casos de uso apenas en estado de borrador, que delinean a grandes rasgos lo que se pretende del sistema en términos de su funcionalidad y el alcance del proyecto. Luego, según vayamos atendiendo los requisitos en nuestras iteraciones o fases, podremos dedicar algo de tiempo en obtener los detalles de cada caso de uso de manera de desarrollar el sistema correcto.

Esta aproximación es interesante también desde el punto de vista de la gestión del proyecto. Es posible crear un plan de proyecto que dedique algunas semanas a la creación de un modelo de casos de uso muy amplio pero sin mayores detalles, para luego decir cuales casos de uso van en cada una de las iteraciones.

Claro que al gestionar nuestros proyectos de esta forma hay que priorizar los casos de uso, según el riesgo y según su relevancia para establecer una arquitectura estable, conceptos que ahora si podemos entender sin mayores problemas: del total de casos de uso identificados, detallamos en las primeras iteraciones aquellos que sean identificados como de alto riesgo o como de mayor impacto en la arquitectura del software.

La otra vía es casi imposible de practicar: documentar en detalle los requisitos aún antes de comenzar a desarrollar la primera línea del código es decir que todo se puede saber de antemano, por lo que para aquellos de entre nosotros que carecemos de la omnisciencia vamos inevitablemente a cometer errores.

Entonces no tentemos al destino. Los requisitos cambian durante el tiempo de vida de los proyectos; no perdamos el tiempo capturando detalles que van a cambiar. Por otra parte, identificar a grandes rasgos las principales características que se nos piden es vital para tener una idea de la magnitud del desarrollo así como de los recursos que tendremos que invertir (tiempo, dinero, etc.) y finalmente, no tiene mucho sentido excluir a los requisitos de la planificación del proyecto, por lo que tenemos de una u otra forma que integrar a los casos de uso en el diseño del proceso de desarrollo.

Todo lo anterior nos obliga a todos quienes practicamos el desarrollo guiado por casos de uso a trabajar primero a lo ancho: prefiriendo lo amplio a lo detallado en tanto dichos detalles no sean impresindibles.

, , , , , , , ,

Deja un comentario

Casos de Uso: Herencia de Actores

La propiedad de mayor interés de los actores, más allá de su identidad, es la relación que estos guarden con los distintos casos de uso de nuestro sistema – las líneas que unen a unos con otros. Es decir que las dos partes más expresivas de un actor son el nombre propio y la activación de un caso de uso.

Aceptado lo anterior, la herencia de actores va a ser la distribución a lo largo de una jerarquía de roles, de las actividades a realizar, representadas estas como casos de uso. O lo que es lo mismo, la herencia nace como una forma de organizar los enlaces entre actores y casos de uso a fin de simplificar los diagramas y reducir la necesidad de presentar información repetida.

Nuevamente pero algo más técnico: a lo largo de la jerarquía de herencia lo que vamos a organizar son las activaciones de casos de uso de cada actor con ayuda de categorías intermedias o actores abstractos.

A diferencia de la herencia de casos de uso, considero que la herencia de actores es una práctica básica y que no tiene mayor problema en ser entendido por los stakeholders ni mucho menos, presenta problemas a los analistas. La razón es que la dificultad de la herencia de los casos de uso es la definición detallada de como los múltiples elementos de información de un caso de uso se comporta durante la herencia, dificultad esta que no existe en la herencia de actores por ser estos tan sencillos.

Como dije antes, la herencia de actores es una forma legible de mejorar la presentación de nuestros modelos, por lo que ejemplo que daré tiene por motivación el mejorar la legibilidad de un por lo demás, muy sencillo modelo de casos de uso.

A efectos del ejemplo, supongamos que trabajamos con un sistema de ventas, que permite tanto a los promotores como a los empleados del departamento de ventas el visualizar las existencias de productos así como la consignación de mercancía, pero que excluye a los promotores de la posibilidad de aceptar devoluciones. La situación es presentada en el siguiente diagrama de casos de uso:

Ejemplo de modelo de casos de uso sin herencia

Fig. 1 – Ejemplo de modelo de casos de uso sin herencia

Si se observa con atención el diagrama 1, se ve como las líneas de activación se cruzan entre actores. Claro que podemos tratar de organizar un poco mejor el diagrama para evitar esto, pero hemos de reconocer que esto solo será una solución temporal. Conforme se incremente la cantidad de casos de uso nos encontraremos una y otra vez en esta situación. No es solo una cuestión de estética, de utilizar líneas segmentadas bien podríamos llegar a hacer el diagrama por completo ilegible. Es entonces necesario un enfoque alternativo.

Dicho enfoque alternativo naturalmente va a ser la herencia. En el segundo diagrama se ven exactamente los mismos casos de uso y los mismos actores, pero se ha establecido una relación de herencia con respecto a un actor abstracto u operador como estrategia para presentar la información sin tanto barullo de líneas.

Ejemplo de modelo de casos de uso con relación de herencia entre actores

Fig. 2 – Ejemplo de modelo de casos de uso con herencia entre actores

En este segundo diagrama hemos indicado que el operador puede realizar las dos tareas comunes, en tanto que por herencia hemos dicho que los empleados del departamento de ventas son los únicos autorizados a aceptar devoluciones de mercancías. Aquí hay que notar que no he establecido una relación de herencia entre promotor y ventas, sino que por el contrario he introducido un actor abstracto nuevo, que articula la presentación del modelo sin correr el riesgo de equivoco: promotor no es ventas y ventas no es promotor. El hecho que compartan dos casos de uso si es algo digno de mención pero sus identidades siguen por completo desligadas.

La presencia de un actor abstracto puede ser considerada una fuente de ruido a la hora de explicar el modelo, pero dado que es solo para simplificar las líneas de activación encuentro que la sobrecarga de información no es nociva. Por otra parte lo que hemos ganado en claridad es en mi opinión, mucho mayor a lo que hemos sacrificado al utilizar una notación un poco más técnica.

, , , , , , , , , ,

13 comentarios

Un buen requisito debe ser atómico

“Un buen requisito debe ser atómico” lo digo y lo repito: Un buen requisito debe ser atómico. Sin embargo esto no significa que debe guardar alguna relación con la industria militar o la energía atómica. Si bien el átomo es un concepto de la ciencia moderna, el adjetivo atómico significa indivisible o dicho en otras palabras: único, singular, no susceptible a ser dividido.

Claro que eventualmente lo vamos a analizar y de ahí, que propongamos una relación de objetos que al colaborar den a lugar la funcionalidad requerida; pero el requisito en si mismo ha de describir un único requisito.

Y es que ocurre que en ocasiones un analista despistado, construye un cuerpo de requisitos donde uno o más de estos, contiene alguna forma de declaración compuesta, de forma que se refiere sin querer, a más de una característica.

La misma necesidad de atomicidad es requerida en los casos de uso. Un buen caso de uso debe hablarnos de un escenario de interacción completo y singular de manera que pueda ser tomado como una unidad indivisible.

Varios trucos se pueden dar para lograr este criterio de atomicidad: evitar las declaraciones compuestas y referirse en todo momento a una única característica son solo las dos primeras que me vienen a la mente. Sin embargo, como las recetas universales siempre tienen casos en que fallan, me limitaré a solo indicar lo que queremos: un requisito de buena calidad siempre ha de ser atómico.

El como lo logre el analista de requisitos es más cosa de habilidad que de consejos leídos por ahí.

, , , , , , , , , ,

5 comentarios

Un buen caso de uso captura valor de negocio

Una de las principales dificultades a la hora de desarrollar un cuerpo de requisitos para un sistema es el hecho innegable de la diferencia de formación entre los profesionales del desarrollo de software y los clientes de estos.

En tanto los desarrolladores cuentan con experiencia en algoritmia, análisis o modelado, los clientes suelen tener formación en contabilidad, finanzas, construcción o quien sabe en qué. Esta diferencia se extrapola a los puntos de vista de cada lado de la mesa, por lo que a la hora de definir el sistema que se desea es inevitable que el desarrollador note vacíos o faltas en la especificación (puntos como: seguridad, gestión de datos y otros aspectos técnicos) a la vez que el cliente puede hacer mucho hincapié en aspectos que a primera vista y desde el punto de vista del desarrollador son menos urgentes o se explicaron ya con unas pocas palabras.

Un poco por lo anterior es la muy conocida queja contra los clientes “no saben lo que quieren” pero en verdad la queja es debida a un fallo en el análisis del profesional de computación: los clientes especifican lo que les preocupa y esto no es ni de lejos, una especificación completa para una aplicación.

Paradójico quizás, en el sentido en que es contrario a la intuición de algunos, pero es que los clientes deben ver que los sistemas que solicitan responden a sus necesidades y aspectos técnicos que son del conocimiento del desarrollador los ven como parte de la solución técnica propuesta por este; lo que el cliente especifica es de valor para él y lo que no especifica es el margen de maniobra que se usa en la busqueda de la mejor solución técnica posible.

De todo lo anterior se desprende una regla básica para obtener un buen requisito y de ahí, un buen caso de uso: todo caso de uso ha de capturar valor de negocio. No hacemos casos de uso para especificar el comportamiento técnico del sistema, por lo que no tenemos casos de uso para indicar el ingreso al sistema o la generación de copias de seguridad. Si tales cosas no son del interés directo del cliente lo mejor es dejarlas por fuera del modelo de casos de uso. En cambio, aspectos quizás irrelevantes como la generación de un reporte o la aprobación de un supervisor a un paso del flujo de trabajo de la aplicación ha de representarse como caso de uso ya que es de interés para el cliente y le ayuda a decir lo que quiere decir sobre el sistema.

, , , , , ,

Deja un comentario