Tarea: Identificar elementos de diseño
En esta tarea se explica cómo se identifican los subsistemas, las clases, las interfaces, los sucesos y las señales.
Objetivo
  • Analizar las interacciones de las clases de análisis para identificar los elementos de modelo de diseño
Relaciones
Descripción principal

Tarea: Análisis de caso de uso da como resultado clases de análisis, que representan elementos conceptuales que pueden ejecutar un comportamiento. En diseño, las clases de análisis evolucionan hasta convertirse en varios tipos de elementos de diseño:

  • clases, que representan un conjunto de responsabilidades detalladas;
  • subsistemas, que representan un conjunto de responsabilidades sin detallar, puede que compuesto por otro conjunto de subsistemas y, en última instancia, por un conjunto de clases;
  • clases activas, que representan hebras en el sistema;
  • interfaces, que representan declaraciones abstractas de responsabilidades proporcionadas por una clase o subsistema.

Asimismo, en diseño también se identifican:

  • sucesos, que son especificaciones de apariciones interesantes en el tiempo y el espacio que normalmente (si son resaltables) requieren alguna respuesta del sistema; y
  • señales, que representan mecanismos asíncronos que se utilizan para comunicar determinados tipos de sucesos dentro del sistema.

Estas distinciones más específicas nos permiten examinar distintos aspectos del diseño:

  • Los sucesos y las señales que se utilizan para comunicarlos nos permiten describir los desencadenantes asíncronos de comportamiento a los que debe responder el sistema.
  • Las clases y las subclases nos permiten agrupar responsabilidades relacionadas en unidades que se pueden desarrollar con una relativa independencia; las clases cumplen un conjunto atómico de responsabilidades relacionadas, mientras que los subsistemas son bloques de construcción compuestos formados a su vez por clases u otros subsistemas. Los subsistemas se utilizan para representar los productos de trabajo de un equipo de desarrollo como una unidad única e integral de funcionalidad, y como tales se utilizan como unidades de control y gestión de configuraciones y como elementos de diseño lógico.
  • Las clases activas se utilizan para representar hebras de control en el sistema, lo que permite el modelado de la concurrencia. Las clases activas a menudo se utilizan en composición con otras clases que suelen ser, aunque no necesariamente, pasivas: más adelante, este tipo de composición se puede utilizar (de la misma forma que una colaboración) para modelar el comportamiento complejo.

    En sistemas en tiempo real, se utilizan cápsulas en lugar de clases activas, lo que permite una semántica más sólida para simplificar el diseño y aumentar la fiabilidad de las aplicaciones concurrentes. Las cápsulas comparten algunos aspectos de las clases y los subsistemas: de hecho, son colaboraciones encapsuladas de clases que representan conjuntamente una hebra de control en el sistema. Se diferencian de los subsistemas en el sentido de que una cápsula es responsabilidad de un único diseñador, mientras que un subsistema es responsabilidad (normalmente) de un equipo de desarrolladores; no obstante, un subsistema puede contener cápsulas. 

  • Las interfaces nos permiten examinar y capturar las 'costuras' del sistema, y definen en términos precisos cómo interactuarán las partes constituyentes del sistema.
  • En los sistemas en tiempo real, utilizaremos protocolos para definir con precisión los mensajes que se pueden enviar y recibir en un puerto de una cápsula.

Al separar y manejar independientemente cada problema representado por estos conceptos, se simplifica el proceso de diseño y se clarifica la solución.

Si se debe mantener la rastreabilidad entre los modelos del sistema, se debe documentar durante esta tarea.  Para obtener más información sobre cómo documentar la rastreabilidad entre el modelo de diseño y otros modelos del sistema, consulte Directriz: Modelo de diseño.

 Representación UML 1.x

