• No se han encontrado resultados

PARTE I. MARCO TEÓRICO

4. EL PROCESO UNIFICADO DE DESARROLLO DE SOFTWARE

4.3. DISEÑO DE LA SOLUCIÓN

De igual forma que en el modelo de análisis, el modelo de diseño también define clasificadores –en este caso, se definen clases, subsistemas e interfaces–, relaciones entre estos clasificadores, y colaboraciones que llevan a cabo los casos de uso (las realizaciones de los casos de uso). Sin embargo, los elementos definidos en el modelo de análisis son más conceptuales, mientras que el modelo de diseño es más “físico” por naturaleza, sus elementos se adaptan al entorno de la implementación.

Puede hacerse la traza de una realización de caso de uso en el modelo de análisis a partir de una realización de caso de uso en el modelo de diseño (figura 13):

Modelo de casos de uso

«trace» Modelo de análisis Realización de caso de uso - análisis Modelo de diseño «trace» Realización de caso de uso - diseño Caso de uso

Figura 13. Realizaciones de caso de uso en diferentes modelos

Las realizaciones de caso de uso en los diferentes modelos sirven para propósitos distintos. Cuando se definen clases de análisis la intención es proporcionar una comprensión precisa y detallada de los requisitos, mediante un modelo de análisis genérico respecto al diseño (aplicable a varios diseños); son clases independientes de la implementación. En cambio,

cuando se diseñan esas clases de análisis, todas ellas especifican y hacer surgir clases de diseño más refinadas que se adaptan al entorno de implementación; se obtiene un modelo de diseño no genérico, específico para una implementación (basada en un lenguaje de programación específico).

Por tanto, una entrada esencial en el diseño es el resultado del análisis, que impone una estructura que interesa conservar lo más fielmente posible cuando se de forma al sistema. En concreto, los propósitos del diseño son (Jacobson et al., 2000):

• Adquirir una comprensión en profundidad de los aspectos relacionados con los requisitos no funcionales y restricciones relacionadas con los lenguajes de programación, componentes reutilizables, sistemas operativos, tecnologías de distribución y concurrencia, tecnologías de interfaz de usuario, tecnologías de gestión de transacciones, etc.

• Crear una entrada apropiada y un punto de partida para actividades de implementación subsiguientes capturando los requisitos o subsistemas individuales, interfaces y clases.

• Ser capaces de descomponer los trabajos de implementación en partes más manejables que puedan ser llevadas a cabo por diferentes equipos de desarrollo, teniendo en cuenta la posible concurrencia. Esto resulta útil en los casos en los que la descomposición no puede ser hecha basándose en los resultados de la captura de requisitos (incluyendo el modelo de casos de uso) o análisis (incluyendo el modelo de análisis). Un ejemplo podría ser aquellos casos en los que la implementación de estos resultados no es directa.

• Capturar las interfaces entre subsistemas, considerando las dependencias entre estos subsistemas. Las interfaces proporcionadas por un subsistema definen operaciones que son accesibles desde fuera del mismo.

• Ser capaces de visualizar y reflexionar sobre el diseño utilizando una notación común.

• Crear una abstracción de la implementación del sistema, en el sentido de que la implementación es un refinamiento directo del diseño, que rellena lo existente sin

cambiar la estructura. Esto permite la utilización de tecnologías como la generación de código y la ingeniería de ida y vuelta entre el diseño y la implementación.

Mientras que el modelo de análisis representa el sistema en términos de objetos que expertos en el dominio conocen, el modelo de diseño representa el mismo sistema pero con un nivel de abstracción cercano al código fuente.

El diseño es el centro de atención al final de la fase de elaboración y el comienzo de las iteraciones de construcción. Esto contribuye a una arquitectura estable y sólida y a crear un plano del modelo de implementación. Más tarde, durante la fase de construcción, cuando la arquitectura es estable y los requisitos están bien entendidos, el centro de atención se desplaza a la implementación (implementación del diseño). No obstante, el modelo de diseño está muy cercano al de implementación. Esto es especialmente cierto en la ingeniería de ida y vuelta, donde el modelo de diseño se puede utilizar para visualizar la implementación y para soportar las técnicas de programación gráfica. La ingeniería de ida y vuelta es un concepto que representa la combinación de la ingeniería directa y la ingeniería inversa. La ingeniería directa permite la transformación de un modelo en código

a través de su traducción a un determinado lenguaje de implementación, mientras que la ingeniería inversa transforma el código en un modelo a través de su traducción desde un determinado lenguaje de implementación.

El modelo de diseño es un modelo de objetos que describe la relación física de los casos de uso centrándose en cómo los requisitos funcionales y no funcionales, junto con otras restricciones relacionadas con el entorno de implementación, tienen impacto en el sistema a considerar. Además, el modelo de diseño sirve de abstracción de la implementación del sistema y es, de ese modo, utilizada como una entrada fundamental de las actividades de implementación.

