Tarea: Diseño de caso de uso
En esta tarea se define cómo perfeccionar los productos de Análisis de guión de uso desarrollando realizaciones de guión de uso a nivel de diseño.
Objetivo
  • Perfeccionar las realizaciones de caso de uso en términos de interacciones
  • Perfeccionar los requisitos en las operaciones de las clases de diseño
  • Perfeccionar los requisitos en las operaciones de los subsistemas de diseño y/o sus interfaces
  • Perfeccionar los requisitos en las operaciones de las cápsulas
Relaciones
RolesPrincipal: Adicional: Asistencia:
EntradasObligatoria: Opcional: Externa:
  • Ninguno
Salidas
Descripción principal

El comportamiento de un sistema se puede describir utilizando varias técnicas: colaboraciones o interacciones. En esta tarea se describe el uso de interacciones, en concreto, diagramas de secuencia, para describir el comportamiento del sistema. Los diagramas de secuencia son más útiles cuando el comportamiento del sistema o subsistema se puede describir principalmente mediante mensajería síncrona. La mensajería asíncrona, sobre todo en sistemas dirigidos por sucesos, se describe a menudo más fácilmente en términos de máquinas de estado y colaboraciones, lo que ofrece una forma compacta de definir las interacciones posibles entre los objetos. Los mensajes asíncronos juegan un papel importante en los sistemas reactivos o en tiempo real, y se utilizan para la comunicación entre instancias de Producto de trabajo: Cápsula.

 Representación UML 1.x

Puede utilizar una clase de proxy para representar el subsistema en diagramas de secuencia. Esta clase de proxy está contenida en el subsistema y se utiliza para representar el subsistema en diagramas que no dan soporte al uso directo de paquetes y subsistemas como elementos de comportamiento. Utilice la clase de proxy en aquellos casos en los que desee mostrar que un subsistema específico responde a un mensaje. En este caso, puede mostrar los mensajes que se envían desde el proxy del subsistema a otros objetos.

Consulte el apartado Diferencias entre UML 1.x y UML 2.0 para obtener más información.

Pasos
Crear realizaciones de caso de uso

Producto de trabajo: Realización de caso de uso de diseño ofrece una forma de rastrear hacia atrás el comportamiento en el modelo de diseño hasta el modelo de caso de uso , y organiza colaboraciones en el modelo de diseño alrededor del concepto de caso de uso .

Cree una realización de caso de uso de diseño en el modelo de diseño para cada caso de uso que se va a diseñar. El nombre de la realización de caso de uso de diseño debe ser el mismo que el del caso de uso asociado, y se debe establecer una relación "realiza" desde la realización de caso de uso de análisis con el caso de uso asociado.

Describir interacciones entre objetos de diseño

Para cada realización de caso de uso , debe ilustrar las interacciones entre los objetos de diseño participantes creando uno o más diagramas de secuencia. Las primeras versiones de éstas pueden haberse creado durante Tarea: Análisis de caso de uso .  Estas "versiones de análisis" de las realizaciones de caso de uso describen las interacciones entre las clases de análisis.  Deben evolucionar para describir las interacciones entre los elementos de diseño.