De acuerdo con UML 1.5, un subsistema es un tipo especial de paquete que tiene sólo interfaces como elementos públicos. Las interfaces proporcionan una capa de encapsulación, lo que permite mantener oculto el diseño interno del subsistema de otros elementos de modelo. El subsistema de concepto se utiliza para distinguirlo de los paquetes "ordinarios", que son contenedores sin semántica de elementos de modelo; el subsistema representa un determinado uso de paquetes con propiedades de tipo clase (de comportamiento).

En RUP, las cápsulas se representan utilizando la notación UML 1.5. La mayor parte de esto se puede representar en UML 2.0 mediante Concepto: Clase estructurada.

Consulte Differences Between UML 1.x and UML 2.0 para obtener más información.

Pasos
Identificar sucesos y señales
Objetivo Identificar los sucesos externos e internos, y las señales a las que debe responder el sistema. 

Los sucesos son apariciones externas e internas que provocan acciones en el sistema. Los sucesos y sus características permiten dirigir la identificación de elementos de diseño clave como, por ejemplo, las clases activas.

Del modelo de caso de uso se puede derivar una lista inicial de sucesos externos, a partir de las interacciones de los actores con los casos de uso . Los sucesos internos se pueden derivar del texto en los flujos de casos de uso , o se pueden identificar a medida que evoluciona el diseño.

Las características más importantes de los sucesos son:

  • interno o externo - ¿El suceso es externo o interno?
  • prioridad - ¿Este suceso debe provocar la suspensión de otros procesos para poder manejarlo?
  • frecuencia - ¿Con qué frecuencia se produce el suceso?
  • distribución de frecuencia - ¿Se produce el suceso a intervalos regulares o hay picos?
  • requisitos de respuesta - ¿Con qué rapidez debe responder el sistema al suceso (distíngase entre la media y el peor de los casos)?
  • tipo - ¿Es un suceso de llamada, un suceso de tiempo, un suceso de señal o un suceso de cambio (consulte Concepto: Sucesos y señales para ver las definiciones)?

Las características de los sucesos se deben capturar según sea necesario para dirigir la identificación de los elementos de diseño que los manejan. La captura de características de sucesos tiende a ser más importante en los sistemas reactivos (dirigidos por sucesos), pero puede ser útil en otros sistemas como, por ejemplo, aquellos con concurrencia y/o mensajería asíncrona.

Los sucesos de comunicación asíncrona se pueden modelar como señales para expresar los datos que transportan o para expresar relaciones entre señales, por ejemplo, la generalización. En algunos sistemas, en concreto, en los sistemas reactivos, es importante relacionar las señales recibidas de dispositivos externos con mecanismos específicos como, por ejemplo, interrupciones o mensajes de sondeo específicos.

Identificar las clases, las clases activas y los subsistemas
Objetivo Perfeccionar las clases de análisis en elementos de modelo de diseño adecuados 

Identificar clases. Cuando la clase de análisis es simple y representa una única abstracción lógica, se puede correlacionar directamente, 1:1, con una clase de diseño. Normalmente, las clases de entidad sobreviven relativamente intactas en el diseño. Como las clases de entidad normalmente también son persistentes, determine si la clase de diseño debe ser persistente y anótelo según corresponda en la descripción de clase.

Cuando se identifican las clases, se deben agrupar en Producto de trabajo: Paquetes de diseño, a efectos de organización y gestión de configuraciones. Consulte el apartado Directriz de producto de trabajo: Paquete de diseño para obtener más información sobre cómo tomar decisiones de empaquetado.

Identificar clases activas. Considere los requisitos de concurrencia del sistema en el contexto de los objetos de análisis identificados: ¿es necesario que el sistema responda a sucesos generados externamente y, en caso afirmativo, qué clases de análisis están 'activas' cuando se producen los sucesos? Los sucesos externos en el modelo de caso de uso están representados por estímulos provenientes de los actores, que interactúan con un caso de uso . Observe las realizaciones de casos de uso correspondientes para ver qué objetos interactúan cuando se produce un suceso. Empiece por agrupar los objetos en conjuntos autónomos de objetos de colaboración; estas agrupaciones representan un corte inicial en un grupo que puede formar una clase activa compuesta.