El modelo de diseño se representa por un sistema de diseño que denota el subsistema de nivel más alto del modelo. La utilización de otros subsistemas es una forma de organización del modelo de diseño en porciones más manejables. En este sentido, el modelo de diseño se puede ver como una jerarquía de subsistemas de diseño que contienen clases de diseño, realizaciones de caso de uso-diseño e interfaces (las interfaces se utilizan para especificar las operaciones que proporcionan las clases y los subsistemas del diseño).

Los casos de uso son realizados por las clases de diseño y sus objetos en el modelo de diseño. Esto se representa por colaboraciones en el modelo de diseño, que denotan la realización de caso de uso – diseño. La realización de caso de uso – diseño es diferente de

la realización de casos de uso – análisis (véase figura 13). Esta última describe cómo se

realiza un caso de uso en términos de interacción entre objetos del análisis, mientras que la primera representa cómo se realiza un caso de uso en términos de interacción entre objetos del diseño.

El diseño de una clase incluye el mantenimiento del diseño en sí mismo y los siguientes aspectos de éste (Jacobson et al., 2000):

• Sus operaciones.

• Sus atributos

• Las relaciones en las que participa.

• Sus métodos (que realizan sus operaciones).

• Los estados impuestos.

• Sus dependencias con cualquier mecanismo de diseño genérico.

• Los requisitos relevantes a su implementación.

• La correcta realización de cualquier interfaz requerida.

Las operaciones que las clases de diseño van a necesitar se describen utilizando la sintaxis de los lenguajes de programación. Esto incluye especificar la visibilidad de cada operación (por ejemplo, public, protected, private en Java o C++). Las operaciones de las clases de

diseño necesitan soportar todos los roles que las clases desempeñan en las diferentes realizaciones de casos de uso. En otras palabras, la clase debe implementar aquellas operaciones que pueda emplear cualquiera de las realizaciones de casos de uso en la que participa. Por ejemplo, la clase Factura puede participar en la realización de los casos de

uso Pagar Factura, Enviar Aviso y Enviar Factura al Comprador. Cada una de estas

realizaciones de casos de uso utiliza objetos Factura de forma diferente, leyendo y/o

cambiando el estado de dichos objetos a su manera; para ello, acuden a operaciones adecuadas implementadas en la clase Factura, por ejemplo, el uso de los métodos crear( ), enviar( ), planificar( ) y cerrar( ). Así, el caso de uso Enviar Factura al Comprador crea y

envía facturas, el caso de uso Pagar Factura planifica facturas, y así cada una de las

realizaciones de caso de uso que empleen dicha clase.

Las operaciones utilizadas por los objetos de una clase, de hecho, podrían estar recogidas en una interfaz o en una clase abstracta que declare métodos virtuales (código vacío). Las clases que accedan a dichos métodos (vía herencia o vía vínculo a interfaz), desarrollarán una implementación particular de los mismos. Como se dijo en su momento, este planteamiento favorece la extensión de la funcionalidad del sistema.

Los atributos asociados a las clases de diseño también se describen utilizando la sintaxis del lenguaje de programación. Un atributo especifica una propiedad de una clase de diseño y está a menudo implicado y es requerido por las operaciones de la clase.

Al igual que el modelo de análisis, el modelo de diseño puede ser descrito gráficamente mediante diagramas de clases (vista estática) y mediante diagramas de interacción (vista dinámica). Ejemplos de diagramas de clases de diseño fueron mostrados en su momento (figura 3, apartado 2.3.5; figura 5, apartado 3.2). Además, mediante el uso de diagramas de estados y diagramas de actividades se puede modelar el flujo de un objeto o instancia de una clase concreta conforme cambia de estado a partir de la ejecución de determinadas operaciones asociadas a la clase. Veamos, por ejemplo, a partir de un diagrama de estados, cómo cambia de estado un objeto concreto de la clase Factura (figura 14).

Figura 14. Un diagrama de estados para la clase Factura

(Fuente: Jacobson et al., 2000)

Las relaciones en las que puede participar una clase se clasifican básicamente en cuatro tipos importantes: dependencias, generalizaciones, realizaciones y asociaciones (Booch et al., 1999). Las dependencias indican que un elemento (una clase, en este caso) utiliza a

otro. Las generalizaciones (herencia) conectan clases generales con otras más

especializadas en lo que se conoce como relaciones subclase/superclase. Las realizaciones,