La actualización de diagramas de secuencia implica los pasos siguientes:

  • Identifique cada objeto que participe en el flujo del caso de uso . Para ello se crea una instancia de las clases y los subsistemas de diseño identificados en Tarea: Identificar elementos de diseño. En los sistemas en tiempo real, también se identificarán las instancias de cápsula que participan en el flujo del caso de uso .
  • Represente cada objeto participante en un diagrama de secuencia. Cree una línea de vida para cada objeto participante en el diagrama de secuencia. Para representar los subsistemas de diseño, tiene varias opciones:
    • Puede mostrar instancias del subsistema en el diagrama de secuencia.
    • Puede utilizar las interfaces realizadas por el subsistema. Esta opción es la preferida en aquellos casos en los que desea mostrar que cualquier elemento de modelo que realiza la misma interfaz se puede utilizar en lugar de la interfaz. Si elige mostrar interfaces en el diagrama de secuencia, tenga en cuenta que deseará garantizar que no se envíen mensajes desde la interfaz a otros objetos. Esto se debe a que las interfaces encapsulan completamente la realización interna de sus operaciones. Por lo tanto, no podemos estar seguros de que todos los elementos de modelo que realizan las interfaces estarán diseñados de la misma forma. Por lo tanto, en los diagramas de secuencia no se deben mostrar los mensajes que se envían desde las interfaces.
    • Puede utilizar el componente para representar el subsistema en diagramas de secuencia. Utilice el componente en aquellos casos en los que desee mostrar que un subsistema específico responde a un mensaje. En este caso, puede mostrar los mensajes que se envían desde el componente a otros objetos.

    Tenga en cuenta que estos son diagramas de secuencia a nivel de sistema, que muestran cómo interactúan las instancias de elementos de diseño de nivel superior (normalmente subsistemas e interfaces de subsistema). Los diagramas de secuencia que muestran el diseño interno de los subsistemas se producen de forma independiente, como parte de Tarea: Diseño de subsistemas.

  • Tenga en cuenta que las interacciones de los objetos activos se describen normalmente utilizando colaboraciones de especificaciones y máquinas de estado. Aquí se utilizarán para mostrar cómo pueden enviar mensajes a los objetos activos los otros elementos del sistema en una realización de caso de uso de mayor tamaño. En una utilización típica, los objetos activos se encapsulan dentro de los subsistemas para ejecutar esta tarea, de forma que la realización de los casos de uso consiste en un conjunto de subsistemas que interactúan. Las interacciones definen las responsabilidades y las interfaces de los subsistemas. Dentro de los subsistemas, los objetos activos representan hebras de ejecución concurrentes. Los subsistemas permiten dividir el trabajo entre los equipos de desarrollo, utilizando las interfaces como contratos formales entre los equipos. En los sistemas en tiempo real, se utilizarán Producto de trabajo: Cápsulas para representar los objetos activos.

    Una nota secundaria sobre cómo mostrar los mensajes que surgen de los subsistemas: la restricción de los mensajes sólo a las interfaces reduce el acoplamiento entre los elementos de modelo y aumenta la elasticidad del diseño. Siempre que sea posible, intente hacerlo de esta forma y, en aquellos casos en los que existan mensajes que emanan de los subsistemas a elementos de modelo que no son interfaces, busque oportunidades de cambiarlos por mensajes a interfaces, para mejorar así el desacoplamiento en el modelo.

  • Represente la interacción que tiene lugar con los actores. Represente cada instancia de actor y cada objeto externo con el que interactúan los objetos participantes mediante una línea de vida en el diagrama de secuencia.
  • Ilustre el envío de mensajes entre los objetos participantes. El flujo de sucesos empieza en la parte superior del diagrama y continúa hacia abajo, indicando un eje cronológico vertical. Ilustre el envío de mensajes entre objetos creando mensajes (flechas) entre las líneas de vida. El nombre del mensaje debe ser el nombre de la operación invocada por el mensaje. En las primeras fases del diseño, no se asignan muchas operaciones a los objetos, por lo que puede que tenga que dejar fuera esta información y dar al mensaje un nombre temporal; estos mensajes se dice que están "desasignados". Posteriormente, cuando encuentre más operaciones de los objetos participantes, deberá actualizar el diagrama de secuencia "asignando" estas operaciones a los mensajes.
  • Describa qué hace un objeto cuando recibe un mensaje. Para ello, adjunte un script al mensaje correspondiente. Coloque estos scripts en el margen del diagrama. Utilice texto estructurado o pseudocódigo. Si utiliza pseudocódigo, asegúrese de utilizar constructos en el lenguaje de implementación, para que la implementación de las operaciones correspondientes sea más sencilla. Cuando la persona responsable de la clase de un objeto asigna y define sus operaciones, los scripts del objeto proporcionarán la base para ese trabajo.

Diagrama descrito en el texto adjunto.

El comportamiento del caso de uso ejecutado por los objetos se documenta en un diagrama de secuencia.

Si tiene el comportamiento distribuido entre los objetos, debe decidir cómo se controlará el flujo. Los objetos se han encontrado suponiendo que interactuarán de cierta forma en la realización del caso de uso y que tienen un determinado rol. Cuando distribuya el comportamiento, puede empezar a probar estas suposiciones. En algunas partes del flujo, deberá utilizar una estructura centralizada; en otras, será preferible una estructura centralizada. Para ver una definición de estas variantes y recomendaciones sobre cuándo utilizar cada tipo de estructura, consulte Técnica: Diagramas de secuencia.