Si los sucesos tienen atributos importantes que se deben capturar, considere modelarlos como clases, una <<señal>> estereotipada. En sistemas en tiempo real, estos conjuntos identificados de objetos se deben agrupar en cápsulas, que tienen una semántica de encapsulación sólida.

Las instancias de las clases activas representan hebras de ejecución 'lógicas' independientes. Estas hebras de ejecución 'lógicas' no se deben confundir ni correlacionar literalmente con hebras de ejecución en el sistema operativo (aunque en algún punto se correlacionarán con hebras de ejecución del sistema operativo). Representan hebras de ejecución conceptuales independientes en el espacio de soluciones. Nuestro objetivo al identificarlas en este punto del diseño es poder particionar la solución en unidades independientes basadas en las 'costuras de concurrencia' naturales del sistema. Este tipo de división el trabajo facilita conceptualmente los problemas de tratar con la concurrencia, ya que las hebras de ejecución independientes se pueden tratar por separado, excepto en aquellos casos en los que comparten clases pasivas subyacentes.

En general, se debe considerar el uso de una clase activa siempre que existan concurrencias y conflictos de concurrencia en el dominio del problema. Se debe utilizar una clase activa para representar un objeto concurrente externo o una actividad concurrente dentro del sistema. Esto permite supervisar y controlar las actividades concurrentes.

Otra opción natural es utilizar clases activas como representaciones internas de dispositivos físicos externos que están conectados a un sistema, ya que esas entidades físicas son concurrentes inherentemente. Estas clases de "controlador de dispositivo" sirven no sólo para supervisar y controlar los dispositivos físicos correspondientes, sino que también aíslan el resto del sistema de las características específicas de los dispositivos. Esto significa que puede que no afecte al resto del sistema aunque evolucione la tecnología subyacente en los dispositivos.

Otro lugar común de utilización de las clases activas es para representar actividades concurrentes lógicas. Una actividad lógica representa un "objeto" concurrente conceptual como, por ejemplo, una transacción financiera o una llamada de teléfono. A pesar de que no se manifiesten directamente como entidades físicas (aunque tienen lugar en el mundo físico), a menudo hay razones para tratarlas como tales. Por ejemplo, puede que sea necesario detener temporalmente una determinada transacción financiera para evitar un conflicto de concurrencia o puede que sea necesario terminarla anormalmente debido a anomalías del sistema. Como estos objetos conceptuales se deben manipular como una unidad, se recomienda representarlos como objetos con interfaces propias que proporcionan las capacidades funcionales correspondientes.

Un ejemplo concreto de este tipo de objeto conceptual es un controlador de objeto activo. Su objetivo es gestionar de forma continua uno o varios objetos activos. Normalmente, esto implica cambiar cada objeto al estado operativo deseado; mantenerlo en ese estado ante distintas interrupciones como, por ejemplo, anomalías parciales; y sincronizar su operación con la operación de otros objetos. Estos controladores de objetos activos a menudo evolucionan a partir objetos de control identificados durante Tarea: Análisis de caso de uso .

Debido a su capacidad de resolver conflictos de concurrencia de forma sencilla y elegante, las clases activas también son útiles como guardianes de recursos compartidos. En este caso, uno o más recursos que necesitan varias actividades concurrentes se encapsulan dentro de una clase activa. Gracias a la semántica de exclusión mutua incorporada, los guardianes protegen estos recursos automáticamente de los conflictos de concurrencia.

En los sistemas en tiempo real, se deben utilizar cápsulas en lugar de clases activas: cuando identifique la necesidad de una clase activa de acuerdo con la heurística descrita anteriormente, sustitúyala por una cápsula.