en este contexto, especifican la relación entre una interfaz y una clase. Una interfaz es una colección de operaciones que sirven para declarar un servicio de una clase o de un componente, como un contrato que debe llevar a cabo (realizar) esa clase o componente. Las asociaciones son relaciones estructurales entre instancias, que especifican que los

objetos de un elemento están conectados con los objetos de otros. Dada una asociación simple entre dos clases, se puede navegar (transmitir mensajes) desde un objeto de una clase hasta un objeto de la otra clase, y viceversa. En el apartado 5, dedicado a UML, se detalla la notación gráfica de cada tipo de relación, con sus variantes.

Podemos esbozar inicialmente algunas clases de diseño a partir de las clases significativas para la arquitectura del modelo de análisis. Además, se pueden utilizar las relaciones entre estas clases de análisis para identificar un conjunto tentativo de relaciones entre las correspondientes clases de diseño. En proyectos de pequeña magnitud, posiblemente la correspondencia entre la estructura de análisis y la estructura de diseño sea prácticamente directa, mediante la constitución de trazas de una sola clase de diseño a la clase de análisis correspondiente, y la adaptación de los atributos y operaciones de dicha clase de análisis a un entorno de implementación específico.

Por otro lado, si el nivel de abstracción asumido en el modelo de análisis es muy alto (como ocurrirá seguramente en proyectos de gran magnitud), probablemente se derivarán varias clases de diseño a partir de una sola clase de análisis.

En consecuencia, el abordar proyectos de pequeña magnitud, nos lleva incluso a plantear la posibilidad de establecer una traza del modelo de diseño directamente al modelo de casos de uso. Cuando el número de elementos del sistema es reducido, puede que un análisis detallado de los mismos en un modelo de análisis sea innecesario; sobre todo si se tiene en cuenta que el modelo de casos de uso del sistema ya integra un análisis del contexto del problema, y que en esta situación, probablemente el modelo de análisis no contribuya de una manera significativa al desarrollo del diseño de la solución. Por tanto, en este caso quizás sea más cómodo para el desarrollador conectar el modelo de casos de uso directamente con el modelo de diseño.

De hecho, dentro del Proceso Unificado, el modelo de análisis es considerado un modelo

opcional, al igual que el modelo de procesos (Booch et al., 1999, Apéndice C). En este sentido, Booch et al. (1999, p. 86) afirman que si se modela una simple aplicación que se ejecuta en una única máquina, se podría necesitar sólo el siguiente grupo de diagramas (en cada una de las vistas de la figura 1, apartado 2.2):

Vista de casos de uso: Diagramas de casos de uso.

Vista de diseño: Diagramas de clases (para modelado estructural). Diagramas de interacción (para modelado del comportamiento).

Vista de procesos: No se requiere. Vista de implementación: No se requiere. Vista de despliegue: No se requiere.

La vista de procesos de un sistema comprende los hilos y procesos que forman los mecanismos de sincronización y concurrencia del sistema. Esta vista cubre principalmente el funcionamiento, capacidad de crecimiento y rendimiento del sistema. Con UML, los aspectos estáticos y dinámicos de esta vista se capturan en el mismo tipo de diagramas que la vista de diseño, pero con énfasis en las clases activas que encarnan estos hilos y procesos. Las clases activas representan procesos que organizan el trabajo de las otras clases (no activas). Una clase activa es una clase cuyos objetos tienen uno o más procesos o hilos de ejecución y por lo tanto pueden dar origen a actividades de control. Un proceso

se define como un flujo de control pesado que puede ejecutarse concurrentemente con otros procesos. Un hilo (thread), en cambio, es un flujo de control ligero que se puede

ejecutar concurrentemente con otros hilos en el mismo proceso. Por tanto, una clase activa es igual que una clase, excepto en que sus objetos representan elementos cuyo comportamiento es concurrente con otros elementos.

La vista de implementación, como proyección del modelo de implementación (véase

siguiente subapartado), comprende los componentes y archivos que se utilizan para ensamblar y hacer disponible el sistema físico. Con UML, los aspectos estáticos de esta vista se capturan en los diagramas de componentes; los aspectos dinámicos se capturan en los diagramas de interacción, diagramas de estados y diagramas de actividades.

La vista de despliegue contiene los nodos que forman la topología hardware sobre la que se ejecuta el sistema. Esta vista se preocupa principalmente de la distribución, entrega e instalación de las partes que constituyen el sistema físico. Cada nodo representa un recurso de computación, normalmente un procesador o un dispositivo hardware similar. Además, los nodos poseen relaciones que representan medios de comunicación entre ellos, tales como Internet, intranet, bus, y similares. Con UML, los aspectos estáticos de esta vista se

capturan en los diagramas de despliegue; los aspectos dinámicos de esta vista se capturan en los diagramas de interacción, diagramas de estados y diagramas de actividades.