Puede que necesite nuevos objetos en este punto, por ejemplo, si utiliza una estructura centralizada y necesita un nuevo objeto para controlar el flujo. Recuerde que todo objeto que añada al modelo de diseño debe cumplir los requisitos creados en el modelo de objeto.

Incorporar mecanismos de diseño aplicables

Durante la Tarea: Análisis de la arquitectura, se han identificado mecanismos de análisis.  Durante la Tarea: Identificar los mecanismos de diseño, se han perfeccionado mecanismos de análisis en mecanismos de diseño, se ha capturado la correlación de los mecanismos de análisis con los mecanismos de diseño en el Documento de arquitectura de software, y los mecanismos de diseño se han documentado en las Directrices específicas del proyecto.  

Durante esta tarea, Diseño de caso de uso , todos los mecanismos de diseño aplicables se han incorporado en las realizaciones de los casos de uso .  El diseñador encuesta los mecanismos de diseño disponibles y determina cuáles se aplican a la realización de caso de uso que se está desarrollando, según las recomendaciones y las directrices documentadas en el Documento de arquitectura de software y las Directrices específicas del proyecto.  
Nota: puede que se haya identificado un mecanismo de diseño aplicable en la Tarea: Análisis de caso de uso , durante la que se han "etiquetado" clases de análisis con un determinado mecanismo de análisis, lo que indica que se debe manejar en el diseño una determinada parte de la funcionalidad.  En tal caso, los mecanismos de diseño aplicables son aquellos asociados con los mecanismos de análisis con los que se han etiquetado las clases de análisis que participan en la realización del caso de uso .

El diseñador incorpora los mecanismos de diseño aplicables en las realizaciones de caso de uso , e incluye los elementos de diseño necesarios y las interacciones de elementos de diseño en las realizaciones de caso de uso siguiendo las reglas de uso documentadas en las Directrices de diseño.

Manejar todas las variantes del flujo de sucesos

Debe describir cada variante del flujo en un diagrama de secuencia aparte. Los diagramas de secuencia generalmente son preferibles al diagrama de comunicación, ya que tienden a ser más fáciles de leer cuando el diagrama debe contener el nivel de detalle deseable cuando se diseña el sistema.

Empiece describiendo el flujo básico, que es el flujo de sucesos más común o más importante. A continuación, describa variantes como, por ejemplo, los flujos excepcionales. No es necesario describir todos los flujos de sucesos, siempre que emplee y ejemplifique todas las operaciones de los objetos participantes. A partir de aquí, se pueden omitir los flujos muy triviales como, por ejemplo, aquellos relacionados sólo con un objeto.

Estudie el caso de uso para ver si hay variantes de flujo distintas de las descritas en el análisis y la captura de requisitos como, por ejemplo, aquellas que dependen de la implementación. Cuando identifique nuevos flujos, describa cada uno en un diagrama de secuencia. A continuación se proporcionan ejemplos de flujos excepcionales.

  • Manejo de errores. Si una interfaz informa de que se ha producido un error en la comunicación con algún sistema externo, por ejemplo, el caso de uso debe tratar con él. Una solución posible es abrir una nueva ruta de comunicación.
  • Manejo de tiempo de espera. Si el usuario no responde en un determinado periodo, el caso de uso tomará medidas especiales.
  • Manejo de entrada con error en los objetos que participan en el caso de uso . Los errores como este pueden provenir de una entrada incorrecta del usuario.

Manejar las partes opcionales del caso de uso

Puede describir una vía de acceso alternativa de un flujo como un flujo opcional, en lugar de como una variante. En la lista siguiente se incluyen dos ejemplos de flujos opcionales.

  • Al enviar una señal, el actor decide (entre varias opciones) qué debe hacer el caso de uso a continuación. Por ejemplo, el caso de uso ha solicitado al actor que responda sí o no a una pregunta, o ha proporcionado al actor varias funciones que el sistema puede ejecutar en el estado actual del caso de uso .
  • La vía de acceso del flujo varía según el valor de los atributos o las relaciones que hay almacenados. El siguiente flujo de sucesos depende del tipo de datos que se va a procesar.