Identificar subsistemas. Cuando la clase de análisis es compleja, por ejemplo, si parece que personifica comportamientos que no pueden ser responsabilidad de una única clase que actúe sola, la clase de análisis se debe correlacionar con un subsistema de diseño. El subsistema de diseño se utiliza para encapsular las colaboraciones de modo que los clientes del subsistema puedan ignorar por completo el diseño interno del subsistema, incluso cuando utilicen los servicios que ofrece el subsistema.

Un subsistema está modelado como un componente UML, que tiene sólo interfaces como elementos públicos. Las interfaces proporcionan una capa de encapsulación, lo que permite mantener oculto el diseño interno del subsistema de otros elementos de modelo. El subsistema de concepto se utiliza para distinguirlo de los paquetes, que son contenedores sin semántica de elementos de modelo.

La decisión de crear un subsistema a partir de un conjunto de clases de análisis de colaboración se basa ampliamente en si la colaboración la puede desarrollar de forma independiente, actualmente o en el futuro, otro equipo de diseño. Si las colaboraciones se pueden contener completamente en un paquete junto con las clases de colaboración, un subsistema puede proporcionar un formato de encapsulación más eficaz que el que ofrece un simple paquete. El contenido y las colaboraciones de un subsistema se aíslan por completo detrás de una o más interfaces, de modo que el cliente del subsistema sólo depende de la interfaz. Así, el diseñador del subsistema está aislado por completo de las dependencias externas; el diseñador (o el equipo de diseño) debe especificar el modo en el que se ha realizado la interfaz, pero puede cambiar libremente el diseño del subsistema interno sin que afecte a las dependencias externas. En sistemas grandes con equipos de gran independencia, este nivel de desacoplamiento combinado con la imposición de la arquitectura que ofrecen las interfaces formales constituye un argumento convincente para la elección de subsistemas mejor que paquetes simples. Consulte el apartado Directriz de producto de trabajo: Subsistemas de diseño para obtener más información sobre los factores que afectan a la elección de utilizar subsistemas como elementos de diseño.

Identificar interfaces de subsistema
Objetivo Identificar los elementos de diseño que formalizan las costuras en el sistema. 

Las interfaces definen un conjunto de operaciones que realiza algún clasificador. En el modelo de diseño, las interfaces se utilizan principalmente para definir las interfaces de los subsistemas. Esto no significa que no se puedan utilizar también para las clases, pero para una única clase normalmente es suficiente definir operaciones públicas en la clase que, de hecho, definen su 'interfaz'. Las interfaces son importantes para los subsistemas ya que permiten la separación de la declaración del comportamiento (la interfaz) de la realización del comportamiento (las clases específicas dentro del subsistema que realizan la interfaz). Este desacoplamiento ofrece una forma de aumentar la independencia de los equipos de desarrollo que trabajan en las distintas partes del sistema, a la vez que se mantienen definiciones precisas de los 'contratos' entre las distintas partes.

Para cada subsistema, identifique un conjunto de interfaces candidatas. Utilizando las colaboraciones agrupadas identificadas en el paso anterior, identifique la responsabilidad que se 'activa' cuando se inicia la colaboración. A continuación, se perfecciona esta responsabilidad determinando qué información debe proporcionar el 'cliente' y qué información se devuelve cuando finaliza la colaboración; estos conjuntos de información se convierten en el valor de retorno y los parámetros de entrada y salida de prototipo de la operación que realizará el subsistema. Defina un nombre para esta operación, utilizando los convenios de denominación definidos en  Producto de trabajo: Directrices específicas del proyecto. Repita este paso hasta que se hayan definido todas las operaciones que realizará el subsistema.