Si desea que un flujo opcional, o un subflujo completo, se perciba especialmente, utilice un diagrama de secuencia aparte. Cada diagrama de secuencia aparte debe referenciarse desde el diagrama de secuencia del flujo de sucesos principal utilizando scripts, texto al margen o notas para indicar dónde se produce el comportamiento de subflujo u opcional.

En aquellos casos en los que el comportamiento de flujo opcional o excepcional se produce en cualquier parte, por ejemplo, el comportamiento que se ejecuta cuando se produce un determinado suceso, el diagrama de secuencia del flujo de sucesos principal se debe anotar para indicar que, cuando se produce el suceso, el comportamiento descrito en el diagrama de secuencia opcional/excepcional se ejecutará. De manera alternativa, si hay un comportamiento significativo dirigido por sucesos, considere el uso de diagramas de gráfico de estados para describir el comportamiento del sistema. Para obtener más información, consulte Directriz: Diagrama de gráfico de estados.

Simplificar los diagramas de secuencia utilizando subsistemas (opcional)

Cuando se realiza un caso de uso , el flujo de sucesos se describe normalmente en términos de los objetos en ejecución, es decir, como una interacción entre objetos de diseño. Para simplificar los diagramas e identificar el comportamiento reutilizable, puede encapsular un subflujo de sucesos dentro de un subsistema. De esta forma, las subsecciones grandes del diagrama de secuencia se sustituyen por un único mensaje al subsistema. Dentro del subsistema, un diagrama de secuencia aparte puede ilustrar las interacciones internas dentro del subsistema que proporcionan el comportamiento necesario (para obtener más información, consulte Tarea: Diseño de subsistemas).

Las subsecuencias de mensajes dentro de los diagramas de secuencia se deben encapsular dentro de un subsistema cuando:

  • La subsecuencia se produce repetidamente en realizaciones de casos de uso diferentes; esto es, se envían los mismos mensajes (o parecidos) a los mismos objetos (o parecidos), proporcionando el mismo resultado final. Se especifica 'parecidos' porque puede que se deba realizar algún trabajo de diseño para que el comportamiento sea reutilizable.
  • La subsecuencia se produce sólo en una realización de caso de uso , pero se espera que se ejecute repetidamente en futuras iteraciones, o en sistemas parecidos en el futuro. El comportamiento puede ser un buen componente reutilizable.
  • La subsecuencia se produce sólo en una realización de caso de uso , es compleja pero fácilmente encapsulable, debe ser responsabilidad de una persona o un equipo, y proporciona un resultado bien definido. En este tipo de situaciones, el comportamiento complejo normalmente requiere un conocimiento técnico especial, o un conocimiento de dominios especial, y por lo tanto está especialmente indicado para encapsularse en un subsistema.
  • La subsecuencia está determinada para encapsularse en un componente reemplazable (consulte Concepto: Componente). En este caso, un subsistema es la representación adecuada para el componente en el modelo de diseño.

Diagrama descrito en el texto adjunto.

La realización de un caso de uso se puede describir, si es necesario, a varios niveles en la jerarquía de subsistemas. Las líneas de vida en el diagrama medio representan subsistemas; las interacciones en los círculos representan la interacción interna de los miembros del subsistema como respuesta al mensaje.

Las ventajas de este enfoque son:

  • Las realizaciones de caso de uso quedan menos desordenadas, especialmente si el diseño interno de algunos subsistemas es complejo.
  • Las realizaciones de caso de uso se pueden crear antes que los diseños internos de los subsistemas; esto es muy útil, por ejemplo, en los entornos de desarrollo paralelos (consulte "Cómo trabajar en paralelo").
  • Las realizaciones de caso de uso son más genéricas y fáciles de modificar, especialmente si se tiene que sustituir un subsistema por otro.

Ejemplo:

Considere el siguiente diagrama de secuencia, que forma parte de una realización del caso de uso Llamada local:

Diagrama descrito en el texto adjunto.

En este diagrama, las clases grises pertenecen a un subsistema Manejo de redes; las otras clases pertenecen a un subsistema Manejo de suscriptores. Esto significa que es un diagrama de secuencia de varios subsistemas, es decir, un diagrama en el que están incluidos todos los objetos que participan en el flujo de sucesos, independientemente de si sus clases están en distintos subsistemas o no.

Como alternativa, podemos mostrar la invocación de comportamiento en el subsistema Manejo de redes, y el ejercicio de una determinada interfaz en ese subsistema. Supongamos que el subsistema Manejo de redes proporciona una interfaz ICoordinator, que es utilizada por el subsistema Manejo de suscriptores.

Diagrama descrito en el texto adjunto.

La clase Coordinador dentro de Manejo de redes realiza la interfaz ICoordinator. Según esto, podemos utilizar el propio subsistema Manejo de redes y la interfaz ICoordinator en el diagrama de secuencia, en lugar de instancias de clases dentro de Manejo de redes.

Diagrama descrito en el texto adjunto.

Tenga en cuenta que las instancias de clase Coordinador, Información de dígitos y Red se sustituyen por el subsistema que las contienen. Todas las llamadas al subsistema se realizan en su lugar a través de la interfaz ICoordinator.

Mostrar interfaces en líneas de vida

Para poder conseguir una auténtica capacidad de sustitución de subsistemas que realizan la misma interfaz, sólo debe estar visible su interfaz en las interacciones (y en los diagramas en general); de lo contrario, las interacciones (o diagramas) se tienen que modificar cuando se sustituyen los subsistemas por otros.

Ejemplo:

Podemos incluir sólo la interfaz ICoordinator, pero no el subsistema que la proporciona, en un diagrama de secuencia:

Diagrama descrito en el texto adjunto.

El envío de un mensaje a una línea de vida de interfaz significa que cualquier subsistema que realiza la interfaz se puede sustituir por la interfaz en el diagrama. Tenga en cuenta que la línea de vida de la interfaz ICoordinator no tiene mensajes salientes, ya que distintos subsistemas que realizan la interfaz pueden enviar distintos mensajes. No obstante, si desea describir qué mensajes se deben enviar (o están permitidos para su envío) desde cualquier subsistema que realice la interfaz, dichos mensajes pueden salir de la línea de vida de la interfaz.

Cómo trabajar en paralelo

En algunos casos, puede ser adecuado desarrollar un subsistema de forma más o menos independiente y en paralelo con el desarrollo de otros subsistemas. Para ello, debemos encontrar primero dependencias de subsistemas identificando las interfaces entre ellos.

El trabajo se puede hacer de la siguiente manera:

  1. Concéntrese en los requisitos que afectan a las interfaces entre los subsistemas.
  2. Realice esquemas de las interfaces necesarias, mostrando los mensajes que van a pasar los límites del subsistema.
  3. Dibuje diagramas de secuencia en términos de subsistemas para cada caso de uso .
  4. Perfeccione las interfaces necesarias para proporcionar mensajes.
  5. Desarrolle cada subsistema en paralelo y utilice las interfaces como instrumentos de sincronización entre equipos de desarrollo.

También puede elegir si desea organizar los diagramas de secuencia en términos de subsistemas o sólo en términos de sus interfaces. En algunos proyectos, incluso deberá implementar las clases proporcionando las interfaces para poder continuar con el resto del modelado.

Describir el comportamiento relacionado con la persistencia

El objetivo global del paradigma orientado a los objetos es encapsular los detalles de implementación. Por lo tanto, en cuanto a la persistencia, nos interesa que el objeto persistente parezca un objeto transitorio. No deseamos notar que el objeto es persistente, ni tratarlo de forma diferente a como lo haríamos con cualquier otro objeto. Al menos, ese es el objetivo.

En la práctica, habrá veces en las que la aplicación necesitará controlar varios aspectos de la persistencia:

  • cuándo se leen y se escriben los objetos persistentes
  • cuándo se suprimen los objetos persistentes
  • cómo se gestionan las transacciones
  • cómo se consigue el control de concurrencia y el bloqueo

Escribir objetos persistentes

Se deben tener en cuenta dos casos: la primera vez que se escribe el objeto en el almacén de objetos persistentes, y las siguientes veces cuando la aplicación desea actualizar el almacén de objetos persistentes con un cambio en el objeto.