A continuación, agrupe las operaciones según las responsabilidades relacionadas. Es preferible grupos pequeños a grupos grandes, ya que es más probable que exista un conjunto coherente de responsabilidades comunes si hay menos operaciones en el grupo. Tenga en cuenta también la reutilización; busque similitudes que faciliten la identificación de la funcionalidad reutilizable relacionada. Al mismo tiempo, no invierta demasiado tiempo intentando encontrar la agrupación de responsabilidades ideal; recuerde que esta es sólo una agrupación inicial y que en la fase de elaboración se realizarán perfeccionamientos iterativos.

Busque similitudes entre las interfaces. Desde el conjunto candidato de interfaces, busque nombres, responsabilidades y operaciones que sean similares. Si existen las mismas operaciones en varias interfaces, refactorice las interfaces, extrayendo las operaciones comunes a una nueva interfaz. Asegúrese de buscar también en las interfaces existentes y reutilizarlas siempre que sea posible. El objetivo es mantener la coherencia de las interfaces y eliminar las operaciones redundantes. De esta forma, las interfaces serán más fáciles de entender y evolucionarán mejor con el tiempo.

Defina dependencias de interfaces. Los parámetros y el valor de retorno de cada operación de interfaz tendrán cada uno un tipo concreto: deben realizar una determinada interfaz o deben ser instancias de un tipo de datos simple. En aquellos casos en los que los parámetros son objetos que realizan una determinada interfaz, defina relaciones de dependencia entre la interfaz y las interfaces de las que depende. La definición de dependencias entre interfaces proporciona información de acoplamiento útil al arquitecto de software, ya que las dependencias de interfaz definen las dependencias primarias entre los elementos del modelo de diseño.

Correlacione las interfaces con los subsistemas. Una vez identificadas las interfaces, cree asociaciones de realización entre el subsistema y las interfaces que realiza. Una realización del subsistema a una interfaz indica que hay uno o varios elementos dentro del subsistema que realizan operaciones de la interfaz. Posteriormente, cuando se diseñe el subsistema, estas realizaciones de subsistema-interfaz se perfeccionarán, y el diseñador del subsistema especificará qué elementos específicos del subsistema realizan las operaciones de la interfaz. Estas realizaciones perfeccionadas sólo son visibles para el diseñador del subsistema; desde el punto de vista del cliente del subsistema, sólo está visible la realización del subsistema-interfaz.

Defina el comportamiento especificado por las interfaces. Las interfaces definen a menudo una máquina de estado implícita para los elementos que realizan la interfaz. Si las operaciones de la interfaz se deben invocar en un orden concreto (por ejemplo, si la conexión de la base datos se debe abrir antes para poder utilizarla), se debe definir una máquina de estado que ilustre los estados visibles (o inferidos) públicamente a los que debe dar soporte todo elemento de diseño que realiza la interfaz. Esta máquina de estado ayudará al usuario de la interfaz a entender mejor la interfaz, y ayudará al diseñador de los elementos que realizan la interfaz a proporcionar el comportamiento correcto para su elemento.

Empaquete las interfaces. Las interfaces son propiedad del arquitecto de software; los cambios en las interfaces son siempre arquitectónicamente significativos. Para gestionarlas, las interfaces se deben agrupar en uno o varios paquetes propiedad del arquitecto de software. Si cada interfaz la realiza un único subsistema, las interfaces se pueden colocar en el mismo paquete con el subsistema. Si las interfaces las realizan más de un subsistema, se colocarán en un paquete aparte propiedad del arquitecto de software. Esto permite gestionar y controlar las interfaces de forma independiente de los subsistemas.

Identificar protocolos de cápsula

Objetivo

Identificar los elementos de diseño que formalizan las costuras en el sistema (sólo para el diseño RT).