En ambos casos, el mecanismo específico depende de las operaciones soportadas por la infraestructura de persistencia. Normalmente, el mecanismo utilizado es enviar un mensaje a la infraestructura de persistencia para crear el objeto persistente. Una vez el objeto es persistente, la infraestructura de persistencia es lo suficientemente inteligente para detectar los cambios posteriores en el objeto persistente y escribirlos en el almacén de objetos persistentes cuando sea necesario (normalmente, cuando se compromete una transacción).

A continuación se muestra un ejemplo de un objeto persistente que se está creando:

Diagrama descrito en el texto adjunto.

El objeto PersistenceMgr es una instancia de VBOS, una infraestructura de persistencia. OrderCoordinator crea un Pedido persistente, al enviarlo como argumento de un mensaje 'createPersistentObject' a PersistenceMgr.

Generalmente no es necesario modelarlo explícitamente, a menos que sea importante saber que el objeto se está almacenando de forma explícita en un determinado punto en la secuencia de sucesos. Si las posteriores operaciones necesitan consultar el objeto, el objeto debe existir en la base de datos y, por lo tanto, es importante saber que el objeto se encuentra en ella.

Leer objetos persistentes

La recuperación de objetos del almacén de objetos persistentes es necesaria para que la aplicación pueda enviar mensajes a esos objetos. Recuerde que el trabajo en un sistema orientado a los objetos se realiza enviando mensajes a los objetos. No obstante, si el objeto al que desea enviar un mensaje está en la base de datos pero no en la memoria, tiene un problema: no puede enviar un mensaje a algo que no existe todavía.

En resumen, necesita enviar un mensaje a un objeto que sabe cómo consultar la base de datos, recuperar el objeto correcto y crear una instancia para él. A continuación, y sólo entonces, puede enviar el mensaje original que deseaba enviar. El objeto que crea una instancia de un objeto persistente se denomina a veces objeto de fábrica. Un objeto de fábrica es responsable de crear instancias de objetos, incluidos los objetos persistentes. Dada una consulta, la fábrica se puede diseñar para devolver un conjunto de uno o varios objetos que coincidan con la consulta.

En general, los objetos están ampliamente conectados entre ellos mediante asociaciones, por lo que sólo será necesario recuperar el objeto raíz en un gráfico de objetos; el resto se 'extraen' de forma transparente de la base de datos mediante sus asociaciones con el objeto raíz. (Un buen mecanismo de persistencia tiene esto en cuenta: sólo recupera los objetos cuando son necesarios; de lo contrario, terminaríamos creando instancias de un gran número de objetos de forma innecesaria. La recuperación de objetos antes de que sean necesarios es uno de los principales problemas de rendimiento provocados por mecanismos de persistencia simplistas).

En el siguiente ejemplo se muestra cómo se puede modelar la recuperación de objetos desde el almacén de objetos persistentes. En un diagrama de secuencia real, no se mostrará el DBMS, ya que estará encapsulado en el objeto de fábrica.

Diagrama descrito en el texto adjunto.

Suprimir objetos persistentes

El problema con los objetos persistentes es precisamente que persisten. A diferencia de los objetos transitorios, que simplemente desaparecen cuando termina el proceso que los ha creado, los objetos persistentes existen hasta que se suprimen de forma explícita. Por lo tanto, es importante suprimir el objeto cuando ya no se esté utilizando.

El problema es que esto es difícil de determinar. Que una aplicación haya terminado con un objeto no significa que todas las aplicaciones, actuales y futuras, hayan terminado con él. Asimismo, como los objetos puedan tener y tienen asociaciones que incluso ellos no conocen, no siempre es fácil determinar si es correcto suprimir un objeto.

En diseño, esto se puede representar semánticamente utilizando diagramas de estado: cuando el objeto alcanza el estado fin, se puede decir que está liberado. A continuación, los desarrolladores responsables de implementar las clases persistentes pueden utilizar la información del diagrama de estado para invocar el comportamiento del mecanismo de persistencia adecuado para liberar el objeto. La responsabilidad del diseñador de la realización del caso de uso es invocar las operaciones adecuadas para que el objeto alcance el estado fin cuando sea correcto suprimir el objeto.

Si un objeto está ampliamente conectado a otros objetos, será difícil determinar si el objeto se puede suprimir. Como un objeto de fábrica conoce la estructura del objeto así como los objetos con los que está conectado, a menudo es útil cargar el objeto de fábrica para una clase con la responsabilidad de determinar si se puede suprimir una determinada instancia. La infraestructura de persistencia también puede dar soporte a esta capacidad.

Modelar transacciones

Las transacciones definen un conjunto de invocaciones de operaciones que son atómicas; o se ejecutan todas, o no se ejecuta ninguna. En el contexto de la persistencia, una transacción define un conjunto de cambios en un conjunto de objetos que, o se ejecutan todos, o no se ejecuta ninguno. Las transacciones proporcionan coherencia y garantizan que los conjuntos de objetos pasan de un estado coherente a otro.

Existen varias opciones para mostrar las transacciones en las realizaciones de caso de uso :

  • Textualmente. Utilizando scripts en el margen del diagrama de secuencia, se pueden documentar los límites de transacción, tal como se muestra a continuación. Este método es sencillo y permite utilizar un número cualquiera de mecanismos para implementar la transacción.

Diagrama descrito en el texto adjunto.

Representación de límites de transacción utilizando anotaciones textuales.

  • Utilizando mensajes explícitos. Si el mecanismo de gestión de transacciones que se está utilizando utiliza mensajes explícitos para empezar y finalizar las transacciones, estos mensajes se pueden visualizar explícitamente en el diagrama de secuencia, tal como se muestra a continuación:

Diagrama descrito en el texto adjunto.

Un diagrama de secuencia que muestra mensajes explícitos para iniciar y detener transacciones.

Manejar condiciones de error

Si no se pueden ejecutar todas las operaciones especificadas en una transacción (normalmente porque se ha producido un error), la transacción termina anormalmente y se invierten todos los cambios realizados durante la misma. Las condiciones de error anticipadas representan a menudo flujos excepcionales de sucesos en los casos de uso . En otros casos, se producen condiciones de error debido a alguna anomalía del sistema. Las condiciones de error se deben documentar también en las interacciones. Los errores y las excepciones simples se pueden mostrar en la interacción donde se producen; los errores y las excepciones más complejos pueden necesitar sus propias interacciones.

Las modalidades de anomalía de objetos específicos se pueden mostrar en gráficos de estado. El manejo del flujo de control condicional de estas modalidades de anomalía se puede mostrar en la interacción en la que se produce el error o la excepción.

Manejo del control de concurrencia

La concurrencia describe el control del acceso a recursos críticos del sistema en el curso de una transacción. Para mantener el sistema en un estado coherente, la transacción necesitará acceso exclusivo a determinados recursos clave del sistema. Esta exclusividad puede incluir la capacidad de leer un conjunto de objetos, escribir un conjunto de objetos, o ambos.

Observemos un ejemplo sencillo de por qué puede ser necesario restringir el acceso a un conjunto de objetos. Supongamos que estamos ejecutando un sistema de entrada de pedido sencillo. Las personas llaman para hacer pedidos y nosotros los procesamos y los enviamos. Podemos ver el pedido como un tipo de transacción.

Para ilustrar la necesidad del control de concurrencia, supongamos que hago una llamada para solicitar un nuevo par de botas de montaña. Cuando el pedido entra en el sistema, comprueba si las botas que deseo están en el inventario en la talla correcta. Si lo están, deseamos reservar ese par, para que nadie más pueda comprarlas antes de que se envíe el pedido. Una vez enviado el envío, las botas se eliminan del inventario.

Durante el periodo entre la realización y el envío del pedido, las botas están en un estado especial& están en el inventario, pero están "comprometidas" a mi pedido. Si mi pedido se cancela por algún motivo (cambio de opinión, o mi tarjeta de crédito ha caducado), las botas se devuelven al inventario. Una vez enviado el pedido, se supone que la pequeña empresa no desea mantener un registro de que una vez tuvo las botas.

El objetivo de la concurrencia, como en las transacciones, es garantizar que el sistema cambia de un estado coherente a otro. Asimismo, la concurrencia intenta garantizar que una transacción tenga todos los recursos que necesita para completar su trabajo. El control de concurrencia se puede implementar de varias formas, por ejemplo, mediante el bloqueo de recursos, los semáforos, los cierres de memoria compartida y los espacios de trabajo privados.