Los protocolos son parecidos a las interfaces en sistemas dirigidos por sucesos: identifican el 'contrato' entre las cápsulas definiendo un conjunto de coincidencia de señales que se utilizan para comunicarse entre hebras de control independientes. Mientras que las interfaces se utilizan principalmente para definir la mensajería síncrona utilizando un modelo de invocación de llamada de función, los protocolos se utilizan principalmente para definir la comunicación asíncrona utilizando una mensajería basada en señales. Los protocolos permiten la separación de la declaración del comportamiento (el conjunto de señales) de la realización del comportamiento (los elementos dentro del subsistema que realizan la interfaz). Este desacoplamiento ofrece una forma de aumentar la independencia de los equipos de desarrollo que trabajan en las distintas partes del sistema, a la vez que se mantienen definiciones precisas de los 'contratos' entre las distintas partes.

Para cada cápsula, identifique un conjunto de señales de entrada y salida. Utilizando las colaboraciones agrupadas identificadas en los pasos anteriores, identifique la responsabilidad que se 'activa' cuando se inicia la colaboración. A continuación, se perfecciona esta responsabilidad determinando qué información debe proporcionar el 'cliente' y qué información se devuelve cuando finaliza la colaboración; estos conjuntos de información se convierten en el valor de retorno y los parámetros de entrada de prototipo de una señal que realizará la cápsula a través de uno de sus puertos. Defina un nombre para esta señal, utilizando los convenios de denominación definidos en  Producto de trabajo: Directrices específicas del proyecto. Repita este paso hasta que calidadlas señales que realizará la cápsula.

A continuación, agrupe las señales según las responsabilidades relacionadas. Es preferible grupos pequeños a grupos grandes, ya que es más probable que exista un conjunto coherente de responsabilidades comunes si hay menos señales en el grupo. Tenga en cuenta también la reutilización; busque similitudes que faciliten la identificación de la funcionalidad reutilizable relacionada. Al mismo tiempo, no invierta demasiado tiempo intentando encontrar la agrupación de responsabilidades ideal; recuerde que esta es sólo una agrupación inicial y que en la fase de elaboración se realizarán perfeccionamientos iterativos. Proporcione al protocolo un nombre significativo, que describa el rol que desempeña el protocolo en las colaboraciones de cápsulas.

Busque similitudes entre los protocolos. Desde el conjunto candidato de protocolos, busque nombres, responsabilidades y señales que sean similares. Si existen las mismas señales en varios protocolos, refactorice los protocolos, extrayendo las señales comunes a una nueva interfaz. Asegúrese de buscar también en los protocolos existentes y reutilizarlos siempre que sea posible. El objetivo es mantener la coherencia de los protocolos y eliminar las señales redundantes. De esta forma, los protocolos serán más fáciles de entender y evolucionarán mejor con el tiempo.

Correlacione los protocolos con las cápsulas. Una vez identificados los protocolos, cree puertos en las cápsulas que realizan los protocolos. Los puertos de las cápsulas definen sus 'interfaces', el comportamiento que se puede solicitar desde la cápsula. Posteriormente, cuando se diseñe la cápsula, la máquina de estado de la cápsula describirá el comportamiento especificado por los puertos.

Defina el comportamiento especificado por los protocolos. Los protocolos definen a menudo una máquina de estado implícita para los elementos que realizan la interfaz. Si las señales de entrada de la interfaz se deben recibir en un orden concreto (por ejemplo, si se debe recibir la señal 'sistema-preparado' para que se pueda recibir una determinada señal de error), se debe definir una máquina de estado que ilustre los estados visibles (o inferidos) públicamente a los que debe dar soporte todo elemento de diseño que realiza el protocolo. Esta máquina de estado ayudará al usuario de las cápsulas que realizan el protocolo a entender mejor su comportamiento, y ayudará al diseñador de las cápsulas a proporcionar el comportamiento correcto para su elemento.

Empaquete los protocolos. Los protocolos son propiedad del arquitecto de software; los cambios en los protocolos son siempre arquitectónicamente significativos. Para gestionarlos, los protocolos se deben agrupar en uno o varios paquetes propiedad del arquitecto de software. Esto permite gestionar y controlar los protocolos de forma independiente de las cápsulas que realizan los protocolos.


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