En un sistema orientado a los objetos, es difícil determinar sólo a partir de los patrones de mensajes si un determinado mensaje puede provocar un cambio de estado en un objeto. Asimismo, implementaciones diferentes pueden obviar la necesidad de restringir el acceso a determinados tipos de recursos; por ejemplo, algunas implementaciones proporcionan a cada transacción su propia vista del estado del sistema al principio de la transacción. En este caso, otros procesos pueden cambiar el estado de un objeto sin afectar a la 'vista' de las demás transacciones en ejecución.

Para evitar la restricción de la implementación, en diseño sólo deseamos indicar los recursos a los que la transacción debe tener acceso exclusivo. Utilizando el ejemplo anterior, deseamos indicar que necesitamos acceso exclusivo a las botas que hemos solicitado. Una alternativa sencilla es anotar la descripción del mensaje que se está enviando, indicando que la aplicación necesita acceso exclusivo al objeto. A continuación, el implementador puede utilizar esta información para determinar cómo implementar mejor el requisito de concurrencia. A continuación se muestra un diagrama de secuencia de ejemplo donde se muestra la anotación de qué mensajes requiere acceso exclusivo. Se supone que se liberan todos los bloqueos cuando finaliza la transacción.

Diagrama descrito en el texto adjunto.

Un ejemplo donde se muestra el control de acceso anotado en un diagrama de secuencia.

El motivo de no restringir el acceso a todos los objetos necesarios en una transacción es que a menudo sólo unos pocos deben tener restricciones de acceso; si se restringe el acceso a todos los objetos que participan en una transacción, se pierden recursos valiosos y se pueden crear cuellos de botella de rendimiento, en lugar de impedirlos.

Perfeccionar la descripción del flujo de sucesos

En el flujo de sucesos de la realización de casos de uso , deberá añadir una descripción adicional de los diagramas de secuencia en aquellos casos en los que el flujo de sucesos no esté totalmente claro al examinar los mensajes enviados entre los objetos participantes. Algunos ejemplos incluyen los casos en los que se necesitan anotaciones de tiempo, notas sobre el comportamiento condicional o una aclaración del comportamiento de las operaciones para facilitar la lectura de los diagramas a los observadores externos.

El flujo de sucesos se describe inicialmente en Tarea: Análisis de caso de uso . En este paso, se perfecciona el flujo de sucesos, según sea necesario para aclarar los diagramas de secuencia.

A menudo, el nombre de la operación no es suficiente para entender por qué se está ejecutando la operación. Se necesitarán notas textuales o scripts al margen del diagrama para aclarar el diagrama de secuencia. También se pueden necesitar notas textuales y scripts para representar el flujo de control como, por ejemplo, los pasos de decisiones, los bucles y las ramificaciones. Asimismo, se necesitarán etiquetas textuales para correlacionar los puntos de extensión en el caso de uso con ubicaciones específicas en los diagramas de secuencia.

En los ejemplos anteriores de esta tarea se han mostrado varias formas de anotar diagramas de secuencia.



Unificar los subsistemas y las clases de diseño

A medida que se realizan los casos de uso , debe unificar las clases y los subsistemas de diseño identificados para garantizar la homogeneidad y la coherencia en el Modelo de diseño.

Debe tener en cuenta los siguientes puntos:

  • Los nombres de los elementos de modelo deben describir su función.
  • Evite los nombres parecidos y los sinónimos, ya que dificultan la distinción entre los elementos de modelo.
  • Fusione los elementos de modelo que definan un comportamiento parecido o que representen el mismo fenómeno.
  • Fusione las clases de entidad que representen el mismo concepto o que tengan los mismos atributos, aunque su comportamiento definido sea diferente.
  • Utilice la herencia para abstraer los elementos de modelo, lo que tiende a fortalecer el modelo.
  • Cuando actualice un elemento de modelo, actualice también la descripción de flujo de sucesos correspondiente de las realizaciones de casos de uso .
Evaluar los resultados

Debe comprobar el modelo de diseño en esta fase para verificar que el trabajo sigue la dirección correcta. No es necesario revisar el modelo en detalle, pero debe tener en cuenta el Modelo de diseño mientras trabaja en él.

Consulte especialmente Realización de casos de uso en Tarea: Revisar el diseño.

Propiedades
Varias apariciones
Condicionado por sucesos
Continuo
Opcional
Planeado
Se puede repetir
Más información