Sie sind auf Seite 1von 74

Ingeniería del Software-UML 1

INGENIERÍA DEL SOFTWARE. UML.

PROFESOR:

Javier Macías del Campo.


Despacho N-317.
e-mail: javier.macias@uah.es

IMPORTANTE:

Este documento es de uso exclusivo para alumnos de la asignatura de “Ingeniería del Software” de
las titulaciones I.T.I.G. e Ingeniería en Electrónica de la Universidad de Alcalá.

TEMARIO:

UML
Introducción.
Diagrama de Casos de uso.
Diagrama de Secuencia.
Diagrama de Colaboración.
Diagrama de Estados.
Diagrama de Actividades.
Diagrama de Clases.
Diagrama de Objetos.
Diagrama de Componentes.
Diagrama de Despliegue.
Proceso Unificado de Rational.
Generación de código.

BIBLIOGRAFÍA:

• Material entregado en CD (presentaciones, estándar UML y otros documentos).

• Ayuda de Rational Rose. En especial, para la generación de código se puede consultar en Ayuda
Contenido Rose C++ las secciones Concepts y Reference Model-to-Code correspondences.

• Apuntes de C++ de “Estructura de Datos”. Entre otra, contiene información sobre plantillas (templates),
constructores de copia y la STL (Standard Template Library).

• Libro “Mastering UML with Rational Rose”. Wendy Boggs y Michael Boggs. Ed. Sybex, 1999. Es muy
fácil de seguir, aunque sólo cubre Rose 98. Tiene cerca de mil páginas porque contiene muchas pantallas,
aunque se repiten demasiado ciertas operaciones. Es caro.

• Libro “El Lenguaje Unificado de Modelado”. Grady Booch, James Rumbaugh e Ivar Jacobson. Ed.
Addison Wesley, 1999. A pesar de definirse en la portada como libro introductorio, es necesario tener
unos conocimientos básicos de UML antes de intentar leer este libro.
Ingeniería del Software-UML 2

Pág.
ÍNDICE.

Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

Diagrama de Casos de uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

Diagramas de Interacción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

Diagrama de Secuencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

Diagrama de Colaboración . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

Diagrama de Estados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

Diagrama de Actividades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

Diagrama de Clases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

Diagrama de Objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

Diagramas de Implementación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

Diagrama de Componentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

Diagrama de Despliegue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

Proceso Unificado de Rational . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

Generación de código . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

PRÓLOGO.

Este documento constituye una introducción a UML 1. Sin embargo, debido a que en la asignatura
“Laboratorio de Ingeniería del Software” se utiliza la herramienta Rational Rose, en algunos momentos se
realizan particularizaciones a dicha herramienta. También se verá una breve introducción a la metodología
“Proceso Unificado de Rational”.

A partir de los diagramas de clases y componentes es factible generar código (al menos un esqueleto
del mismo). El último tema se dedicará a la generación de código mediante Rational Rose, para lo cual se
usará C++ como lenguaje de implementación.

1
El estándar UML es muy amplio, por lo que aquí no se verán todas sus particularidades. Se recomienda consultar la
bibliografía si se desean completar los conocimientos o profundizar en algún aspecto concreto.
Ingeniería del Software-UML 3

INTRODUCCIÓN.

¿QUÉ ES UML?
Son las siglas de Lenguaje de Modela do Unificado (Unified Modeling Language). UML es un
lenguaje gráfico para visualizar, especificar, construir y documentar los artefactos de sistemas con una
componente software significativa. Como ejemplos de artefactos de un sistema tenemos el código fuente, el
diseño, los requisitos, la arquitectura y los prototipos, entre otros.

UML es un lenguaje de modelado orientado a objetos. Se debe recalcar que UML no es una
metodología, aunque proporciona técnicas que pueden ser usadas en conjunto o parcialmente en metodologías,
fundamentalmente aquellas destinadas al desarrollo orientados a objetos, como el Proceso Unificado de
Rational o Métrica V.3 (aunque Métrica V.3 es una metodología mixta que también permite el desarrollo
estructurado).

Al ser UML un lenguaje, está compuesto de una sintaxis (reglas que indican cómo ensamblar los
componentes de su vocabulario para crear expresiones) y una semántica (reglas que indican el significado de
las expresiones). Ambos aspectos serán tratados aquí.

LA IMPORTANCIA DE MODELAR .
Los sistemas, ya sean naturales o artificiales, son difíciles de comprender. Esto es debido a que en
general son bastante complejos y la mente humana sólo puede manejar 7 ±2 “elementos” de forma simultánea.
Sin embargo, es posible representar y entender un sistema usando la técnica del modelado, esto es,
construyendo modelos del sistema.

Un modelo es una simplificación de la realidad creada para comprender mejor un sistema; un modelo
es una abstracción que captura la parte esencial de los sistemas a un determinado nivel de detalle.

Los modelos:
- Ayudan a visualizar cómo es o queremos que sea un sistema.
- Permiten especificar la estructura o componentes del sistema.
- Son una guía para la construcción y mantenimiento de los sistemas.
- Permiten experimentar múltiples soluciones.
- Reducen los riesgos por errores.
- Documentan las decisiones adoptadas.

Existe una serie de principios básicos en el modelado de sistemas, entre los que destacan los
siguientes:
- Elegir el modelo más adecuado para cada sistema. Por ejemplo, si se va a realizar un desarrollo
orientado a objetos, se debería utilizar un modelado orientado a objetos.
- Cuando así convenga, el sistema se podrá ver a diferentes niveles de detalle. Para eso, se
utilizarán modelos más o menos refinados.
- Debe representar fielmente la realidad.
- Un modelo único no suele ser suficiente para modelar un sistema, siendo necesarios varios
modelos utilizando diversos puntos de vista.
- Los modelos deben ser semánticamente consistentes. Por ejemplo, si estamos modelando una casa,
los tabiques deben ser los mismos en el plano eléctrico, de la fontanería, calefacción, etc.
Ingeniería del Software-UML 4

UML utiliza modelos orientados a objetos. Un modelo orientado a objetos es una representación de un
sistema a partir de los objetos u entidades que lo constituyen, con unos atributos y operaciones asociados, que
interactúan con otros objetos para conseguir conjuntamente satisfacer los objetivos del sistema.

Existen varios tipos de modelos: gráficos, matemáticos, físicos, etc. Por ejemplo, la maqueta de un
automóvil es un modelo físico del “sistema” automóvil que podría utilizarse para estudiar su aerodinámica en
el túnel de viento.

UML es un lenguaje de modelado visual, esto es, utiliza modelos gráficos para la representación de
sistemas. Los seres humanos son criaturas visuales (de ahí el dicho “más vale una imagen que mil palabras”).
Es más fácil entender información visual que información no visual (por ejemplo, es más fácil entender un
recorrido dibujado en un mapa que entender las instrucciones en texto equivalentes). UML utiliza diagramas
para representar los modelos.

HISTORIA DE UML.
Aunque el nacimiento de los lenguajes orientados a objetos tuvo lugar en los años 70 con la aparición
de Smalltalk, fue en los 80 cuando empezó realmente su despegue y expansión.

Los métodos de modelado existentes a principios de los 80 estaban adaptados para la construcción de
programas en lenguajes pertenecientes al paradigma de la programación estructurada. Sin embargo, estos
métodos no se adaptaban correctamente al desarrollo de programas orientados a objetos.

A mediados de los 80 empezaron a aparecer métodos de modelado orientados a objetos. Durante el


período comprendido de 1989 a 1994, el número de métodos se incrementó de menos de 10 a más de 50,
enfatizando cada uno de ellos en ciertos aspectos y sin proporcionar ninguno de ellos una solución
suficientemente general. Durante este tiempo, los métodos se fueron perfeccionado a la vez que el paradigma
orientado a objetos se consolidaba.

De la experiencia acumulada, aparecieron nuevas generaciones de métodos, entre los que destacan:
- Método de Booch, de Grady Booch.
- OOSE (Object Oriented Software Engineering), de Ivar Jacobson.
- OMT (Object Modeling Technique), de James Rumbaugh.

Éstos eran métodos completos, pero cada uno de ellos tenía sus puntos fuertes y débiles. Según
evolucionaban, se iban tomando ideas los unos de los otros, pareciéndose cada vez más. Finalmente, deciden
unirse los creadores de dichos métodos (fundando “ Rational Software Corporation”) al objeto de unificar sus
métodos, naciendo UML, cuyos objetivos eran:
- Modelar sistemas, desde el concepto hasta ejecutables, utilizando técnicas orientadas a objetos.
- Válido para cualquier sistema, ya fuera pequeño, grande, crítico o complejo.
- Utilizable tanto por personas como por máquinas.

Paulatinamente, fueron apareciendo versiones:


- 0.8 en 1995.
- 1.0 en enero de 1997.
- 1.1 en noviembre de 1997.
- 1.2 en junio de 1998 (revisión editorial, sin cambios significativos a nivel técnico).
- 1.3 en noviembre de 1999.

La versión actual de UML es la 1.3, que es un estándar del OMG ( Object Management Group). Se
lleva cierto tiempo trabajando ya en la versión 1.4, una revisión menor de la actual que aparecerá a corto
Ingeniería del Software-UML 5

plazo (principios del año 2001). Se espera una revisión importante del estándar hacia el año 2002, con la
publicación de la versión 2.0.

VISIÓN GENERAL DEUML.


El vocabulario de UML se compone de:
- Elementos. Son abstracciones de algún componente o aspecto del sistema modelado.
- Relaciones. Ligan elementos entre sí.
- Diagramas. Agrupan elementos y relaciones.

Elementos.
Hay cuatro tipos de elementos:
- Estructurales.
- De comportamiento.
- De agrupación.
- De anotación.

Los elementos estructurales representan partes materiales o conceptuales del sistema. Los elementos
estructurales principales de UML son la clase, la interfaz, la colaboración, el caso de uso, los componentes y
los nodos. Más adelante se verá su representación y significado.
Los elementos de comportamiento son las partes dinámicas de los modelos UML. Los elementos de
comportamiento básico son las interacciones (que comprende un conjunto de mensajes intercambiados entre un
conjunto de objetos, dentro de un contexto particular, para alcanzar un propósito específico) y la máquina de
estados (que especifica las secuencias de estados por las que pasa un objeto o una interacción durante su vida
en respuesta a eventos, junto con sus reacciones a estos eventos).

Mensaje Estado

Los elementos de agrupación de UML son los paquetes, y sirven para organizar otros elementos de los
modelos UML (pudiendo incluir incluso otros paquetes). Un paquete es un mecanismo conceptual de propósito
general para organizar elementos en grupos. Por ejemplo, se pueden incluir en un paquete varias clases y luego
asignar ese paquete a un componente (con lo que, realmente, lo que estamos asignado al componente son todas
las clases que el paquete incluye). Gráficamente, un paquete se visualiza como una carpeta, incluyendo su
nombre y, a veces, su contenido:

Paquete

Los elementos de anotación son partes explicativas de los modelos UML. Son comentarios que se
pueden aplicar para describir, clarificar o hacer observaciones sobre cualquier elemento de un modelo. Aunque
la mayoría de herramientas del tipo Rose permiten añadir un texto (o incluso un fichero o una dirección web)
comentando o documentando cada elemento, con las anotaciones este texto se ve de forma explícita en el
diagrama, de forma que resalta a primera vista.
Ingeniería del Software-UML 6

El símbolo utilizado para una anotación es el siguiente:

Aquí se escribe el
texto de la nota.

Relaciones.
Los tipos fundamentales de relaciones son los siguientes:
- Generalización.
- Asociación.
- Realización.
- Dependencia.

La relación de generalización conecta a elementos vinculados por una relación padre/hijo


(generalización/especialización). Gráficamente viene dada por una línea acabada en punta de flecha vacía que
va del elemento especializado (el hijo) al general (el padre).

La relación de asociación es una relación estructural entre dos elementos. Gráficamente se muestra
como una línea que conecta ambos elementos (de forma opcional puede también acabar en punta de flecha
para indicar la dirección de navegabilidad o incluir ciertos adornos que aumentan su expresividad):

La relación de realización es una relación semántica entre clasificadores, en donde un clasificador


especifica un contrato que otro clasificador garantiza que cumplirá. Es la relación que hay entre una
especificación y su implementación. Poner ejemplo Gráficamente viene dada por una línea discontinua que
acabada en punta de flecha vacía y va del elemento que cumple el contrato al elemento que lo especifica:

La relación de dependencia es una relación semántica entre dos elementos, en la cual un elemento
requiere la presencia de otro para su implementación o funcionamiento. Un cambio en el elemento requerido
(el independiente) puede afectar al del otro elemento (el dependiente). Se representa como una línea
discontinua entre el elemento dependiente y el independiente acabada en punta de flecha que señala al elemento
independiente (esto es, el elemento dependiente indica el elemento del que depende):
Ingeniería del Software-UML 7

Diagramas.

Los diagramas se utilizan para visualizar un sistema desde diferentes perspectivas, de forma que un
diagrama es una proyección de un sistema. Para todos los sistemas, excepto los más triviales, un diagrama
representa una vista resumida de los elementos que constituyen un sistema. En UML existen nueve tipos de
diagramas, agrupables según la siguiente clasificación:

- Diagramas de comportamiento (modelan cómo se comporta el sistema).


1. Diagrama de casos de uso.
- Diagramas de interacción (muestran cómo interaccionan entre sí objetos de un sistema).
2. Diagrama de secuencia.
3. Diagrama de colaboración.
4. Diagrama de estados.
5. Diagrama de actividades.

- Diagramas estructurales (modelan algún aspecto de la estructura del sistema).


6. Diagrama de clases.
7. Diagrama de objetos.
- Diagramas de implementación (muestran aspectos relacionados con la implementación).
8. Diagrama de componentes
9. Diagrama de despliegue.

El diagrama de casos de uso muestra actores y formas en que ést os pueden utilizar el sistema.

El diagrama de secuencia muestra cómo se mandan mensajes los actores y objetos de un sistema a lo
largo del tiempo.

El diagrama de colaboración muestra las relaciones existentes entre actores y objetos y los mensajes
enviados entre ellos.

El diagrama de estados muestra los diferentes estados por los que puede pasar un objeto, así como las
transiciones y eventos asociadas.

El diagrama de actividades muestra el flujo de control entre objetos.

El diagrama de clases muestra la estructura de clases de un sistema, incluyendo las relaciones que
pudieran existir entre ellas. Es el más común de los diagramas en el modelado de sistemas orientados a
objetos.

El diagrama de objetos muestra un conjunto de objetos y sus relaciones (enla ces) en un instante
determinado. Equivale a una instancia de un diagrama de clases (o una parte del mismo) y se utiliza
generalmente para documentar estructuras de datos complejas.

El diagrama de componentes muestra cómo se organizan los elementos constit uyentes del sistema
(código fuente, ejecutables, etc.) y las dependencias existentes entre ellos.

El diagrama de despliegue muestra la configuración de nodos de procesamiento en tiempo de ejecución


y los componentes que residen en ellos.
Ingeniería del Software-UML 8

MECANISMOS DE EXTENSIBILIDAD .
UML proporciona una serie de mecanismos de extensibilidad que permiten aumentar la capacidad
expresiva del mismo. Estos mecanismos son:
- Estereotipos.
- Valores etiquetados.
- Restricciones.

Un estereotipo extiende el vocabulario de UML, permitiendo crear nuevos tipos de bloques de


construcción que se deriven de los existentes. Los nombres de los estereotipos se muestran encerrándolos entre
los símbolos « y » 2. Por ejemplo, podríamos crear el estereotipo «tabla» para representar una tabla. Este
estereotipo, añadido al símbolo de una clase, indicaría que nos encontramos ante un nuevo elemento (en este
caso, el estereotipo nos indica que dicho elemento representa una tabla).

Un valor etiquetado extiende las propiedades de un bloque de construcci ón, permitiendo añadir nueva
información en la especificación de ese elemento. Los valores etiquetados se muestran encerrándolos entre
llaves. Por ejemplo, se podría mostrar el autor de una determinada clase mediante un valor etiquetado añadido
al símbolo que representa la clase: {autor = J. Macías}.

Una restricción extiende la semántica de un bloque de construcción de UML, permitiendo añadir


nuevas reglas o modificar las existentes. Las restricciones se muestran encerrándolas entre llaves. Por ejemplo,
la restricción {xor} aplicada a un grupo de asociaciones se utiliza para indicar que sólo se debe instanciar una
relación de las varias posibles.

DIAGRAMA DE CASOS DE USO3.

Los diagramas de casos de uso representan la funcionalidad del sistema tal como l a ven los usuarios.
En los diagramas de casos de uso se muestran las diferentes formas posibles de utilización de un sistema. Los
diagramas de casos de uso permiten visualizar el comportamiento de un sistema, de forma que los usuarios
puedan comprender cómo se utiliza ese elemento y de forma que los desarrolladores puedan implementarlo.

En un diagrama de casos de uso importa qué hace el sistema (qué proporciona), no cómo lo hace.

Los elementos principales que aparecen en los diagramas de casos de uso son:
- Actores.
- Casos de uso.
- Relaciones.

2
A los símbolos « y » se les denomina guillements y son símbolos simples. Esto significa que, por ejemplo, el símbolo
« no está compuesto de dos símbolos menor seguidos, esto es <<, sino que existe el símbolo especial «.
3
Para más información, se puede consultar el libro “Writing Effective Use Cases”, A. Cockburn, ed. Addison-Wesley
(oct., 2000).
Ingeniería del Software-UML 9

Veamos, para empezar, un diagrama de casos de uso para un cajero automático:

Transferir Fondos

Empleado Banca
Ingresar
Cambiar PIN

Cliente

Disponer Realizar Pago

Sistema de
Crédito
Ver Saldos

En este diagrama se pueden identificar los actores (Cliente, Empleado de Banca y Sistema de Crédito)
que son los agentes externos que interactúan con el cajero automático, los casos de uso (Transferir Fondos,
Cambiar PIN, Realizar Pago, Ver Saldos, Disponer e Ingresar) que son las funcionalidades que el cajero
proporciona y, por último, las relaciones entre actores y casos de uso (las líneas que van entre actores y casos
de uso).

Opcionalmente, se puede añadir al diagrama un rectángulo que representa los límites del sistema
representado (marca el límite entre el sistema físico objeto del modelado y los actores que interactúan con
dicho sistema), como se puede ver en el ejemplo siguiente:

Realizar Llamada

Red Telefónica

Recibir Llamada

Usuario

Usar Agenda
Teléfono móvil

Los diagramas de casos de uso son una herramienta de comunicación efectiva entre clientes y
desarrolladores. Ayudan a capturar los requerimientos del sistema (que será una cuestión básica para todo el
desarrollo posterior), para validar el diseño contra ellos, para obtener los casos de prueba (el sistema obtenido
debe proporcionar todas las funcionalidades especificadas en los casos de uso) e incluso como base para la
documentación de usuario.

Los diagramas de caso de uso se centran en la interacción entre los usuarios y los sistemas, y no en las
actividades internas que tengan lugar en dicho sistema. Son una herramienta muy general que permite
Ingeniería del Software-UML 10

especificar las reglas de un negocio 4. No están basados en la teoría de orientación a objetos y pueden usarse
tanto en procesos de desarrollo orientados a objetos como a desarrollos estructurados u otros.

La creación de los casos de uso necesita de la participación de los usuarios (expertos en e l tema a
modelar) para su construcción y validación, además de analistas. La creación de los diagramas es un proceso
de descubrimiento, que suele requerir varias sesiones.

De forma resumida, se puede decir que los diagramas de caso de uso:


- Representan una forma estructurada, pero informal, de expresar los requerimientos funcionales.
- Son fáciles de entender, tanto por el cliente como por el desarrollador.
- Son un mecanismo para obtener el consenso en la visión del sistema y sus objetivos entre clientes
y desarrolladores.

ACTORES .
Un actor5 es un rol o conjunto homogéneo de roles que un usuario (persona o máquina) desempeña
respecto al sistema. Son, por tanto, agentes externos al sistema y que interactúan con él. Gráficamente, un
actor se simboliza mediante un hombre “de alambre”, figurando debajo de él el nombre:

Cliente
Un actor representa una clase, a la cual pueden pertenecer uno o más elementos (o, de forma
equivalente, instancias). Por ejemplo, instancias del actor cliente serían José, Luis, Fernando, etc.

Hay tres tipos principales de actores: usuarios del sistema, otros sistemas que interactúan con el
sistema que está siendo modelado y el tiempo:
- El primer tipo de actor corresponde a personas físicas o usuarios. No se deben usar nombres de
personas ya que, si tomamos por ejemplo el caso del cajero automático, una misma persona puede
desempeñar en un momento dado el rol de empleado de banca (porque sea un empleado del banco)
y en otro instante el rol de cliente (ya que además puede ser cliente del banco y usar el cajero para,
por ejemplo, sacar dinero).
- El segundo tipo de actor es otro sistema. Nuestro sistema puede interaccionar con otros sistemas,
que son externos y están fuera de nuestro control (esto es, nos vienen ya dados y es nuestro
sistema el que se debe adaptar para comunicarse con ellos).
- El tercer tipo de actor es el tiempo. El tiempo es un actor cuando el paso de un cierto tiempo
dispara algún evento en el sistema. Por ejemplo, a medianoche el sistema podría realizar un
proceso de control del estado del cajero. Debido a que el tiempo está fuera de nuestro control, es
un actor.

Representar un actor del tipo sistema externo o tiempo como un hombre de alambre puede resultar
poco claro. Una opción mejor puede ser asignar un estereotipo a los sistemas externos (por ejemplo «sistema»)
y utilizar un nuevo icono para su representación, por ejemplo la imagen de un miniordenador o un servidor. De
forma similar se puede hacer con el tiempo.

Los actores se pueden clasificar como primarios o secundarios, de pendiendo si participan en las
funciones principales del sistema (pertenecientes al ámbito del negocio, como Realizar Llamada en el caso del

4
Las reglas o procesos de negocio son procesos realizados en el seno de una cierta organización o empresa.
5
El nombre “actor” con el que se denominó a este elemento en UML no fue acertado, ya que lo que realmente
representa el elemento UML es un rol (o conjunto homogéneo de roles), y un actor del mundo real puede (y de hecho
normalmente lo hace) representar varios roles dispares.
Ingeniería del Software-UML 11

teléfono móvil) o funciones secundarias en el mismo (pertenecientes al ámbito del mantenimiento del sistema,
como copias de seguridad, arrancada y parada del sistema o administración de la base de datos).

También es posible clasificarlos como activos o pasivos, dependiendo de si inician los casos de uso o
no.

A la hora de encontrar los actores de un sistema, existen dos enfoques diferentes, ambos importantes y
legítimos, correspondientes a dos niveles de abstracción: el modelo de sistemas de información y el modelo de
negocios.

Por ejemplo, pensemos que deseamos modelar el caso de uso consistente en realizar el pedido de un
coche en un concesionario. Podríamos suponer que el actor es el vendedor o que el actor es el cliente.

En el primer caso, estamos a nivel de abstracción del modelo de sistemas de información, ya que
modelamos una solución específica organizativa y tecnológica (el vendedor es el encargado de interactuar con
el sistema).

En el segundo caso, estamos a un mayor nivel de abstracción, ya que lo que realmente modelamos es
una regla del negocio (el cliente es quién encarga el coche). Desde este punto de vista, el vendedor no es más
que un intermediario, el interface del sistema con el que interactúa el actor.

Cuando se elige el modelo de sistemas de información estamos especificando ya una enfoque definido.
Sin embargo, al usar el modelo de negocio dejamos abierta la puerta a diferentes enfoques. Por ejemplo, se
podría optar durante la fase de análisis y diseño que el cliente pudiera encargar el coche tanto personalmente a
través del vendedor, por teléfono, por correo electrónico o vía Web (simplemente, representarían diferentes
interfaces para el cliente para realizar una misma tarea: realizar el pedido de un coche).

Nota:

El uso de interfaces humano o automáticos tiene sus pros y sus contras, tal y como se puede
ver en la siguiente tabla:

Ventajas Inconvenientes

Interfaz humano Flexibilidad (adaptable al actor). Coste. Ausencia de uniformidad.

Interfaz automático Coste. Uniformidad. Rigidez.

CASOS DE USO .
Un caso de uso representa una funcionalidad que el sistema proporciona o, de forma equivalente , un
caso de uso muestra una forma en la que alguien podría utilizar el sistema. Un caso de uso representa una
secuencia de transacciones en un sistema cuyo objetivo es proporcionar un resultado mensurable de valor para
el actor del sistema. Gráficamente, un caso de uso se representa mediante una elipse, con el nombre del caso
escrito dentro o debajo:

Ingresar

Para nombrar los casos de uso se utiliza un verbo o una frase que empiece por un verbo activo, que
indique el objetivo o funcionalidad del caso.

Los casos de uso pueden describir funcionalidades a diferentes niveles: sistema, subsistemas y
componentes (clases). A cualquiera de estos niveles, los casos de uso definirán el comportamiento del elemento
Ingeniería del Software-UML 12

que describen, sin revelar su estructura interna. Se debe precisar que si se utilizan casos de uso para describir
clases, los actores que participarán serán en general otras clases o subsistemas.

El nivel más importante es el que describe las funcionalidades del sistema. Pertenece al nivel de
abstracción del negocio, y es útil tanto para clientes como desarrolladores. Se les denomina casos esenciales o
abstractos. Desde este punto de vista, se puede redefinir caso de uso como “una única actividad discreta,
completa, significativa y bien definida de interés para un usuario externo que desempeña un rol o roles
específicos con relación al sistema, englobando las posibles acciones del usuario y las responsabilidades del
sistema durante el desarrollo de la actividad, descritas de una forma abstracta, independiente de la tecnología y
de la posible implementación, usando un lenguaje perteneciente al dominio de la aplicación y, por tanto,
fácilmente entendible por los usuarios”. Se debe tener en cuenta que, a este nivel, un caso de uso puede tener
una duración finita cualquiera, ya sea unos segundos, varios días o incluso meses.

A nivel de subsistemas se suelen tratar con operaciones atómicas o CRUD ( Create, Read, Update,
Delete). Este nivel suele ser poco útil para los clientes, ya que está más enfocado al diseño, centándose en las
interacciones con la base de datos en lugar de interacciones entre el actor y los sistemas. A este tipo de casos
de uso se les denomina a veces como reales, a diferencia de los anteriores (esenciales, abstractos o ideales).

Los casos de uso se deben documentar. Dicha documentación debe contener una descripción del caso
de uso y el flujo de eventos del mismo (la secuencia de acciones, incluyendo variantes, que un sistema puede
ejecutar interactuando con los actores para proporcionar la funcionalidad indicada en el caso de uso).
Opcionalmente, puede incluir precondiciones y/o postcondiciones. El texto usado en la documentación de los
casos de uso debe estar basado en el lenguaje del negocio a modelar. No se recomienda detallar excesivamente
ni utilizar pseudocódigo para especificar el flujo de eventos, ya que podría restringir las soluciones a tomar.

Las secciones que podrán aparecer en un caso de uso son, por tanto:
- Descripción. Describe, generalmente de forma breve, lo que hace el caso de uso.
- Precondiciones. Son las condiciones que se deben cumplir antes de poder utilizar el caso de uso.
- Postcondiciones. Son las condiciones que se cumplirán después de haber finalizado la ejecución
del caso de uso.
- Flujo de eventos primario (o base) y alternativo(s). El flujo de eventos describe, paso a paso, lo
que sucede en el caso de uso (no cómo sucede). El flujo primario describe la situación normal
(debe ser además el primer flujo descrito al crearlo). El flujo o flujos alternativos documentan qué
ocurre en situaciones variantes o anormales (por ejemplo, que el cliente no dispusiera de suficiente
saldo). Para especificar flujos de eventos se puede, además de texto, usar otras técnicas, como los
diagramas de actividad o de estado.

Si se utiliza texto para especificar el flujo de eventos, se recomienda seguir el estilo del siguiente
ejemplo, que representa el flujo de eventos para el caso de uso de “obtención de ayuda para un problema
específico” de una empresa de ventas:

Acciones del usuario Responsabilidades del sistema

1. Identificación como cliente.


2. Presentación de las opciones de ayuda.
3. Seleccionar una opción de ayuda.
4. Pedir descripción del problema.
5. Describir el problema.
6. Ofrecer posibles soluciones.
Ingeniería del Software-UML 13

RELACIONES .
Hay cuatro tipos de relaciones que pueden aparecer en un diagrama de casos de uso.

Relación de comunicación.

Es el tipo más normal de relaciones y tiene lugar entre un caso de uso y un actor. Gráficamente es una
línea, a la que se puede añadir una punta de flecha para indicar quién inicia la comunicación.

Por ejemplo:

Realizar Pago
Cliente Sistema de
Crédito

En este caso, el actor “Cliente” se comunica con el caso de uso “Realizar Pago”, siendo el actor quien
inicia la comunicación. Además, el caso de uso “Realizar Pago” se comunica con el actor “Sistema de
Crédito”.

Todos los casos de uso deben ser iniciados por un actor (a excepción de los casos de uso que
extienden el comportamiento o están incluidos en otro caso de uso, tal y como se verá más adelante).

Relación de inclusión6.

La relación de inclusión en un caso de uso “A” de caso de uso “B” (esto es, la flecha va de “A” a
“B”) indica que el caso de uso “A” contiene el comportamiento indicado por “B”. El lugar o lugares donde
dicho comportamiento se incluye debe especificarse en el flujo de eventos de “A”.

La relación de inclusión se muestra gráficamente como una relación de dependencia con el estereotipo
«include». Por ejemplo:

«include»
Disponer

Autentificar Cliente
«include»

Realizar Pago

En este fragmento se puede ver que tanto el caso de uso “Disponer” como “Realizar Pago” incluyen el
caso de uso “Autentificar Cliente”. Esta factorización permite especificar de una sola vez un comportamiento
común a varios casos de uso.

6
En versiones anteriores de UML a esta relación se le denominaba de uso (uses), sin embargo su nombre se cambio
por la de incluye (include) ya que el anterior nombre daba a entender una semántica que no se correspondía con la
real.
Ingeniería del Software-UML 14

Las relaciones de inclusión también se pueden utilizar para detallar un caso de uso complejo que
proporcione varias subfuncionalidades, de manera que visualmente se puedan apreciar de una forma más fácil
en qué consiste dicho caso, sin tener que consultar la descripción del mismo.

La relación de inclusión indica que un caso de uso va a usar siempre la funcionalidad pro porcionada
por otro caso.

Relación de extensión.

Una relación de extensión de un caso de uso “A” a un caso de uso “B” indica que comportamiento del
caso de uso “B” puede ser incrementado con el comportamiento del caso de uso “A”, sujeto a determinadas
condiciones, que pueden ser especificadas en la extensión o en el caso de uso.

La relación de inclusión se muestra gráficamente como una relación de dependencia con el estereotipo
«extend». Por ejemplo:

«extend» Solicitar cobro revertido

Realizar Llamada Llamada a Cobro Revertido

En este ejemplo, la funcionalidad “Llamada a Cob ro Revertido” extiende la funcionalidad “Realizar


Llamada”. Esto ocurriría cuando solicitáramos, por alguna razón, llamar a cobro revertido

Relación de generalización.

Puede ser entre actores o entre casos de uso.

Entre actores:

La relación de generalización entre actores se utiliza cuando varios actores tienen características
comunes. Gráficamente se muestra como una relación de generalización que va del actor especializado al
genérico. Para los usuarios del teléfono móvil podríamos representar, por ejemplo:

Usuario

Usuario Tarjeta Usuario Contrato

Una generalización de un actor “A” (descendiente) a un actor “B” (ancestro) indica que una instancia
de “A” puede comunicarse con los mismos casos de uso que un actor “B”. Para el caso del ejemplo, un
“Usuario Tarjeta” (o un “Usuario Contrato”) podría comunicarse con los mismos casos de uso que un
“Usuario” y, posiblemente, con otros particulares a él (por ejemplo, un “Usuario Tarjeta” podría comunicarse
con el caso de uso “Recarga Tarjeta”).
Ingeniería del Software-UML 15

Se deben de usar las relaciones de generalizació n entre actores cuando algunos actores tengan en
común parte de sus comportamientos o cuando interese mostrar explícitamente que cualquier especialización
de un tipo de actor actúa de igual forma.

Entre casos de uso:

La relación de generalización entre c asos de uso se utiliza para indicar que un caso de uso es un
refinamiento de otro. Por ejemplo:

Consultar Habitaciones Libres por Consultar Habitaciones


Categoría

Este tipo de relación se utiliza poco y no se debe abusar de ella.

NORMAS PARA CREACIÓN DE UN DIAGRAMA DE CASOS DE USO .


- No modelar la comunicación entre actores, ya que está fuera del ámbito del sistema 7.
- No dibujar flechas entre casos de uso, excepto para relaciones de inclusión, extensión o
generalización.
- Todo caso de uso debe ser iniciado por un actor (excepto los casos de uso incluidos o las
extensiones).
- No se debe representar el flujo de información entre casos de uso. Un caso de uso representa una
funcionalidad o un modo de utilizar el sistema, pero no indica el cómo se implementa esa
funcionalidad. Por tanto, un caso de uso puede representar la introducción de una información y
otro caso de uso el acceso a la misma, sin que exista ninguna comunicación entre ambos casos.
- Es importante que cualquier requerimiento funcional aparezca al menos en un caso de uso, ya que
de otro modo no será implementado.
- Los diagramas de casos de uso deben proporcionar fácilmente una visión de lo que el sistema
proporciona, tanto a los desarrolladores como a los clientes (para casos de uso abstracto). Se debe
usar un número de diagramas adecuado (dependiendo de la complejidad del sistema) con un
número de casos de uso razonable y dependiendo del nivel de detalle de dicha vista en particular.
Además, los nombres de los casos de uso, actores y descripciones deben ser significativos para el
cliente (deben pertenecer al lenguaje del negocio y la organización del cliente).
- Se deben considerar también casos de uso relacionados con el mantenimiento del sistema.
- Se debe elegir con cuidado las personas participantes en su creación. Es importante evitar
personas con pensamiento “lineal” (al estilo de los programadores), es decir, personas que intentan
describir todos y cada uno de los pasos y detalles.
- Los diagramas de casos de uso sólo pueden capturar requerimientos funcionales, y a un nivel
relativamente alto. Para capturar otro tipo de requerimientos o detallarlos, se deben usar otras
técnicas.
- No se debe partir del nivel CRUD, ya que aparecerían demasiados casos, a un nivel muy fino y
dificultarían su entendimiento por el cliente. El sistema no existe para leer/escribir en una base de
datos, existe para producir un resultado de valor mensurable para los actores.

7
Para modelar el modo en que las tareas se llevan a cabo en una empresa se podrían utilizar diagramas de flujo de
trabajo (workflow diagram).
Ingeniería del Software-UML 16

- Se debe evitar crear los casos de uso basándose exclusivamente en la interfaz del sistema de
información que ya existiera, si se diera esta situación, ya que en vez de las reglas del negocio (el
qué) podemos estar dando directamente una solución basada en el sistema existente, que pudiera
no ser lo suficientemente buena o flexible.
- Se debe cuidar la granularidad. Los casos de uso abstracto deben capturar lo esencial y no
intentar detallar demasiado, porque esta situación hace caer en el cómo. Sin embargo, una
pequeña descomposición de los casos puede hacerlos más fáciles de comprender y simplificar su
diseño.

EJEMPLO DE UN DIAGRAMA DE CASOS DE USO .

Tomar Productos
Aportar Datos Cliente
«include» Aportar Forma Pago
«include»
«include»

1 n «extend»
Tomar Pedido
Vendedor

Pedir Catálogo

1 n
Proporcionar Crédito El catálogo se
Supervisor enviará al servir el
pedido.

Notas:
- El supervisor es una especialización de vendedor. El supervisor es el único que puede
proporcionar crédito, pero también puede tomar pedidos como cualquier otro vendedor, ya que es
una especialización de éste.
- En el ejemplo se puede ver una forma de utilización de las notas.
- Se ha añadido la multiplicidad en las relaciones de comunicación.
- La condición para la extensión “Pedir Catálogo” estará definida en el caso de uso “Tomar
Pedido” (no se ha mostrado en el diagrama).
- Véase que se ha optado por modelar a nivel de sistema de información (aparece el actor
“vendedor” y no el actor “cliente”).

EJEMPLO DE LA DOCUMENTACIÓN DE UN CASO DE USO .


A continuación, se dará la documentación (resumida) del caso de uso “Sacar” perteneciente al modelo
de casos de uso de un sistema de cajeros automáticos. Para hacerlo más real, se supondrá que el cliente sólo se
identifica una vez (representado por el caso de uso “Validar usuario”), y después podrá hacer una o más
operaciones sin necesidad de volver a identificarse.
Ingeniería del Software-UML 17

Nota: El flujo de eventos primario del caso de uso “Validar usuario” sería:

Acciones del usuario Responsabilidades del sistema


1. Insertar tarjeta en el cajero
2. Leer la tarjeta.
3. Pedir PIN.
4. Introducir PIN.
5. Verificar PIN.
6. Muestra las opciones.

La documentación del caso de uso “Sacar” sería la siguiente:

- Descripción: Permite al cliente obtener una cierta cantidad de dinero en efectivo del cajero
automático.

- Precondiciones: El usuario se ha validado contra el sistema mediante “Validar usuario”.

- Flujo de eventos principal:

Acciones del usuario Responsabilidades del sistema


1. Selecciona opción sacar dinero.
2. Preguntar la cantidad.
3. Introduce la cantidad.
4. Visualizar la cantidad.
5. Confirmar la cantidad
6. Dispensar el efectivo.
7. Muestra opciones.

- Flujos alternativos:
- En el paso 2, el usuario cancela la operación. Se pasa al paso 7.
- En el paso 5, el usuario indica que la cantidad es errónea. Se vuelve al paso 2.
- En el paso 6, si no es posible proporcionar la cantidad requerida, se indica y se vuelve al paso
2.

- Postcondición: La operación, si finaliza con éxito, queda reflejada en la cuenta del usuario.

DIAGRAMAS DE INTERACCIÓN.
Definiciones previas.

Objeto: Es una entidad con límites definidos e identidad propia que encapsula un estado y un
comportamiento. Un objeto es una instancia de una clase.

Clase: La descripción de un conjunto de objetos que comparten los mismos atributos,


operaciones, métodos y semántica.

Atributo: Característica que describe el rango de valores que una instancia de una clase puede
almacenar.
Ingeniería del Software-UML 18

Operación: Es un servicio que puede ser solicitado a un objeto para que se comporte de una
determinada forma.

Método: La implementación de una operación. Esp ecifica el algoritmo o procedimiento asociado


con una operación.

Mensaje: Solicitud de una operación determinada a un objeto concreto.

Notación para la representación de objetos.

Un objeto se representa gráficamente como un rectángulo, dentro del cual se incluye, subrayado, el
nombre del objeto (empezando por letra minúscula), o la clase (empezando por letra mayúscula) a la que
pertenece precedida de dos puntos, o ambos:

Por ejemplo:

ana Objeto de nombre ana (no se especifica


explícitamente la clase a la que pertenece).

: Persona Objeto anónimo de la clase Persona.

luis : Persona Objeto de nombre luis perteneciente a la


clase Persona.

También puede incluirse una sección en la que se mues tren los valores de uno o más atributos, tal y
como se puede ver en el ejemplo siguiente:

Oscar : Persona
Nombre: String = “Oscar”
dni: Integer = 3102427
telefono = 91 555 00 00

Los diagramas de interacción muestran cómo cooperan (interaccionan) un conjunto de objetos para
realizar alguna tarea determinada. Modelan, por tanto, aspectos dinámicos del sistema. Un diagrama de
interacción consta de un conjunto de objetos y sus relaciones (ya sea de forma implícita o explícita), así como
de los mensajes que se envían entre ellos.

Hay dos clases de diagramas de interacción: el diagrama de secuencia y el diagrama de colaboración.


Ambos diagramas son prácticamente equivalentes entre sí, ya que la información subyacente en la que se
basan es la misma, estando la diferencia en que en el diagrama de secuencia lo que se destaca es la ordenación
temporal de los mensajes mientras en los diagramas de colaboración lo que se destaca es la organización
estructural de los objetos que envían y reciben mensajes. Dependiendo de la misión principal a la que se
destine el diagrama, convendrá usar uno u otro, tal y como se verá más adelante.
Ingeniería del Software-UML 19

Una de las aplicaciones más importantes de los diagramas de interacción consiste en el modelado de
escenarios. Un escenario es una secuencia específica de acciones entre objetos que permite mostrar un
comportamiento. Un escenario es, por tanto, una instancia de un flujo de eventos particular de un caso de uso.
Varios diagramas de interacción representando escenarios pertenecientes a distintos flujos de eventos de un
mismo caso de uso (por ejemplo, flujo principal, flujo alternativo 1, flujo alternativo 2, etc.) se suelen agrupar
en un paquete. Cada diagrama de interacción que represente un escenario debe tener al menos un objeto actor
iniciante, que es el estímulo externo que ejecuta alguna funcionalidad. Este objeto actor será una instancia de
un actor perteneciente al diagrama de casos de uso al que pertenece el flujo de eventos.

A la hora de construir un diagrama de interacción, es necesario encontrar los objetos que participan, a
los que se añadirán a continuación los mensajes que se envían. Existen varias técnicas para encontrar objetos.
Una de ellas consiste en analizar los sustantivos que aparezcan en los flujos de eventos o en escenarios
específicos. En general, estos sustantivos se corresponderán con actores, atributos u objetos (serán objetos si
exhiben un comportamiento). Sin embargo, esta técnica no permite descubrir todos los objetos. Habrá
posiblemente que añadir objetos cuya tarea sea controlar 8 a los otros objetos (controlan el desarrollo de los
acontecimientos). También puede ser necesario añadir objetos de entrada/salida, como formularios e informes,
que realizan la tarea de interface entre el usuario y el sistema.

En Rose, un objeto se puede calificar (a través de sus especificaciones) como persistentes ( persistent),
estático (static) o transitorio (transient):
- Persistente: Aquel cuya vida continúa aunque el programa haya terminado. Cuando se vuelva a
ejecutar el programa, el estado del objeto dependerá del estado que tuviera al terminar la ejecución
anterior. Para que esto sea posible, debe ser guardado en un fichero o una base de datos
(almacenamiento permanente) al terminar una ejecución y recuperado al empezar la siguiente.
- Estático: Es aquel que reside en memoria hasta que el programa termina. Esto es debido a que se
trata de un objeto compartido por varios hilos de control o procesos.
- Transitorio: Aquel que permanece en memoria por un espacio de tiempo limitado (por ejemplo,
durante el tiempo o parte del tiempo en que se desarrolla una determinada tarea o flujo de
eventos).

El estándar también proporciona un símbolo para múltiples instancias de un objeto. Esto permite
representar en los diagramas de interacción agrupaciones de objetos como, por ejemplo, listas de objetos. En
general, los mensajes que se mandan a las agrupaciones de objetos constan de una búsqueda más una
operación que se requiere al objeto (o subconjunto de objetos) encontrado. La notación es la siguiente (este
icono sólo puede aparecer en el diagrama de colaboración):

: Persona

Para modelar los mensajes, Rose permite especificar cinco semánticas diferentes de sincronización de
mensajes:

- Simple: El mensaje se ejecuta en un hilo simple de control, por lo que el objeto al que va destinado el
mensaje siempre lo aceptará y de forma inmediata. Es la opción por defecto. Gráficamente se
representa como:

8
Este tipo de objetos, denominados objetos activos, se pueden mostrar en UML regruesando sus bordes para
diferenciarlos del resto de objetos, los pasivos.
Ingeniería del Software-UML 20

- Síncrono: El objeto cliente manda el mensaje y espera hasta que el objeto al que va destinado acepta
el mensaje. Gráficamente se representa como:

- Rechazable (balking): El cliente manda el mensaje y si el objeto al que va destinado no lo acepta, el


cliente abandona el mensaje. Gráficamente se representa como:

- Tiempo límite (timeout): El cliente manda el mensaje y espera como máximo una determinada
cantidad de tiempo. Si el objeto destino no está disponible para recibir el mensaje durante ese periodo,
el cliente abandona el mensaje. Gráficamente se representa como:

- Asíncrono: El cliente manda el mensaje y continua sin esperar confirmación de si el mensaje ha sido
recibido. Gráficamente se representa como:

Rose también permite especificar la frecuencia de los mensajes, calificándolos como aperiódicos
(mandados en un instante cualquiera de forma única o sin una periodicidad; es la opción por defecto) o
periódicos (aquellos que son enviados a intervalos regulares).

Se debe tener en cuenta que, al poner un mensaje en un diagrama de interacción, se está asignando una
responsabilidad al objeto que lo recibe. Por ejemplo, si en un diagrama de interacción se representa un mensaje
de un objeto a al objeto b, es responsabilidad del objeto b aceptar el mensaje y obrar en consecuencia, para lo
cual deberá disponer del método adecuado. Supongamos, por ejemplo, que a manda el mensaje
imprimir(hola.txt) al objeto b; el objeto b debe tener una operación, que normalmente se implementará con un
método denominado imprimir, que trate dicho mensaje (en este caso el comportamiento de b podría consistir
en imprimir el fichero hola.txt que se le ha pasado como parámetro).

Los diagramas de interacción constituyen una piedra angular en el diseño, ya que a través de ellos los
desarrolladores pueden determinar las clases que necesitan (aquellas a las que pertenecen los objetos que
aparecen en ellos), las relaciones entre clases y las operaciones y responsabilidades de cada clase.

Para que el diseño sea consistente, todo objeto de un diagrama de interacción deberá ser mapeado en
algún momento a una clase del diagrama de clases, así como todo mensaje deberá ser mapeado a una
operación (método) de la clase que recibe el mensaje. Además, la persistencia indicada en los diagramas de
interacción debe ser compatible con la persistencia indicada en los diagramas de clase, debiéndose cumplir en
Rose lo siguiente:
- Si la clase se define como persistente en el diagrama de clases, un objeto de dicha clase podrá
calificarse como transitorio, estático o persistente en el diagrama de interacción.
- Si la clase se define como transitoria en el diagrama de clases, un objeto de dicha clase podrá
calificarse como estático o transitorio en el diagrama de interacción.

En Rose, es posible documentar en las especificaciones de un caso de uso los diagramas relacionados
con dicho caso (ya sean de interacción, estado, actividad o clases).

Al ser semánticamente equivalentes los diagramas de secuencia y los de colaboración, es posible pasar
de uno a otro automáticamente. Por ejemplo, en Rose basta crear uno de ellos y pulsando la tecla [F5]
generará el otro.
Ingeniería del Software-UML 21

DIAGRAMA DE SECUENCIA.
Un diagrama de secuencia es un tipo de diagrama de interacción en el cual se destaca el tiempo: los
mensajes entre objetos vienen ordenados explícitamente por el instante en que se envían. Consta de dos ejes.
Generalmente, el eje vertical es el eje del tiempo, transcurriendo éste de arriba a abajo. En el otro eje se
muestran los objetos que participan en la interacción, siendo el primero de ellos el actor que inicia la ejecución
de la secuencia modelada.

De cada objeto parte una línea discon tinua, llamada línea de la vida, que representa la vida del objeto
durante la interacción. Si el objeto existe durante toda la interacción, éste aparecerá en el eje horizontal y su
línea llegará hasta el final del diagrama de secuencia.

Los mensajes parten de la línea de vida del objeto que lo envía hasta la línea de vida del objeto al que
va destinado (excepto en el caso del mensaje de creación, como se verá más adelante). Cada mensaje lleva un
número de secuencia creciente con el tiempo y el nombre de la operación requerida, así como posibles
argumentos que pueden utilizarse como valores de entrada y/o salida.

Usualmente, no se especifica una graduación en el eje del tiempo, aunque podría hacerse para
interacciones que modelen escenarios en tiempo real.

Por ejemplo, vamos a modelar un escenario que muestre una instancia del flujo de eventos primario
del caso de uso “Validar usuario”, en el cual el cliente Luis se identifica ante el cajero automático con su
número secreto (el 4567):

Obsérvese en el diagrama que el mensaje leerNumTarjeta() es un mensaje que el objeto lector se


envía a sí mismo (mensaje reflexivo).
Ingeniería del Software-UML 22

Nota: Se recuerda que el flujo de eventos primario del caso de uso “Validar usuario” era:

Acciones del usuario Responsabilidades del sistema


1. Insertar tarjeta en el cajero
2. Leer la tarjeta.
3. Pedir PIN.
4. Introducir PIN.
5. Verificar PIN.
6. Muestra las opciones.

Un objeto se crea mediante un mensaje de estereotipo «create» que apunta al objeto que se crea. Un
objeto se destruye mediante un mensaje de estereotipo «destroy», dando finalizada la línea de vida con un
aspa. En este diagrama de secuencia simplificado se pueden ver varios ejemplos de creación y destrucción de
objetos:

objetoA objetoB
juan : Cliente

«destroy»

«create
objetoC

«destroy»

«create
objetoE

Apréciese que objetoA y objetoB existen ya cuando empieza el diagrama, aunque objetoB es
destruido, por lo que su línea de la vida está interrumpida en el punto de su destrucción. Por otro lado,
objetoC es creado y destruido durante la interacción, mientras que objetoE es creado y continua existiendo al
final del diagrama (al igual que objetoA).

Opcionalmente, se puede mostrar en los diagramas de secuencia el foco de control, que es un pequeño
rectángulo puesto sobre la línea de la vida que indica qué objeto tiene el control en cada momento (esto es, el
tiempo durante el cual está realizando una acción directa o indirectamente). Véase, por ejemplo, el siguiente
fragmento simplificado:

objeto1 objeto2 objeto3

1: mensaje1
2: mensaje2
Ingeniería del Software-UML 23

En este ejemplo, objeto1 tiene el control al empezar. En un momento determinado, manda un mensaje
(mensaje1) al objeto2 para requerirle una cierta operación. A partir de ese momento, objeto2 tiene también el
control. Para realizar la operación, objeto2 necesita un servicio de objeto3, para lo cual le envía el mensaje2,
teniendo también control el objeto3 desde que recibe el mensaje hasta que finaliza el servicio requerido. De
igual forma, el control de objeto2 finaliza al terminar el servicio que le había requerido objeto1.

Téngase en cuenta que para el caso de un sólo hilo de ejecución, o cuando se debe esperar la
terminación de la operación solicitada por un mensaje para continuar, el que un objeto tenga el foco de control
no significa que se esté “ejecutando” realmente código de dicho objeto durante todo el tiempo de control (ya
que puede estar esperando que termine alguna operación que haya requerido de algún otro objeto).

Aunque, en principio, los diagramas de secuencia están pensados para mostrar un único escenario,
Rose permite mediante los Scritps modelar varios flujos simultáneamente, aunque no se debe abusar de esta
posibilidad, ya que puede complicar en demasía el diagrama. Un ejemplo de script sería:

objeto1 objeto2

IF (condicion= TRUE) THEN


1: mensaje1

ELSE
2: mensaje2

En este ejemplo, si se cumple condicion=TRUE, objeto1 mandará mensaje1 a objeto2, y si no se


cumple, le mandará mensaje2.

Aunque Rose no lo soporta, UML permite añadir la condición delante del mensaje (como por ejemplo
[x>0] mensaje, que indica que se mandará el mensaje sólo si la condición se cumple, esto es, si x es mayor
que cero). También permite desdoblar la línea de vida de un objeto en varias para mostrar flujos alternativos.

REFINAMIENTO .
Los diagramas de secuencia permiten mostrar escenarios de forma que sean comprensibles tanto por
clientes como por desarrolladores.

Sin embargo, una vez que los clientes h an dado su visto bueno a los mismos, se suelen refinar
añadiendo detalles de diseño que serán útiles a los desarrolladores. Por ejemplo, en el diagrama de secuencia
visto anteriormente para validar usuario se debería de refinar e incluir un objeto que fuera el que controlara
todo el proceso en vez de ser un objeto : Pantalla Cajero el que se encargue de la mayoría del control. Esto es
así porque el objeto : Pantalla Cajero es un interface y no conviene que los interfaces se encarguen del control
ya que se volverían muy complicados y heterogéneos, y serían muy sensibles a los cambios.

De forma similar, se suelen crear objetos que manejen transacciones, de forma que se separe la lógica
de la aplicación de la lógica de la base de datos. De esta forma, si la lógica de la base de datos cambia, sólo es
necesario realizar cambios en la clase encargada de las transacciones. Además, este tipo de clases suelen ser
fácilmente reutilizables.
Ingeniería del Software-UML 24

DIAGRAMA DE COLABORACIÓN.
Un diagrama de colaboración es un diagrama que muestra una interacción en el cual se destaca la
organización estructural de los objetos que envían y reciben mensajes. Un diagrama de colaboración muestra
los objetos que intervienen en una relación, los mensajes que se intercambian y las relaciones de comunicación
que hay entre ellos (para que un objeto pueda comunicarse con otro debe existir algún tipo de enlace o link
entre ellos).

Por ejemplo, el diagrama de colaboración equivalente al de secuencia visto en el apartado anterior es


el siguiente:

2: leerNumTarjeta( )

1: aceptarTarjeta( )
lector : Lector
Tarjeta
luis : Cliente

5: introducirPin(4567)

3: inicializarPantalla()
4: pedirPIN()
7: mostrarOperaciones()

6: verificarPIN(4567)
: Pantalla cuentaDeLuis :
Cajero Cuenta

Apréciese que, aunque aquí también aparece el orden de los mensajes, no es fácil seguir la secuencia
de los mismos. Sin embargo se ve claramente qué objetos participan y las relaciones que existen entre ellos, lo
que les hace muy útiles para los desarrolladores. Estos diagramas permiten, por ejemplo, valorar el impacto
que supondría un cambio en una clase.

Hay una diferencia significativa entre los diagramas de secuencia y los de colaboración, y es que en
los de colaboración se pueden añadir explícitamente flujos de datos. Esto se hace mostrando al lado del
mensaje afectado un circulo al que se añade una flecha indicando la dirección del flujo. Si la dirección del
flujo coincide con la del mensaje, se trata de un argumento de entrada. Si no coincide, se trata de un valor de
retorno.

Como ejemplo, aquí se muestra un flujo de datos correspondientes a argumentos de entrada del
mensajeA que objeto1 envía a objeto2:

1: mensajeA()

objeto1 objeto2

En general, sólo se utiliza esta técnica cuando el flujo de datos es grande, como por eje mplo cuando se
pasa una lista.
Ingeniería del Software-UML 25

En los diagramas de colaboración también se pueden asociar estereotipos a los roles de los enlaces,
como por ejemplo «local», que es una restricción que especifica que el objeto al que califica es visible por ser
una variable local al objeto que manda el mensaje. También se pueden añadir restricciones a los objetos que
indiquen su persistencia: {new} si son creados durante la interacción, {destroy} si son destruidos o {transient}
si son creados y destruidos durante la interacción. Por ejemplo:

1: create()

2: mensajeA()

3: destroy()
objeto1 objeto2 {transient}
L

En este caso, objeto2 es accesible a objeto1 por ser local a objeto1 (nótese que en Rose, en vez de
aparecer el estereotipo «local», lo que aparece es una L en el extremo del enlace). El objeto2 es además
transitorio, siendo creado y destruido en la interacción (como de hecho se puede comprobar por los mensajes
que se le envían).

DIAGRAMA DE ESTADOS.
Un diagrama de estados muestra el ciclo de vida de un objeto (aunque también se puede utilizar para
sistemas o subsistemas) desde el momento en que el objeto es creado al momento de su destrucción. Describe
todas las secuencias de estados y acciones por las que un objeto puede pasar durante su vida como reacción a
distintos eventos (como pueden ser los mensajes o señales).

Un estado es una situación particular en la que se exhibe un comportamiento determinado y que está
caracterizado por el valor de uno o más atributos y/o por las relaciones con otros objetos. El estado en que se
encuentre un objeto será por tanto dependiente de su historia anterior.

Por ejemplo, un objeto de tipo fax podría encontrarse en los estados inactivo, transmitiendo o
recibiendo, y en cada uno de estos estados tendría un comportamiento diferente. Un evento, como por ejemplo
pulsar la tecla “Parar” cuando se encuentra en el estado transmitiendo, haría que pasara al estado inactivo.

Los diagramas de estado sólo se suelen realizar para objetos (clases) que tienen un comportamiento
dinámico significativo, esto es, para aquellos que poseen un conjunto significativo de estados. Esto sucede con
los objetos reactivos, que son aquellos cuyo comportamiento viene dirigido por los eventos que recibe. En
estos casos, los diagramas de estado resultan de gran utilidad para los desarrolladores.

Para encontrar clases con un comportamiento dinámico significativo, se puede buscar en primer lugar
aquellos objetos que se comporten de forma diferente según los valores de sus atributos, siendo candidatos,
por ejemplo, las clases que tengan un atributo llamado estado.

También se deben analizar las clases que participen en relaciones en las que aparezca en número cero
en la multiplicidad. Esto significa que dicha relación es opcional y puede que el comportamiento en ese caso
sea muy diferente. Por ejemplo, en una relación entre persona y compañía para la que trabaja, si un objeto
persona tiene una relación con una o más compañías significará que es un empleado. Sin embargo, si no tiene
ninguna relación, podría estar parado, jubilado o incapacitado.
Ingeniería del Software-UML 26

En un diagrama de estados aparecen uno o más estados relacionados entre sí por transiciones. Las
transiciones, en general, serán ocasionadas por algún evento. Por ejemplo, este podría ser el diagrama de
estados de un objeto de la clase Curso:

Abierto
cancelar
Cancelado
fin periodo matrícula
cancelar

Cerrado

fin cuatrimestre

Completado

ESTADO.
Un estado una situación en la vida de un objeto durante la cual se satisface alguna condición, se
realiza alguna actividad o se espera algún evento.

Un estado se representa gráficamente como un rectángulo redondeado. Por ejemplo:

NombreEstado

Dentro del estado (o adjunto en el extremo sup erior izquierdo en ciertas ocasiones) se puede escribir el
nombre del estado, aunque es opcional y se pueden utilizar estados anónimos.

Mientras un objeto está en un estado particular, puede realizar cero, una o más acciones internas. En
este contexto, una acción es una tarea que tiene lugar mientras un objeto se encuentra en un determinado
estado. Estas acciones se muestran en una sección debajo del nombre del estado, con el formato
etiquetaDeAcción/expresiónDeAcción. La etiqueta de acción identifica las circunstancias o eventos bajo los
cuales la expresión de la acción será invocada.

Existen algunas etiquetas de acción reservadas para propósitos especiales y que no pueden ser
utilizadas como nombres de eventos. Estas son:

entry: Indica que la tarea se realiza cuando el objeto entra en dicho estado. Se considera una acción no
interrumpible.

exit: Indica que la tarea se realiza cuando el objeto abandona el estado. Se considera una acción no
interrumpible.

do: Indica que la tarea se realiza mientras el objeto permanezca en el estado en que se encuentra o
hasta que termine dicha tarea. Se considera una acción interrumpible. Dicho de otra forma, cuando un
objeto está en un estado que contiene una acción etiquetada con do, realiza dicha acción (después de
realizar la acción de entrada si la hubiera) hasta que ésta termina o hasta que se abandona dicho
estado por la llegada de un evento adecuado.
Ingeniería del Software-UML 27

include. No se verá aquí.

El resto de las etiquetas se ajustan al siguiente formato:

nombreEvento (listaDeParámetros) [condiciónDeGuarda]

, siendo la lista de parámetros y la condición de guarda (condición que se debe satisfacer para que se produzca
la acción si se recibe el evento) opcionales.

Por ejemplo (nótese que Rose añade a las etiquetas no predefinidas la palabra event):

LeyendoPassword

entry/ poner el eco invisible


exit/ poner eco normal
event carácter(c)/ tratar carácter (c)
event Ayuda/ ^ayuda.mostrarAyuda(password)

Como se puede ver, el estado LeyendoPassword contiene una serie de acciones. En primer lugar, al
entrar (entry) se eliminaría el eco para evitar que los caracteres tecleados sean visibles. Después, si se recibe
un evento carácter (esto es, el usuario introduce un carácter c) se realiza el tratamiento de dicho carácter (esto
es, se añadirá a una cadena para ir formando el password que se teclee). Si el usuario pulsara la tecla definida
como ayuda, el objeto recibirá el evento Ayuda. En ese caso, el objeto manda el mensaje mostrarAyuda al
objeto ayuda, con el argumento password (esto es, se requiere al objeto ayuda que muestre la ayuda sobre el
password). Al salir de este estado (exit) se vuelve a poner el eco para que se puedan ver los caracteres
tecleados. La forma de salir de este estado no se ha especificado, pero puede suponerse que esto ocurre al
pulsar el usuario la tecla [enter] (este sería el evento que produciría el cambio de estado).

En este ejemplo se ha visto cómo especific ar desde un objeto el envío de un mensaje. La sintaxis
general es:

^objeto.mensaje(argumentos)

, siendo los argumentos optativos.

Estados especiales.

Estado inicial. Es un pseudoestado que representa el estado en que se encuentra un objeto cuando es creado
(inicio de la vida del mismo). Debe aparecer obligatoriamente uno y sólo uno en todo diagrama de estados.
Gráficamente se representa:

Estado final. Es un pseudoestado que indica la destrucción del objeto (finalización de la vida del mismo). Es
opcional y se pueden añadir varios estados de fin para simplificar el diagrama y evitar el cruce de líneas.
Gráficamente se representa:
Ingeniería del Software-UML 28

TRANSICIÓN .
Una transición es el paso de un estado a otro. Se muestra gráficamente como una flecha que va del
estado origen al estado destino:

EstadoOrigen

EstadoDestino

Este movimiento puede ser reflexivo, es decir, el estado origen y el estado destino pueden coincidir, tal
y como se muestra a continuación:

Las transiciones pueden incluir especificaciones que indiquen cuándo ocurre la trans ición o qué
acciones se llevarán durante la transición. En caso de no indicarse evento, significa que la transición ocurre
inmediatamente después de satisfechas las posibles acciones entry, do y exit del estado. El formato general de
estas especificaciones es:

evento(listaDeParámetros) [condiciónDeGuarda] / acción

, siendo opcionales todos los componentes.

Un evento es un suceso que ocurre y que puede causar la transición de un estado a otro. La condición
de guarda, si se especifica, debe cumplirse para que la transición sea posible. La acción es un comportamiento
no interrumpible que ocurre como parte de la transición. Nótese que no siempre es posible sustituir esta acción
por una acción interna entry en el estado destino, ya que otras transiciones al estado destino pueden requerir
otras acciones (o ninguna).

Por ejemplo, el siguiente diagrama de estados modela el comportamiento de un robot:

girar( grados ) / realizarGiro(grados)

Inactivo sensorMuro / pitidoAlarma

paro Movimiento

entry/ motorOn
exit/ motorOff
avance[ noTocandoMuro ]

Si partimos del robot en estado inactivo y pulsamos el botón de avance (evento avance), el robot se
pone en movimiento (acción entry) siempre y cuando no esté tocando el muro (condición de guarda de la
transición). Si estamos en movimiento y pulsamos el botón de paro (evento paro) el robot se para (acción exit)
y pasa al estado inactivo. Si, por otro lado, estando en movimiento se activa el sensor de muro, el robot se
para y además suena un pitido de alarma, pasando al estado inactivo. En el estado inactivo puede recibir el
Ingeniería del Software-UML 29

evento girar que haga que gire un número determinado de grados. En este último caso se trata de una
transición reflexiva.

ESTADOS ANIDADOS .
Un estado puede estar compuesto por uno o más subestados. Estos subestados pueden ser disjuntos o,
en el caso de que existan varias regiones o barras de sincronización, concurrentes. A su vez, los subestados
pueden estar compuestos por otros subestados y así sucesivamente.

Por ejemplo, un estado con subestados disjuntos sería el siguiente:

EstadoCompuestoConSubestadosDisjunto

Subestado1 Subestado2

En este caso se ha añadido un estado de inicio y de terminación dentro del estado compuesto, aunque
no es necesario si las transiciones, que entran o salen al estado, llegan o parten de los subestados.

Una de las ventajas de los estados compuestos es que, si todos sus subestados responden a una misma
transición, sólo hace falta ponerla una vez en el estado superior. Esto hace que se reduzcan el número de
líneas en el diagrama, haciéndolo más sencillo. Si tomamos el ejemplo del diagrama de estados de un curso
dado al inicio, podemos definir un nuevo estado, denominado Activo, que englobe a los subestados Abierto y
Cerrado, y agrupar sus transiciones cancelar en una única transición que parte del estado Activo:

Activo

Abierto

fin periodo matrícula


Cerrado

fin cuatrimestre

cancelar

Completado Cancelado

Hay veces que, después de salir de un estado compuesto, interesa volver al mismo subestado en el que
se estaba cuando se salió. Para modelar esta posibilidad, se utilizan estados con memoria. Estos estados se
identifican porque en la esquina inferior izquierda tienen una letra H (de History) dentro de una circunferencia.
Ingeniería del Software-UML 30

Por ejemplo:

Activo

Abierto
dimite profesor

Pendiente de cancelación

fin periodo matrícula

Cerrado asignado nuevo profesor

H
cancelar

fin cuatrimestre

cancelar

Completado Cancelado

En este diagrama, existe un nuevo est ado al que se accede desde el estado Activo cuando dimite el
profesor del curso. Si se asigna un nuevo profesor es posible volver al subestado anterior ( Abierto o Cerrado)
debido a que el superestado tiene historia.

En caso de que los subestados sean a su vez estados compuestos, es también posible volver al último
subestado pertenezca al nivel que pertenezca. Para ello, el superestado que contiene a todos los subestados
debe estar marcado con H* en vez de H.

Para modelar estados compuestos concurrentes se utilizan regiones concurrentes. Estas reguiones se
separan por lineas de puntos en el superestado. Alternativamente a las regiones concurrentes, es posible
utilizar barras de sincronización, como las que se utilizan en el diagrama de actividades, tal y como se verá.

Ejemplo:

Recibiendo clase

Incompleto

hecha hecha
Práctica1 Práctica2

terminado Aprobado
Trabajo

aprobado
Examen

suspendido
Suspenso
Ingeniería del Software-UML 31

En este ejemplo, el estado Incompleto (que a su vez es un subestado de Recibiendo clase) está
compuesto por tres subestados, cada uno de ellos en una región concurrente. Además, el primer subestado está
compuesto por otros dos subestados, en este caso disjuntos ( Práctica1 y Práctica2).

Cuando un estado es compuesto pero su descomposición está en un diagrama aparte, se añade un


pequeño símbolo de composición en su esquina inferior derecha, tal y como se puede ver en el siguiente
ejemplo:

EstadoCompuesto

SIMPLIFICACIÓN DE TRANSICIONES .
Cuando varias transiciones son disparadas por un mismo evento pero con diferente condición de
guarda, es posible utilizar una simplificación para su dibujo. Por ejemplo:

ev [cg1]
Origen Destino1

ev [cg2]
Destino1

ev [cg3]
Destino1

Puede simplificarse como:

[cg1]
Destino1

Origen ev [cg2]
Destino1

[cg3]
Destino1
Ingeniería del Software-UML 32

DIAGRAMA DE ACTIVIDAD9.
Los diagramas de actividad permiten modelar el comportamiento de un sistema o alguno de sus
elementos, mostrando la secuencia de actividades o pasos que tienen lugar para la obtención de un resultado o
la consecución de un determinado objetivo. Opcionalmente, permite mostrar los flujos de información
(objetos) producidos como resultado de una actividad y que serán utilizados posiblemente como entrada por la
actividad siguiente.

Los diagramas de actividad permiten:


- Modelar el flujo de trabajo de un negocio.
- Modelar información procedimental.

Los diagramas de actividad son útiles para describir flujos de evento en los casos de uso, las
actividades que tienen lugar entre un conjunto de objetos (clases) y las operaciones o métodos de las clases.

Es interesante comparar las diferencias entre los diagramas de estados y actividades. La siguiente
tabla es un resumen de ellas:

Diagrama de actividades Diagrama de estados


Centrado en las actividades de un proceso. Centrado en los estados de un objeto o sistema.

Énfasis en el orden procedimental y/o flujo de objetos Énfasis en la reacción al entorno (control por
(control procedimental). eventos).

Veamos a continuación un ejemplo de diagrama de acti vidad, que muestra los diferentes pasos o
actividades y el orden en que se deben realizar para obtener un disco de sistema (MS-DOS):

Formatear
Pistas

Grabar Boot

Crear FAT

Crear
Directorio Raíz

Grabar Fich.
Sistema

9
Actualmente, los diagramas de actividad de UML son un caso especial de una máquina de estados, por lo que
comparte ciertas características comunes con los diagramas de estado. Sin embargo, para evitar confusiones, se ha
evitado intencionadamente el uso de la palabra estado al hablar de las actividades, aunque realmente una actividad es
un estado de acción.
Ingeniería del Software-UML 33

El elemento fundamental de los diagramas de actividad son las actividades. Una actividad representa
la ejecución de una tarea o misión en un flujo de trabajo o la ejecución de una sentencia en un procedimiento,
dependiendo del elemento cuyo comportamiento se esté modelando.

Las actividades pueden describirse usando lenguaje natural, aunque cuando el diagrama mode la
operaciones de una clase suele utilizarse pseudocódigo o incluso el lenguaje de programación en que se vaya a
realizar el desarrollo.

Las actividades se relacionan unas con otras mediante transiciones, que indican el orden en que se
deben de realizar las actividades, empezando desde el punto de inicio del diagrama hasta llegar a un punto
final del mismo.

Una transición se dispara cuando termina de realizarse la actividad de la que parte. También es
posible añadir condiciones de guarda a las transiciones. Esto permite realizar decisiones o bifurcaciones
basadas en las condiciones de las guardas, tal y como muestra el ejemplo siguiente:

Leer PIN

Verificar PIN

[ incorrecto ]

[ correcto ]

Nótese que se utiliza un rombo para simbolizar el punto de decisión y el origen de las bifurcaciones.

Las condiciones de guarda de una decisión deben ser mutuamente excluyentes, y se permite la
condición especial [else] que se cumple cuando no se cumple ninguna de las otras.

Una actividad puede estar compuesta de un conjunto de subactividades, que suelen ser model adas
utilizando un diagrama de actividad propio. Una actividad compuesta no está concluida hasta que no han
concluido sus subactividades. Para indicar que una actividad contiene subactividades, se añade un pequeño
símbolo de composición en su esquina inferior derecha, tal y como se puede ver en el siguiente ejemplo:

Actividad Compuesta
Ingeniería del Software-UML 34

En los diagramas de actividad se puede mostrar la concurrencia y la sincronización utilizando barras


de sincronización, que simbolizan uniones y divisiones en el flujo de control. Por ejemplo:

Conseguir
ingredientes

Calentar aceite Cascar huevos

Batir

Freir

Como se puede ver, la transición que sigue a la actividad Conseguir ingredientes se divide por medio
de una barra de sincronización en dos transiciones que desembocan en las actividades Calentar aceite y
Cascar huevos, que pueden ser realizadas de forma concurrente. Por otro lado, la transición que desemboca en
la actividad Freir parte de una barra de sincronización a la cual llegan dos transiciones. Este es un punto de
sincronización que indica que no se disparará la transición saliente de la barra hasta que no se hayan
disparado las transiciones entrantes (esto es, hasta que no hayan concluido las actividades de las transiciones
entrantes: Calentar aceite y Cascar huevos).
Ingeniería del Software-UML 35

En los diagramas de actividades también se pue den representar calles (swimlanes: calles en el sentido
de las diversas calles paralelas en las que se divide una piscina olímpica). Las calles son elementos
organizativos que permiten asignar las responsabilidades de las acciones a unidades organizacionales de un
negocio o a clases. Por ejemplo, en el siguiente diagrama se modela una compra por correo:

Cliente Ventas Almacén

Solicitar
pedido

Verificar
pedido

Reunir pedido

Enviar pedido

Recoger
pedido

Obsérvese, por ejemplo, que el cliente es el encargado de realizar las actividades Solicitar pedido y
Recoger pedido.
Ingeniería del Software-UML 36

Los diagramas de actividad permiten también mostrar el flujo de información (objetos) entre
actividades, significando un compromiso tanto por parte de la actividad que debe generarla como por la
actividad que debe aceptarla como entrada. Para ello, se dibuja una línea discontinua terminada en flecha que
va desde la actividad que genera como salida al objeto, y otra línea similar que va desde el objeto a la
actividad que sigue y que recibe dicho objeto como entrada. Frecuentemente, un mismo objeto se repite como
entrada y salida en diversas actividades sucesivas, actividades que posiblemente irán modificando el estado del
objeto. En este caso se suele añadir al nombre del objeto el estado en que se encuentra entre corchetes.

Por ejemplo:

Cliente Ventas Almacén

Solicitar
pedido

: Pedido [realizado]

Verificar
pedido

: Pedido [verificado]

Reunir pedido

: Pedido [completado]

Enviar pedido

: Pedido [enviado]

Recoger
pedido

ICONOS DE CONTROL .
Los iconos de control son un mecanismo que, aun no siendo imprescindibles para la construcción de
los diagramas de actividad, resulta una conveniencia que puede ser útil para añadir cierta clase de información
en las transacciones. Existen dos iconos de control, el de envío de señal y el de receptor de señal.
Ingeniería del Software-UML 37

El icono de envío de señal equivale a una transacción que envía una señal. Su símbolo es:

El icono de recepción de señal equivale a un estado de espera, esto es, se produce una espera hasta
que se recibe una señal que dispara la transacción. Su símbolo es:

Optativamente, se puede añadir una línea discontinua acabada en flecha que vaya al objeto que recibe
la señal o que parta desde el que la envía (puede ser el mismo). Por ejemplo:

Levantarse

Encender
caferera

Coger taza : Café

Café hecho

Beber café

DIAGRAMA DE CLASES.
Los diagramas de clases se utilizan para mostrar la estructura estática del sistema modelado. Pueden
contener clases, interfaces, paquetes, relaciones e incluso instancias, como objetos o enlaces. Los diagramas de
clases son una potente herramienta de diseño, ayudando los desarrolladores a planificar y establecer la
arquitectura y estructura del sistema y subsistemas antes de escribir ningún código. Esto permite asegurar que
el sistema está bien diseñado desde el principio. Los diagramas de clases son usados prácticamente en la
totalidad de sistemas en que se utiliza UML para su modelado.

Para sistemas no triviales, se suele usar más de un diagrama de clases. Cuando se utilizan varios
diagramas, cada uno no tiene necesariamente que representar divisiones del modelo subyacente, sino que se
utilizarán según convenga, pudiendo una misma clase aparecer en diagramas diferentes para representar
distintas vistas del modelo.
Ingeniería del Software-UML 38

CLASES.
Las clases son los componentes fundamentales de los diagramas de clases. La notación general para
una clase es un rectángulo dividido en tres secciones, mostrando la primera el nombre de la clase (y
opcionalmente otra información que afecte a la clase), la siguiente los atributos y la última las operaciones.

Por ejemplo:

Punto

coordenadaX
coordenadaY

mostrar()
ocultar()
posicionX()
posicionY()

Tanto la sección de los atributos como la de las operaciones pueden no mostrarse, en cuyo caso
tampoco se mostrará la línea que las separa. Tampoco es necesario visualizar todos y cada uno de los
atributos y operaciones, lo cual puede ser útil para remarcar qué atributos u operaciones son interesantes en
una determinada vista. En este caso, conviene añadir puntos suspensivos (...) al final de la sección de la que se
hayan suprimido atributos u operaciones.

Opcionalmente, se pueden añadir más secciones para indicar otra información, como
responsabilidades de la clase, excepciones que puede generar, eventos que maneja, etc. Tanto éstas como las
secciones de atributos y operaciones pueden contener en primer lugar un nombre que indique la sección de que
se trata. Por ejemplo:

Reservas

operaciones
confirmar()
cancelar()
cambiar()

responsabilidades
facturar clientes sin reserva
ajustarse a habitaciones libres

excepciones
tarjeta de crédito no válida

Rose permite especificar la visibilidad de cada clase. La visibilidad puede ser pública, protegida o
privada (-), con los significados usuales. También es posible otras visibilidades dependientes del lenguaje,
como por ejemplo la visibilidad de implementación o paquete ( implementation) en el caso de C++ que
equivale a una visibilidad pública para el resto de clases definidas en el mismo paquete y privada para las
definidas fuera. También permite especificar otras propiedades, como por ejemplo si los objetos son
persistentes, estáticos o transitorios.
Ingeniería del Software-UML 39

Sección de nombre.

El nombre de la clase se debe poner centrado y en negrita 10, y empezando por letra mayúscula. En
caso de que la clase sea abstracta, el nombre se pondrá además en cursiva. Los nombres de clase deben ser
únicos en su entorno, pudiendo coincidir sus nombres si están definidos en paquetes distintos (ya que sería otro
entorno). Cuando sea necesario, se puede preceder al nombre de la clase por el nombre del paquete donde se
ha definido, como por ejemplo Utilidades::Visualizador.

En caso de especificar un estereotipo para la clase, éste se pondrá encima del nombre de la clase.
También es posible sustituir el rectángulo por un icono asociado a dicho estereotipo o poner dicho icono en el
extremo superior derecho de la sección.

Existen algunos estereotipos muy comunes con iconos preestablecidos:


- «boundary»: Indica que la clase constituye la frontera o interface entre el sistema modelado y el
exterior. Se aplica a formularios, informes, interfaces y similares. Su icono es el siguiente:

- «control»: Indica que la clase es una clase de control que se dedica a labores de coordinación.
Estas clases son fácilmente reconocibles porque de ellas suelen partir muchos mensajes a otras
clases. Su icono es el siguiente:

- «entity»: Contienen la información significativa del sistema (entidades) y generalmente son


guardadas en almacenamiento externo, esto es, son clases persistentes. Por ejemplo, en un sistema
de almacén los clientes, proveedores y productos serían clases a las que se les aplicaría este
estereotipo. Su icono es el siguiente:

En esta sección también se pueden añadir, debajo del nombre, valores etiquetados con alguna
información relativa a la clase. En el siguiente ejemplo se muestra la clase EntradaMaterial, con el
estereotipo «boundary» y valores etiquetados que indican su autor y estado:

«boundary»
EntradaMaterial
{autor = Eva,
estado = comprobado}

Sección de atributos.

En la sección de atributos se muestran todos o parte de los atributos, alineados a la izquierda y


utilizando la siguiente sintaxis:

visibilidad nombre[multiplicidad]:tipo=valorInicial {cadenaPropiedades}

10
Rose no lo visualiza en negrita.
Ingeniería del Software-UML 40

La visibilidad puede ser pública (+), protegida (#), privada (-) o, según el lenguaje, implementación.
Rose permite mostrar la visibilidad mediante los signos o, de forma optativa, con un icono:

Es obligatorio definir la visibilidad para cada atributo, aunque se puede no visualizar.

El nombre del atributo se escribirá con minúsculas, y a continuación se pondrá entre corchetes su
multiplicidad (siendo optativo para el caso habitual de multiplicidad 1). Cuando la multiplicidad es mayor que
uno se puede pensar que equivale a definir un array.

La multiplicidad en UML se indica como uno o más intervalos enteros (en el caso de múltiples
intervalos, se separarán por comas). Cada intervalo tiene el formato límiteInferior..límiteSuperior (cuando el
límite inferior es igual que el superior basta con poner simplemente el número). Para indicar un límite
indefinido, se utiliza el símbolo asterisco (*), aunque Rose utiliza en este caso la letra ene (n).

Ejemplos de multiplicidad son:

0..1 1 0..* 1..6 1..3, 7..10, 15, 19..*

Si un atributo tiene como multiplicidad 0..1, significa que dicho atributo podrá contener un valor o
ninguno (esto es, puede tener un valor nulo, que significa la ausencia de valor). Imagínese que una estación
meteorológica recoge la temperatura a medio día todos los días. Si un día, por cualquier razón, esto no es
posible, el valor de dicho atributo será nulo (ningún valor), que es distinto de 0.0, que sería una temperatura
de 0º. Si tuviéramos que hallar la media de temperaturas, las temperaturas con valor nulo no serían usadas (no
pueden sumar en el numerador ni tampoco cuentan para el denominador).

El tipo será uno de los existentes en el lenguaje de desarrollo, igual que la forma de expresar el valor
inicial. El valor inicial es optativo (en cuyo caso no se incluye el signo igual), pero el tipo es obligatorio,
aunque puede no visualizarse.

La cadena de propiedades es optativa. Por ejemplo, {frozen} indica que un atributo no es modificable.

Cuando la clase dispone de un atributo(s) “clave”, esto es, que el valor de dicho atributo(s) identifica
de forma unívoca a cada objeto de dicha clase, se puede indicar subrayándolo(s).

Los atributos derivados, esto es, los atributos cuyo valor se calcula a partir de otros atributos de la
clase, se marcan con una barra inclinada (/) delante del nombre. Aunque el uso de atributos derivados se debe
evitar, pueden ser recomendables en algunos casos por cuestiones de eficacia (tiempo de ejecución).

Los atributos estáticos, esto es, atributos cuyo valor es compartido por todas las instancias de una
clase, se marcan con el símbolo de dólar ($) delante del nombre.

Es posible agrupar atributos por estereotipo precediéndoles del mismo.

Rose también permite indicar el modo de almacenamiento del atributo, esto es, si será almacenado
por valor o por referencia.

Ejemplos:

Habitacion Punto

-largo: double -coordenada[1..3]


-ancho: double #color
#/area: double -visible
-id: int {frozen} ...
-estado: tEstados = habitable
Ingeniería del Software-UML 41

Apréciese en la clase Habitación que el atributo area es derivado, ya que puede calcularse
multiplicando el valor de los atributos largo y ancho.

Nótese también que en la clase Punto no se han visualizado el tipo de sus atributos, aunque sí estarán
definidos, y sólo se han mostrado parte de los atributos, por lo que se han añadido punto suspensivos para
indicarlo.

Sección de operaciones.

En la sección de operaciones se muestran todas o parte de las operaciones que la clase proporciona,
alineadas a la izquierda y utilizando la siguiente sintaxis:

visibilidad nombre(listaParámetros):tipoRetorno {cadenaPropiedades}

La visibilidad puede ser pública (+), protegida (#), privada (-) o, según el lenguaje, implementación,
de forma similar a la visibilidad de los atributos. Es obligatorio especificarla, aunque puede no visualizarse.

El nombre de la operación se escribirá en minúsculas. En caso de que sea una operación abstracta
(recurso utilizado para implementar polimorfismo), se escribirá en cursiva.

En caso de existir parámetros, estos vendrán separados p or comas y siguiendo la siguiente sintaxis
para cada parámetro:

clase nombre: tipo = valorPorDefecto

La clase puede ser:


- in: Parámetro de entrada. Es el valor por defecto. En C++ se puede indicar con const.
- out: Parámetro de salida.
- inout: Parámetro de entrada y salida.

El nombre indica el nombre del parámetro formal y se escribirá en minúsculas. Después se indica el
tipo del parámetro (que será dependiente del lenguaje) y, en caso de que existiera, el valor por defecto.

A continuación se indica el tipo que retorna la operación (que será dependiente del lenguaje), pudiendo
suprimirse si la operación no devuelve ningún valor (procedimiento).

Por último, se podrá indicar una cadena de propiedades. Aquí se podría indicar, por ejemplo, si una
operación es secuencial {concurrency=sequential} o concurrente {concurrency=concurrent}.

Es posible añadir una nota a una operación para indicar, por ejemplo, su algoritmo o código. Rose
también permite para cada operación especificar, entre otras, las precondiciones, postcondiciones, su
semántica, la cantidad (absoluta o relativa) de memoria necesaria para la operación y el tiempo (absoluto o
relativo) que precisará su ejecución.

Las operaciones se pueden clasificar de la siguiente forma:


- Implementadoras. Proporcionan una funcionalidad básica del negocio. Estas operaciones son las
que responden a los mensajes que aparecen en los diagramas de interacción de alto nivel, que
proceden de los flujos de eventos de los casos de uso y estos a su vez de los requerimientos.
- Administración. Pertenecen a esta categoría los constructores y los destructores, encargados de la
construcción y destrucción de objetos de la clase.
- Acceso. Permiten leer o escribir en los atributos (generalmente, realizando las comprobaciones de
integridad oportunas en el caso de escritura).
Ingeniería del Software-UML 42

- Auxiliares. Operaciones necesarias para que la clase pueda realizar su trabajo, pero que no son
visibles desde el exterior. Este tipo de operaciones aparece como mensajes reflexivos en los
diagramas de interacción (generalmente, en los de bajo nivel).

Las operaciones se pueden agrupar por estereotipo precediéndolas del mismo.

Por ejemplo:

Rectangulo

-p[1..2]: tPunto

«constructor»
+Rectangulo(p1: tPunto, p2: tPunto)
«query»
+area(): double
+perimetro(): double
...
«update»
#mover(delta: tPunto)
#escalar(ratio: double=2.0)
...

Nótese que se ha escrito el nombre del constructor empezando por mayúsculas. Esto ha sido así
porque, presuponiendo que esta clase se implementará en C++, el nombre del constructor debe ser igual que el
nombre de la clase.

Las clases deben estar equilibradas tanto en el número de operaciones como en el de los atributos. Si
una clase tiene muy pocos atributos u operaciones, puede significar (aunque no necesariamente) que se ha
llegado a una descomposición demasiado grande y que sería mejor que fuera absorbida por otra clase con
responsabilidades coherentes. Si una clase tiene demasiados atributos u operaciones, puede significar (aunque
no necesariamente) que tiene demasiadas responsabilidades y que es mejor dividirla en dos o más clases más
sencillas.

RELACIONES .
Una relación es una conexión semántica entre elementos (en nuestro caso, clases o, de forma más
general, entre clasificadores). Existen cuatro tipos principales de relaciones en UML:
- Generalización: Es una relación de especialización.
- Asociación: Es una relación estructural. Existen dos subtipos, la agregación y la composición.
- Realización: Es una relación contractual, en la cual un clasificador especifica un contrato (por
ejemplo, un interface) que otro clasificador garantiza que cumplirá.
- Dependencia: Es una relación de uso.

Desde un punto de vista amplio, la generalización, asociación y realización son también relaciones de
dependencia. Sin embargo, debido a sus características particulares, UML las creó como relaciones
específicas. Conviene modelar antes estas relaciones, ya que las que no se ajusten a ellas serán relaciones de
dependencia.

Hay varias formas de encontrar o diseñar relaciones. Por ejemplo, si en un diagrama de interacción un
objeto a manda un mensaje a un objeto b, habrá una relación entre ellos (típicamente una asociación o una
Ingeniería del Software-UML 43

dependencia). También se deben examinar posibles relaciones todo-parte (que posiblemente se podrán modelar
como relaciones de composición o agregación). Las generalizaciones de pueden crear mediante un proceso
descendente (de arriba a abajo, de la clase más general a la más particular) o ascendente (de abajo a arriba, de
las más particulares a las más generales).

Generalización.

La generalización es una relación taxonómica 11 entre el objeto más general (el padre o superclase) y el
más específico (el hijo o clase descendiente). Gráficamente, se especifica como una línea acabada en flecha
vacía que va del elemento más particular (el hijo) al más general (el padre):

ClasePadre

ClaseHija

La generalización se utiliza para modelar la herencia en los lenguajes orientados a objetos. Una de las
características de la herencia es que permite simplificar la construcción de clases relacionadas, ya que gracias
a ella es posible agrupar las características comunes de un conjunto de clases en una clase padre (superclase)
y hacer que todas ellas hereden de la superclase.

Todos los lenguajes orientados a objetos permiten la herencia simple (una clase puede descender a lo
sumo de otra), aunque algunos lenguajes, como C++, permiten la herencia múltiple (una clase puede descender
de varias clases padre). Aunque la descendencia múltiple puede ser muy conveniente en algunos casos, no se
debe abusar de ella (ya que puede resultar compleja su utilización).

También se debe cuidar el esquema de herencia. Un esquema con demasiados niveles (más de cuatro o
cinco) es usualmente demasiado complicado de entender; un esquema de sólo dos niveles y muy ancho no suele
estar aprovechando la potencia de la herencia (ya que, posiblemente, sería posible extraer características
comunes entre algunas clases del segundo nivel que permitiera la creación de un nuevo nivel).

Por ejemplo:

Vehículo

Terrestre Marítimo Aéreo

Automóvil Camión Globo Aeroplano

Véase que en este ejemplo las clases Vehículo, Terrestre y Aéreo son abstractas, luego no se puede
instanciar ningún objeto de ellas.

11
Clasificación, en el sentido de clasificación de “especies” en ancestras y descendientes.
Ingeniería del Software-UML 44

Si el lenguaje dispusiera de herencia múltiple, podríamos crear clases descendientes de varias clases
padre, como en el siguiente ejemplo:

Terrestre Marítimo

Anfibio

La relación de generalización también puede darse entre paquetes, indicando que un paquete es una
especialización de otro. Los paquetes descendientes heredan los elementos públicos y protegidos del paquete
ancestro, redefiniendo generalmente algunas clases y definiendo otras nuevas. Por ejemplo:

GUI12

WindowsGUI XWindowGUI

Asociación.

Las asociaciones modelan relaciones estructurales entre clases. Una asociación se representa
gráficamente como una línea que conecta las clases relacionadas:

Compañía Persona

Esta asociación significa que la clase Compañía puede acceder a los atributos y operaciones públicas
de la clase Persona y que, de forma similar, la clase Persona puede acceder a los atributos y operaciones
públicas de la clase Compañía.

También se puede restringir la navegabilidad de la asociación, añadiendo una flecha que indique el
sentido de dicha asociación:

Compañía Persona

En este caso, Compañía puede acceder a los atributos y operaciones públicas de la clase Persona,
pero Persona no puede acceder a Compañía.

12
Interface gráfica de usuario.
Ingeniería del Software-UML 45

Una clase puede relacionarse consigo misma, es decir, pueden modelarse asociaciones reflexivas:

Persona

Esta asociación reflexiva podría modelar, por ejemplo, la relación “es familiar directo de”.

Se pueden añadir varios adornos y otros elementos a las as ociaciones que aumentan su expresividad o
completan o restringen su significado:
- Nombre de la asociación. Es un nombre descriptivo que indica la naturaleza de la asociación.
Opcionalmente se puede añadir un pequeño triángulo que indique el sentido en que se debe
interpretar. Por ejemplo:
Trabaja para
Compañía Persona

En este ejemplo, estamos expresando que las personas trabajan para las compañías. Téngase
en cuenta que el sentido del nombre de la asociación no restringe la navegabilidad.
Es posible indicar el estereotipo de la asociación encima del nombre, siendo también posible
indicar una cadena de propiedades a la derecha del nombre o debajo.

- Roles. Se puede indicar el rol que desempeña una o ambas clases en la asociación. Por ejemplo:

Compañía Persona
patronal empleado

- Multiplicidad. Se puede indicar cuántas instancias (objetos) de una clase podrán estar asociados a
una instancia (objeto) de la otra. Por ejemplo:

Compañía Persona
0..* 1..*

En este caso, para una compañía podrán trabajar una o más personas, y una persona podrá
trabajar en cero (que representaría el caso de estar desempleada) o más compañías.

- Calificador. Es un atributo que califica una asociación. Dado un objeto origen y un valor
determinado para el calificador, se obtendrá un objeto destino (si la multiplicidad del destino es a
lo más uno) o un conjunto de objetos destino (si la multiplicidad del destino es muchos). Por
ejemplo:

titular
Banco Nº cuenta: int Persona

0..* 0..1
Ingeniería del Software-UML 46

En este ejemplo, dado un banco y un número de cuenta, obtendremos una persona (el titular de
la cuenta). Téngase en cuenta que el calificador pertenece a la asociación y no es un atributo ni
del banco ni de la persona.
Es significativo el extremo de la asociación en el que se pone el calificador. Por ejemplo, si el
nº de cuenta lo representáramos nada más que con los dígitos finales (eliminando los dígitos
iniciales, que son los que especifican el banco), tal y como está el ejemplo, para un banco y un
número de cuenta obtendríamos un solo titular. Pero si pusiéramos el nº de cuenta en el extremo
de Persona, dado un titular y un nº de cuenta obtendríamos uno o más bancos.
El uso de cualificadores restringe el entorno de la asociación y es útil, por ejemplo, para
realizar búsquedas.

- Orden. Si la multiplicidad es mayor que uno, los elementos relacionados por la asociación pueden
estar ordenados o no. Se utiliza {ordered} para indicar que dichos elementos se encuentran
ordenados. Por ejemplo:
paciente
Lista Médico Persona
{ordered}

- Xor-asociación. Se utiliza esta restricción para indicar que sólo una de las posibles asociaciones
modeladas en el diagrama de clases puede ser instanciada en un momento dato para una
determinado objeto. Se representa gráficamente como una línea de puntos que conecta dos o más
asociaciones a la que se le añade la restricción {xor}. Por ejemplo:

Persona
Cuenta {xor}

Compañía

Aquí estamos indicando que una cuenta puede estar a nombre de una compañía o de una
persona, pero no simultáneamente de ambas. Esto es, un objeto : Cuenta puede estar relacionado
(enlazado) con un objeto : Persona o con un objeto : Compañía, pero no con un objeto : Persona y
un objeto : Compañía a la vez.

- Clase asociación. Designa a una asociación que tiene propiedades de clase, tales como atributos,
operaciones y/o otras asociaciones. Siempre es representada junto a la asociación a la que
corresponde, y unida a ella mediante una línea discontinua. Ya que clase y asociación forman un
todo, el nombre de ambas es igual, pudiéndose especificarse en cualquiera de ellas o en ambas.
Por ejemplo:
0..* 1..*
Compañía Persona
patronal empleado

Trabajo
jefe
fechaContrato
salario 0..1

trabajador
0..*
dirige
Ingeniería del Software-UML 47

Nótese que Trabajo, al pertenecer a la asociación, está ligado tanto a Compañía como a
Persona, y es ese conjunto el que tiene significado. Véase que este diagrama permite modelar que
una persona p1 fuera jefe de otra persona p2 en una compañía c1, y que simultáneamente p2 fuera
jefe de p1 en una compañía c2.

Hasta ahora se han visto asociaciones binarias, pero las asociaciones se pueden dar entre cualquier
número de clases. Tal caso se representa gráficamente como un rombo que está unido por una línea continua a
todas las clases incluidas en la asociación. Por ejemplo:

Temporada

0..*
0..* 0..*
Equipo Jugador

Ficha

sueldo
clausulaRescision

En este ejemplo se modela una asociación denominada Ficha (que además tiene una clase asociación)
entre las clases Temporada, Jugador y Equipo.

Agregación y composición.

Estas relaciones son un tipo especial de asociación. En una relación de asociación, las clases
participantes tienen una relación de igual a igual, mientras que en la agregación y la composición la relación
es de todo-parte. Esto es, una clase forma parte o es un componente, en algún sentido, de otra.

La composición es más fuerte que la agregación. En la composición, la vida de la parte coincide (o es


un subintervalo) de la vida del todo. Es el todo quien se tiene que encargar de construir y destruir la parte y la
parte, en general, no podrá ser compartida por ningún otro elemento.

Simplificando se puede decir que, internamente, una clase todo contendrá a una clase parte agregada
por referencia, mientras que a una clase parte compuesta la contendrá por valor.

La agregación se representa como una asociación con un rombo vacío en el lado de la clase todo. Por
ejemplo:

1 4
Coche Rueda

Aquí se ha mostrado que un coche (el todo) t iene cuatro ruedas (la parte). Se ha modelado como una
agregación porque la rueda puede existir antes que el coche como entidad propia o incluso después (se
desguaza el coche y de dejan las ruedas) e incluso se puede cambiar alguna de las ruedas de un coche a otro.
Ingeniería del Software-UML 48

La composición se representa como una asociación con un rombo lleno en el lado de la clase todo. Por
ejemplo:
1 0..*
Formulario Botón

Aquí se ha mostrado que un formulario (el todo) puede contener cero o más botones (la parte). Un
botón sólo puede existir dentro de un formulario, por lo que la vida del botón estará restringida a la vida del
formulario que lo posee. Un botón pertenece a un y sólo un formulario.

He aquí otro ejemplo de composición y agregación:

1 contiene 3..*
Poligono Punto
{ordered}
1

PropiedadesGraficas
1
color
textura
focosIluminacion

Realización.

Una realización es una relación semántica entre clasificadores, en la cual un clasificador especifica un
contrato que otro clasificador garantiza que cumplirá. Generalmente se emplea la realización para especificar
una relación entre una interfaz y la clase o componente que implementa las operaciones especificadas en dicha
interfaz.

Una interface es un clasificador que especifica una serie de operaciones, pero que no proporciona
ninguna implementación (ni tiene atributos). Es equivalente a una clase abstracta que sólo tiene operaciones
abstractas. Un ejemplo de interface sería el RS-232 (suele ser el estándar para puertos serie). El estándar
especifica operaciones como el envío y recepción de caracteres, que podrán ser implementados por un chip o
tarjeta (que son los que realizan dicha interface).

Gráficamente, una interface se muestra como una clase con el estereotipo «interface» y sus
operaciones, o en forma resumida como un círculo y debajo el nombre del interface:

«interface»
Mensurable

peso(): double Mensurable


volumen(): double

En este caso, el interface Mensurable especifica dos operaciones, peso() y volumen().

Para indicar que una clase realiza una interfaz, se muestra una línea discontinua acabada en flecha
vacía que va de la clase que implementa el interfaz a la interfaz.
Ingeniería del Software-UML 49

Por ejemplo:

Saco

...

peso(): double
volumen(): double
... «interface»
Mensurable

Automóvil peso(): double


volumen(): double

...

peso(): double
volumen(): double
...

En este caso, se indica que tanto Saco como Automovil “realizan” el interface Mensurable, es decir,
ambas implementan las operaciones indicadas en el interface.

En el caso de usar la notación resumida, se unirá el interface a la clase que lo implementa por una
línea continua. Por ejemplo:

Saco
Mensurable

Automóvil
Mensurable

Cuando una clase realiza un interface, debe implementar todas las operaciones indicadas en dicha
interface y, posiblemente, otras exclusivas de la clase.

Varias clases pueden satisfacer un interface (como en el ejemplo anterior), y una clase puede
satisfacer varios interfaces. Por ejemplo:

Furgoneta Mensurable

Alquilable

Las interfaces pueden evitar en ciertos casos el uso de herencia múltiple. Son muy útiles para
independizar la implementación de sistemas o utilidades de los servicios u operaciones que proporcionan (esto
es, se puede cambiar la implementación sin que sea necesario modificar las llamadas, ya que no se ha
Ingeniería del Software-UML 50

modificado el interface), fomentando la reutilización. Los interfaces son soportados por lenguajes como Java o
Corba.

Otra de las posibilidades de los interfaces consiste en limitar el acceso en las asociaciones. Por
ejemplo, sea el siguiente interface:

«interface»
Empleado

nombre()
fechaNacimiento()
dni()
numeroHijos()

Si en el extremo de una asociación especificamos un nombre (o lista de nombres) de interface(s)


precedidos de dos puntos, la clase en el extremo contrario sólo podrá acceder a las operaciones indicadas en el
interface, como en el siguiente ejemplo:

Compañía Persona
: Empleado

Esto evitaría, por ejemplo, que la Compañía pudiera acceder a métodos de la clase Persona que no
fueran de su incumbencia para el tipo de relación Compañía-Persona (como sería el caso, suponiendo que la
clase Persona lo implementara, del método perteneceGrupoRiesgoSida(): bool, que sí sería de incumbencia
en una relación Médico-Persona).

Dependencia.

Una dependencia es una relación entre un elemento dependient e (el cliente) y un elemento
independiente (el suministrador del servicio requerido). El elemento dependiente (cliente) requiere conocer al
elemento independiente (suministrador) y que éste esté presente. Las dependencias se usan para modelar
relaciones en la cual un cambio en el elemento independiente (el suministrador) puede requerir cambios en el
elemento dependiente (el cliente).

Es un tipo de relación unidireccional, ya que el elemento dependiente debe conocer al independiente,


pero el independiente desconoce la existencia del elemento dependiente. Gráficamente se muestra como una
línea discontinua acabada en flecha que va del elemento dependiente al independiente (esto es, el elemento
dependiente señala al elemento del que depende). Por ejemplo:

Cliente Servidor

En este caso, la clase Cliente (dependiente) dependerá de servicios proporcionados por la clase
Servidor (independiente), y un cambio en la clase Servidor puede ocasionar que la clase Cliente necesite ser
adaptada. Un cambio en la clase Cliente no tiene ningún efecto sobre la clase Servidor, ya que esta última es
independiente de la primera (no la necesita).

Para que la clase dependiente tenga acceso a la clase independiente, la clase independiente debe tener
visibilidad global, ser pasada como parámetro a una operación o ser instanciada como variable local en una
operación de la clase dependiente.
Ingeniería del Software-UML 51

Cuando una clase usa los servicios de otra a través de un interface, también se modela como
dependencia (depende del interface, un cambio en el interface requeriría un cambio en la clase dependiente).
Por ejemplo:

ClaseImplementadoraInterface ClaseDependiente

Interface

Nótese que la ClaseDependiente depende de Interface, no de la ClaseImplementadoraInterface. De


hecho un cambio en la ClaseImplementadoraInterface no tendría ninguna consecuencia sobre la
ClaseDependiente, ya que el interface aísla de posibles cambios en la clase implementadora.

Las relaciones de dependencia también se utilizan para mostrar la dependencia entre paquetes. Tal y
como se dijo, las clases se suelen agrupar en paquetes. Para agrupar las clases en paquetes, se pueden utilizar
varios criterios. Un criterio puede ser el agrupar las clases por estereotipos (en este caso habría un paquete
para las clases frontera, otro para las de control y otro para las de entidad). También es posible agrupar las
clases por su funcionalidad (podría haber un paquete con clases que se encargaran del control de acceso, otras
de la gestión informes, otra de errores, etc.). Como los paquetes pueden contener a su vez otros paquetes, una
tercera posibilidad consiste en agrupar las clases por funcionalidades y dentro de cada grupo de funcionalidad,
volver a agrupar por estereotipo.

Una relación de dependencia entre un paquete A y un paquete B indica que alguna clase del paquete A
tiene una relación unidireccional con alguna clase del paquete B y, por tanto, el paquete A necesita tener
acceso al paquete B. Las relaciones de dependencia entre paquetes deben ser calificadas con el estereotipo
«access» o «import». Con ambos estereotipos se tiene acceso a los elementos públicos del paquete
independiente, pero con «access» es necesario preceder dichos elementos por el nombre del paquete que los
contiene mientras que con «import» no (en este caso, es necesario que ningún nombre de un elemento del
paquete dependiente coincida con un nombre de elemento del paquete independiente). Por ejemplo:

«access»
A B

Esta dependencia tiene implicaciones en la reutilización. El paquete B es fácilmente reutilizable (es


independiente), mientras que el paquete A no lo es, ya es dependiente del B y para reutilizar el paquete A
habría que usar también el B. Se deben evitar en lo posible referencias circulares.

Los paquetes contenidos en otros paquetes pueden acceder a todos los elementos del paquete que los
contiene. Sin embargo, las dependencias no son transitivas, tal y como se muestra en el siguiente ejemplo:

B
«import «import
A » » D
C
Ingeniería del Software-UML 52

El paquete A puede acceder al paquete B y al paquete C. El paquete B y el paquete C pueden acceder


al paquete D. El paquete A no puede acceder al paquete D. Si se deseara que A accediera a D, habría que
añadir una dependencia de A a D.

Clases parametrizadas.

Una clase parametrizada o plantilla (template) es un descriptor de una clase con uno o más parámetros
formales. Una clase parametrizada define una familia de clases: cada clase se especifica ligando los
parámetros formales de la clase parametrizada a valores reales. Una plantilla no es utilizable directamente (es
decir, no se puede instanciar ningún objeto de la misma) por tener parámetros libres. Gráficamente, una clase
parametrizada se muestra como una clase a la que se añade un recuadro en línea discontinua en la parte
superior derecha donde se indican sus parámetros formales:

ListaParámetros
NombreClase

Las clases parametrizadas suelen utilizarse para crear contenedores, siendo el parámetro el tipo de
elemento que almacenará dicho contenedor. También puede recibir valores, como por ejemplo un número
entero.

Un ejemplo de clase parametrizada (del tipo contenedor) sería una plantilla de pila. Esta plantilla,
además de tener el tipo del elemento a almacenar como parámetro, podrá recibir un valor entero que indique el
máximo número de elemento de la pila (100 por defecto). Para instanciar una clase a partir de la clase
parametrizada, se utilizará una dependencia estereotipada como «bind» (ligar), tal como se muestra en el
ejemplo:

tElem, max:int=100
Pila

«bind» (persona,200)

PilaPersonas

También es posible indicar directamente los parámetros entre ángulos en la clase instanciada. Por
ejemplo:
Pila<persona>

Nótese que en este caso no se ha especificado el número máximo de elementos, luego la pila tendrá
100 que es el número que se le ha dado por defecto. Si quisiéramos dar expresamente el valor, quedaría:

Pila<persona,100>
Ingeniería del Software-UML 53

UTILIDADES .
Las utilidades son un agrupamiento de variables y procedimientos globales en forma de una
declaración de clase. Es un artificio que facilita el diseño y programación. Una clase utilidad se modela con el
estereotipo «utility», tal como se puede ver en el siguiente ejemplo:

«utility»
UtilidadesMatemáticas

sin(double): double
random(): double
...

Otro ejemplo sería una utilidad de operaciones estadísticas, como la media, la mediana, la desviación,
etc. Al definirse como utilidad, se podrían utilizar dichas operaciones directamente por cualquier clase
(visibilidad global).

Las utilidades pueden estar parametrizadas, utilizándose una notación similar a las clases
parametrizadas.

TIPOS .
Los tipos se utilizan para especifica r un dominio de objetos junto con las operaciones aplicables a
dichos objetos, sin definir ni la implementación física de esos objetos ni métodos. Un tipo se representa como
una clase con el estereotipo «type»:

«type»
MiTipoDeDatos

Esta notación permite modelar los tipos predefinidos del lenguaje o crear tipos nuevos. Para que el
nuevo tipo sea utilizable, es necesario crear una clase que proporcione métodos para todas las operaciones del
tipo. La relación sería una realización:

«type»
MiTipoDeDatosImplementado
MiTipoDeDatos

DIAGRAMA DE OBJETOS.
Un diagrama de objetos es una instancia de un diagrama de clases. Es una instantánea de un sistema
en la que se detalla el estado del mismo en ese momento: objetos, valores significativos de los atributos y
enlaces entre objetos. Un diagrama de clases indica lo que puede ser el sistema; un diagrama de objetos
representa la situación del sistema en un momento determinado (se utilizan instantes significativos o
prototípicos).

Los diagramas de objetos se utilizan, generalmente, para visualizar, especificar y documentar mod elos
estructurales, esto es, estructuras de objetos cuya complejidad aconseje dibujar un diagrama que sirva para
una mejor comprensión del modelo.
Ingeniería del Software-UML 54

En general, existen dos posibilidades:


- Partir del diagrama de clases y crear una instancia (diagrama de objetos) que permita una mejor
comprensión del mismo.
- Partir de un diagrama de objetos significativo y modelar un diagrama de clases que posibilite, al
menos, dicha instancia. Esto sucede, por ejemplo, cuando se conocen ejemplos de la estructura
real y se quiere derivar un diagrama de clases al que se ajuste.

Para construir un diagrama de objetos hay que:


- Identificar la estructura o mecanismo que se quiera modelar.
- Identificar las clases, interfaces y otros elementos que intervengan en la relación.
- Considerar un escenario en el que intervenga ese mecanismo y congelar ese escenario,
representando cada objeto que participe en dicho mecanismo.
- Mostrar los valores y atributos necesarios para comprender el escenario.
- Mostrar los enlaces entre esos objetos, que representarán instancias de asociaciones entre ellos.

Por ejemplo, si tenemos este diagrama de clases:

Compañía

0..n
Dpto

0..n 1..n

Persona

, podríamos modelar el siguiente diagrama de objetos para documentarlo:

: Compañía

ventas: Dpto id: Dpto

nombre= “Ventas” nombre= “I+D”

: Persona
: Persona : Persona

dMa: Dpto dLu: Dpto

nombre= “Deleg. Madrid” nombre= “Deleg. Lugo”

: Persona : Persona : Persona


Ingeniería del Software-UML 55

Nótese que los enlaces son instancias de las relaciones del diag rama de clases, esto es, relaciones que
se dan en un momento dado, por lo cual no puede aparecer ninguna multiplicidad en ellas. También se han
incluido los valores del atributo nombre de los objetos de la clase Dpto para facilitar su entendimiento.

También es posible especificar el estado en que se encuentra el objeto. Por ejemplo, el siguiente
diagrama muestra un objeto de la clase Robot que se encuentra moviéndose (estado movimiento), así como el
mundo (entorno) que ha identificado y la relación entre elementos identificados:

: Robot [movimiento]

: Mundo

a1: Area a1: Area

m1: Muro p1: Puerta m2: Muro m3: Muro

ancho= 80 ancho= 40 ancho= 80 ancho= 40

Nótese que el objeto a1 es un área rectangular (habitación) formada por tres muros y una puerta, y
que cada uno de los elementos constituyentes está relacionado con su adyacente (por ejemplo, el muro m1
limita con la puerta p1 y con el muro m3).

Como en los diagramas de clases también se pueden mostrar objetos, un diagrama de clases que sólo
contenga instancias de clases, esto es, objetos, se le puede denominar diagrama de objetos. Este caso sucede,
por ejemplo, en Rose: no hay un diagrama de objetos como tal, por lo que se debe utilizar un diagrama de
clases para representar un diagrama de objetos.

DIAGRAMAS DE IMPLEMENTACIÓN.
Los diagramas de implementación muestran aspectos relativos a la implementación, incluyend o la
estructura del código fuente y similares (diagrama de componentes) y la estructura de implementación en
tiempo de ejecución (diagrama de despliegue).

DIAGRAMAS DE COMPONENTES.
Un diagrama de componentes se utiliza para modelar los componentes de un sistema y mostrar las
dependencias entre ellos.
Ingeniería del Software-UML 56

Un componente representa un módulo de software con un interface bien definido. Ejemplos de


componentes son el código fuente, código binario, ejecutable, DLL, fichero de inicialización (.ini), fichero de
registro (.log), tablas, documentos, mapas de bits de los iconos de una aplicación, etc.

Los componentes pueden existir en tiempo de compilación, de enlace o de ejecución o incluso en


varios o todos esos tiempos. Los componentes son equivalentes a tipos, siendo sus instancias las que
aparecerán en el diagrama de despliegue.

Hay una gran diferencia entre clases y componentes. Las clases son “componentes lógicos”, mientras
que los componentes tienen significado físico. Antes de poder generar código, las clases deben ser mapeadas a
componentes (esto es, las clases residen o son implementadas en componentes), y estos componentes serán los
que contengan su código fuente.

La notación estándar de un componente es:

Nombre

Dentro del componente se especifica su nombre y/o su tipo y, opcionalmente, una cadena de
propiedades que indiquen, por ejemplo, su versión, autor, estado, etc. También se puede mostrar dentro de un
componente las clases o paquetes que residan en él, o incluso otros componentes.

Un componente puede depender de otro. En este caso existe una relación de dependencia entre ellos,
tal y como se puede ver en el siguiente ejemplo:

programa.exe programa.pas

Nótese que el programa ejecutable ( programa.exe) depende del programa fuente (programa.pas).
Esta es una dependencia de compilación: para generar programa.exe necesitamos programa.pas.

Tal y como se dijo, los componentes deben tener interfaces bien definidos. Esto permite que los
componentes puedan ser reemplazados (por ejemplo, por componentes más eficaces) y reutilizados fácilmente,
posibilitando la construcción de componentes complejos utilizando componentes más simples. Se puede
expresar explícitamente que un componente depende de un interface realizado por otro componente, tal y como
se muestra a continuación:

B.dll A.exe

Esto podría modelar, por ejemplo, un ejecutable A.exe que requiere de algún servicio proporcionado
por la dll (Dinamic Link Library) B.dll. No habría ningún problema en cambiar la dll por otra más moderna
que fuera, por ejemplo, más eficaz, ya que, al accederse a ella a través de un interface, no habría que realizar
ninguna modificación en los ejecutables.
Ingeniería del Software-UML 57

Rose proporciona para los componentes algunos estereotipos estándar con iconos asociados, tal y
como se muestra a continuación:
- Especificación y cuerpo de subprograma. Los subprogramas son colecciones de rutinas (no
contienen definiciones de clases), tales como funciones o procedimientos. Las especificaciones
constituyen el interface del componente (la definición de las funciones; en C++ sería el fichero .h)
y el cuerpo la implementación (la implementación de las funciones; en C++ sería el fichero .cpp).
Sus representaciones gráficas son:

Especificación de Subprograma Cuerpo de subprograma

- Programa principal. Indica que en el componente reside el programa principal. Su representación


gráfica es:

Programa principal

- Especificación y cuerpo de paquete. Los paquetes contienen las clases. Las especificaciones
constituyen el interface del componente (la definición de las clases; en C++ sería el fichero .h) y el
cuerpo la implementación (la implementación de los métodos de las clases; en C++ sería el fichero
.cpp). En C++ se pueden asociar varias clases a un componente, mientras que en Java cada clase
debe asociarse a un componente individual. Sus representaciones gráficas son:

Especificación de paquete Cuerpo de paquete

- Especificación y cuerpo de tarea. Representa paquetes que tienen hilos independientes de control.
Normalmente, un fichero ejecutable se representa como una especificación de tarea con extensión
.exe. Sus representaciones gráficas son:

Especificación de tarea Cuerpo de tarea


Ingeniería del Software-UML 58

Los diagramas de componentes permiten mostrar tanto dependencias en tiempo de compilación y


lincado como en tiempo de ejecución. Incluso permiten mostrar dependencias entre varias versiones de
componentes.

Por ejemplo, el siguiente diagrama muestra dependencias en tiempo de ejecución:

.exe

.hlp a.dll

.ini .log b.dll

Este otro diagrama muestra dependencias en tiempo de compilación:

principal.exe

principal.cpp

b.h
a.h

c.h b.cpp

a.cpp

c.cpp
Ingeniería del Software-UML 59

Este tipo de diagrama muestra el orden en que se deben compilar los ficheros, a qué otros
componentes afectaría el cambio de uno de ellos y qué se debería recompilar. Téngase en cuenta que en los
diagramas que muestran la secuencia de compilación no deben aparecer referencias circulares, ya que sería
imposible realizar dicha compilación.

A la hora de asociar clases a componentes, si éstas se han agrupado en paquetes, se suelen asociar
dichos paquetes a los componentes. Sin embargo, hay veces en que conviene hacerlo de forma diferente (para
adaptarse a una arquitectura cliente-servidor, porque haya clases sujetas a modificaciones frecuentes, etc.).
Además, aunque una clase se suele asociar a un solo componente, hay veces que conviene asociar una misma
clase a varios componentes.

Rose permite especificar el lenguaje en que se realizará cada componente. Esto permitiría, por
ejemplo, generar los componentes de la parte cliente en Visual Basic y los componentes de la parte servidor en
C++ en un sistema con arquitectura cliente-servidor.

DIAGRAMA DE DESPLIEGUE.
Los diagramas de despliegue muestran la configuración de elementos de proceso (el despliegue de
procesadores, periféricos, comunicaciones, etc.) y los componentes software (programas, procesos, etc. ) que
residen en ellos en tiempo de ejecución. En los diagramas de despliegue aparecen instancias de componentes,
pertenecientes al diagrama de componentes, mostrándose en qué nodos (procesadores) reside cada instancia.
En un diagrama de despliegue no pueden aparecer componentes que no existen como entidades en tiempo de
ejecución, como los ficheros fuente.

Los nodos de un diagrama de despliegue representan elementos físicos con capacida d de proceso o
facilitadores de algún servicio. Se puede especificar el tipo de un nodo o una instancia del mismo (en cuyo
caso se subrayará). Un nodo se representa tal como sigue:

Nombre

Rose utiliza dos representaciones diferentes para los nodos. Si el no do tiene capacidad de proceso
(como un ordenador, un servidor o similar), los laterales se ponen en negro:

Si el nodo no tiene capacidad de proceso (como un terminal, una impresora o un escaner), los laterales
no se rellenan:
Ingeniería del Software-UML 60

Los nodos son los elementos donde se encuentran o ejecutan las instancias de los componentes en
tiempo de ejecución. Para mostrar que una instancia de un componente reside o se ejecuta en un nodo, es decir,
que el nodo soporta una instancia de ese componente, se relaciona al nodo con la instancia mediante una
dependencia estereotipada como «support», tal y como se muestra a continuación:

OrdContabilidad : PC

«support
»
: ContaGes
.

De forma alternativa, se puede mostrar la instancia dentro del nodo:

OrdContabilidad: PC

: ContaGes

Los nodos están relacionados entre sí por asociaci ones, que indican caminos de comunicación. Una
asociación se representa gráficamente como una línea entre los nodos que comunica. Es común estereotipar las
asociaciones para indicar su tecnología.
Ingeniería del Software-UML 61

Un ejemplo de un diagrama de despliegue de un sistema sería:

ServBD : Servidor

: SGBD

«LAN»

ServCentral : Servidor «USB»


:
Impresora
: ServGestor

«RDSI» «RDSI»

DelegacionJaen : PC DelegacionToledo : PC

: CliGestor : CliGestor

Hay veces que una instancia de un componente puede migrar de un nodo a otro. Para modelar esta
migración se representa una relación entre dichas instancias con el estereotipo «become». Por ejemplo:

Nodo1
:A
: Cluster

«become»
Nodo2

: Cluster
Ingeniería del Software-UML 62

Aquí se representa la instancia : Cluster que en principio reside en Nodo1 y que en cierto momento
pasa a residir en Nodo2. Nótese que la instancia : A reside todo el tiempo en Nodo1.

Rose sólo permite un diagrama de despliegue. Por otro lado, Rose permite especificar, entre otras, el
tipo de planificación de tareas que se utiliza en cada nodo.

PROCESO UNIFICADO DE RATIONAL13.


Las técnicas que proporciona UML son bastante independientes del proceso y pueden ser utilizadas en
varias metodologías. Una de estas metodologías es el Proceso Unificado de Rational.

Las características fundamentales de esta metodología son las siguientes:


- Enfoque iterativo e incremental.
- Desarrollo orientado a objetos.
- Dirigida y controlada.
- Altamente automatizada.

Está basada en tres pilares:


- Personas.
- Proceso.
- Herramientas y método.

Además, integra dos perspectivas:


- Organizativa: relativa a aspectos financieros, estratégicos, comerciales y humanos.
- Técnica: relativa a la calidad y métodos ingenieriles y de diseño.

13
Para más información se recomienda consultar el documento “A Rational Development Process” de Philippe
Kruchten, disponible en http://www.rational.com/products/whitepapers/334.jsp.
Ingeniería del Software-UML 63

Las fases del ciclo de vida del Proceso Unificado de Desarrollo, desde el punto de vista organizativo,
son las siguientes:
- Concepción (inception): La “idea feliz”: especificación de la visión del producto final y los casos
de negocio.
- Elaboración (elaboration): Planificación de las actividades y recursos necesarios; especificación
de requisitos y diseño de la arquitectura.
- Construcción (construction): Construcción del producto y refinamiento hasta que el producto esté
preparado para su uso.
- Transición (transition): Realizar la transición de los clientes al producto generado, incluyendo
formación, soporte y mantenimiento hasta que los usuarios estén satisfechos.

Desde un punto de vista técnico, el ciclo de vida se divide en varias iteraciones (cuyo número y
duración depende de factores como la complejidad del software, experiencia del equipo y otros). Existe una
coincidencia en el tiempo de los hitos desde el punto de vista organizativo con los hitos desde el punto de vista
técnico, como es lógico:
Ingeniería del Software-UML 64

Cada iteración consta de siete actividades:


- Planificación.
- Análisis.
- Arquitectura.
- Diseño.
- Implementación.
- Integración.
- Prueba/mantenimiento.

El énfasis en cada una de estas actividades depende de la fase e iteración en la que nos encontremos,
predominando al principio las actividades de análisis, más tarde las de diseño, luego las de construcción y por
último las de prueba y mantenimiento, como se puede ver en el siguiente gráfico:

El Proceso Unificado de Rational no está guiado por documentos, sino por el producto en sí. Los
documentos típicos a obtener pertenecen tanto al ámbito organizativo como técnico, incluyendo los modelos de
casos de uso, clases, interacción, etc., para lo cual se recomienda la utilización de herramientas CASE
apropiadas.
Ingeniería del Software-UML 65

GENERACIÓN DE CÓDIGO14.

En esta sección se dará una introducción básica sobre cómo generar y qué código se genera a partir
de los modelos realizados en Rose.

CÓMO GENERAR CÓDIGO .


En general, se deben seguir 6 pasos para la generación de código:
1. Comprobar el modelo.
2. Crear los componentes.
3. Asignar clases a componentes.
4. Establecer las propiedades para la generación del código.
5. Seleccionar una clase, componente o paquete.
6. Generar el código.

1. Comprobar el modelo.

Utilizando la opción Tools Check Model se comprueba que el modelo es consistente antes de generar
código. Aunque no es obligatorio, es muy recomendable realizarlo.

Algunos errores comunes que detecta esta opción son:


- Mensajes en los diagramas de secuencia o colaboración no mapeados a operaciones.
- Objetos en los diagramas de secuencia o colaboración no mapeados a clases.
- Accesos no permitidos entre clases causados por falta de visibilidad.

2. Crear los componentes.

Se deben crear los componentes necesarios y sus relaciones (diagrama de componentes). Al crear un
componente se puede especificar su estereotipo (p. ej., programa principal, cabecera, cuerpo, etc.) y el
lenguaje en el que se generará (C++ en nuestro caso).

3. Asignar clases a componentes.

Dependiendo del lenguaje utilizado, una clase debe estar asignada a un solo componente, o varias
clases pueden estar asignadas a un mismo componente o, como en el caso de C++, una misma clase puede
pertenecer a dos componentes distintos (.h y .cpp). Esta asignación se hace arrastrando la clase desde el
browser y “soltándola” en el componente o desde la ficha realizes de la especificación del componente.

4. Establecer las propiedades para la generación del código.

Estas propiedades controlarán el código que será generado. Rose proporciona unas propiedades por
defecto que pueden ser cambiadas según se requiera. Este cambio se puede hacer para todo el modelo desde
Tools Options (se recomienda hacer una copia con Clone y trabajar sobre ella) o para una clase en particular

14
Se recomienda consultar los apuntes de C++ dejados en el servidor donde se tratan conceptos como constructores
por copia, plantillas y la STL.
Ingeniería del Software-UML 66

abriendo su especificación. Entre las propiedades que se pueden establecer paralas clases están si Rose
generará operadores de igualdad (operador == y operador !=) o si generará el destructor y la visibilidad del
destructor en caso afirmativo. Cambiando el elemento seleccionado en el desplegable type de dicha opción se
puede acceder a otros elementos susceptibles de ser modificados para la generación de código, como por
ejemplo, las relaciones.

5. Seleccionar una clase, componente o paquete.

Se puede seleccionar una clase, un componente o un paquete para generar su código. También se
pueden seleccionar múltiples elementos mediante la tecla [Ctrl].

6. Generar el código.

Se puede generar código seleccionando Tools C++ Code Generation o desde el menú contextual.
Por defecto, el fichero o ficheros se generan en C:\Archivos de programa\Rational\Rose\C++\source siendo el
nombre de archivo el nombre del componente y la extensión .h o .cpp según el estereotipo del componente.

QUÉ SE GENERA .
Rose puede generar los siguientes elementos:
- Clases.
- Atributos (incluyendo visibilidad, tipo y valor por defecto).
- Declaraciones de operaciones (incluyendo parámetros, tipos de los parámetros y tipo devuelto).
- Relaciones (aunque sólo algunos tipos).
- Componentes (ficheros).

Por ejemplo, sea la siguiente clase:

Coche

-cilindrada: double

+potencia(): double

El código generado para esta clase, dejando las opciones de generación de código por defecto, incluye:
- Definición de la clase, incluyendo la definición del atributo cilindrada y la operación potencia().
- Definición del constructor y constructor por copia y destructor. También genera el esqueleto del
código necesario para su implementación.
- Definición de las operaciones de comparación (igualdad y desigualdad) y la asignación. También
genera el esqueleto del código necesario para su implementación.
- Definición e implementación de las operaciones (privadas) set y get del atributo cilindrada.
Téngase en cuenta, sin embargo, que posiblemente la operación set se tendrá que retocar para
Ingeniería del Software-UML 67

evitar la introducción de valores inválidos en el atributo, como en este caso sería intentar asignar
un valor negativo a la cilindrada.
- Esqueleto para la implementación de la operación potencia().

Rose permite documentar la mayoría de los elementos. Al generar código, parte de esa documentación
aparecerá como comentario en el código. Por ejemplo, si documentamos la semántica de una operación de una
clase, esta documentación aparecerá como comentario encima de la definición de la operación al generar el
código.

Veamos ahora el esqueleto que crea Rose correspondiente a la implementación de la operación


potencia:

//## Other Operations (implementation)


double Coche::potencia ()
{
//## begin Coche::potencia%3A13C55B00DC.body preserve=yes
//## end Coche::potencia%3A13C55B00DC.body
}

El programador debería generar el código del cuerpo de dicho método entre las líneas //## begin
... y //## end ... . De esta forma, dicho código será preservado ( preserve=yes ) si se vuelve a generar
el código de esa clase.

Al ser la programación orientada a objetos un proceso fundamentalmente iterativo, si sobre el código


generado se añaden o suprimen directamente atributos u operaciones, conviene realizar ingeniería inversa para
que los nuevos elementos sean introducidos al modelo de forma “automática” (Rational Rose C++ Analyzer),
ya que, si se olvida modelar los cambios en el diagrama de clases y se vuelve a generar código, se perderán las
operaciones y atributos introducidas manualmente.

No se deben borrar los códigos que genera Rose, ya que le son necesarios para si se desea volver a
generar código o se realiza ingeniería inversa.

Rose también proporciona espacios para introducir nuevo código, por ejemplo, para declaraciones
públicas:

// Additional Public Declarations


//## begin Coche%3A13C52B03A2.public preserve=yes
//## end Coche%3A13C52B03A2.public

Proporciona también secciones para realizar “includes” y otras declaraciones adicionales.

El listado completo del código generado para la anterior clase es el siguiente:

//## begin module%1.3%.codegen_version preserve=yes


// Read the documentation to learn more about C++ code generator
// versioning.
//## end module%1.3%.codegen_version

//## begin module%3A13C58701AE.cm preserve=no


// %X% %Q% %Z% %W%
//## end module%3A13C58701AE.cm

//## begin module%3A13C58701AE.cp preserve=no


//## end module%3A13C58701AE.cp

//## Module: Coche%3A13C58701AE; Main program


//## Subsystem: <Top Level>
//## Source file: C:\Archivos de programa\Rational\Rose\C++\source\Coche.cpp
Ingeniería del Software-UML 68

//## begin module%3A13C58701AE.additionalIncludes preserve=no


//## end module%3A13C58701AE.additionalIncludes

//## begin module%3A13C58701AE.includes preserve=yes


//## end module%3A13C58701AE.includes

//## begin module%3A13C58701AE.declarations preserve=no


//## end module%3A13C58701AE.declarations

//## begin module%3A13C58701AE.additionalDeclarations preserve=yes


//## end module%3A13C58701AE.additionalDeclarations

//## begin Coche%3A13C52B03A2.preface preserve=yes


//## end Coche%3A13C52B03A2.preface

//## Class: Coche%3A13C52B03A2


//## Category: <Top Level>
//## Persistence: Transient
//## Cardinality/Multiplicity: n

class Coche
{
//## begin Coche%3A13C52B03A2.initialDeclarations preserve=yes
//## end Coche%3A13C52B03A2.initialDeclarations

public:
//## Constructors (generated)
Coche();

Coche(const Coche &right);

//## Destructor (generated)


~Coche();

//## Assignment Operation (generated)


Coche & operator=(const Coche &right);

//## Equality Operations (generated)


int operator==(const Coche &right) const;

int operator!=(const Coche &right) const;

//## Other Operations (specified)


//## Operation: potencia%3A13C55B00DC
double potencia ();

// Additional Public Declarations


//## begin Coche%3A13C52B03A2.public preserve=yes
//## end Coche%3A13C52B03A2.public

protected:
// Additional Protected Declarations
//## begin Coche%3A13C52B03A2.protected preserve=yes
//## end Coche%3A13C52B03A2.protected

private:
//## Get and Set Operations for Class Attributes (generated)

//## Attribute: cilindrada%3A13C53501EA


const double get_cilindrada () const;
void set_cilindrada (double value);

// Additional Private Declarations


//## begin Coche%3A13C52B03A2.private preserve=yes
//## end Coche%3A13C52B03A2.private

private: //## implementation


// Data Members for Class Attributes

//## begin Coche::cilindrada%3A13C53501EA.attr preserve=no private: double {U}


double cilindrada;
//## end Coche::cilindrada%3A13C53501EA.attr
Ingeniería del Software-UML 69

// Additional Implementation Declarations


//## begin Coche%3A13C52B03A2.implementation preserve=yes
//## end Coche%3A13C52B03A2.implementation

};

//## begin Coche%3A13C52B03A2.postscript preserve=yes


//## end Coche%3A13C52B03A2.postscript

// Class Coche

//## Get and Set Operations for Class Attributes (inline)

inline const double Coche::get_cilindrada () const


{
//## begin Coche::get_cilindrada%3A13C53501EA.get preserve=no
return cilindrada;
//## end Coche::get_cilindrada%3A13C53501EA.get
}

inline void Coche::set_cilindrada (double value)


{
//## begin Coche::set_cilindrada%3A13C53501EA.set preserve=no
cilindrada = value;
//## end Coche::set_cilindrada%3A13C53501EA.set
}

// Class Coche

Coche::Coche()
//## begin Coche::Coche%3A13C52B03A2_const.hasinit preserve=no
//## end Coche::Coche%3A13C52B03A2_const.hasinit
//## begin Coche::Coche%3A13C52B03A2_const.initialization preserve=yes
//## end Coche::Coche%3A13C52B03A2_const.initialization
{
//## begin Coche::Coche%3A13C52B03A2_const.body preserve=yes
//## end Coche::Coche%3A13C52B03A2_const.body
}

Coche::Coche(const Coche &right)


//## begin Coche::Coche%3A13C52B03A2_copy.hasinit preserve=no
//## end Coche::Coche%3A13C52B03A2_copy.hasinit
//## begin Coche::Coche%3A13C52B03A2_copy.initialization preserve=yes
//## end Coche::Coche%3A13C52B03A2_copy.initialization
{
//## begin Coche::Coche%3A13C52B03A2_copy.body preserve=yes
//## end Coche::Coche%3A13C52B03A2_copy.body
}

Coche::~Coche()
{
//## begin Coche::~Coche%3A13C52B03A2_dest.body preserve=yes
//## end Coche::~Coche%3A13C52B03A2_dest.body
}

Coche & Coche::operator=(const Coche &right)


{
//## begin Coche::operator=%3A13C52B03A2_assign.body preserve=yes
//## end Coche::operator=%3A13C52B03A2_assign.body
}

int Coche::operator==(const Coche &right) const


{
//## begin Coche::operator==%3A13C52B03A2_eq.body preserve=yes
//## end Coche::operator==%3A13C52B03A2_eq.body
}

int Coche::operator!=(const Coche &right) const


{
//## begin Coche::operator!=%3A13C52B03A2_neq.body preserve=yes
Ingeniería del Software-UML 70

//## end Coche::operator!=%3A13C52B03A2_neq.body


}

//## Other Operations (implementation)


double Coche::potencia ()
{
//## begin Coche::potencia%3A13C55B00DC.body preserve=yes
//## end Coche::potencia%3A13C55B00DC.body
}

// Additional Declarations
//## begin Coche%3A13C52B03A2.declarations preserve=yes
//## end Coche%3A13C52B03A2.declarations

//## begin module%3A13C58701AE.epilog preserve=yes


//## end module%3A13C58701AE.epilog

CÓDIGO GENERADO EN LAS RELACIONES .


Una asociación bidireccional uno a uno se implementa mediante un atributo puntero a la otra clase en
cada una de las clases. Ej.:

ClaseA ClaseB
1 1

class ClaseA { class ClaseB {


... ...
private: private:
ClaseB *the_ClaseB; ClaseA *the_ClaseA;
... ...
};
};

Si la asociación es unidireccional, se define el puntero sólo en la clase que tiene navegabilidad:

ClaseA ClaseB
1 1

class ClaseA { class ClaseB {


... ...
private: };
ClaseB *the_ClaseB;
...
};
Ingeniería del Software-UML 71

Si la asociación es uno a un número determinado, por defecto se utili zará una matriz de punteros. Por
ejemplo:

ClaseA ClaseB
1 4

class ClaseA { class ClaseB {


... ...
private: };
ClaseB *the_ClaseB[4];
...
};

Si la asociación es uno a muchos, se necesita algún tipo de contenedor para los punteros:

ClaseA ClaseB
1 0..*

class ClaseA { class ClaseB {


... ...
private:
};
UnboundedSetByReference<ClaseB> the_ClaseB;
...
};

Nótese que UnboundedSetByReference<ClaseB> the_ClaseB significa que el atributo


the_ClaseB será un conjunto (sin número máximo de elementos) de valores por referencia a objetos de la la
clase ClaseB (punteros).

Este es el código generado por defecto y no es compilable directamente por C++, a no ser que creemos
un contenedor con dicho nombre y semántica. Sin embargo, se podría utilizar, por ejemplo, alguno de los
contenedores proporcionados por la STL ( Standard Template Library) de C++, por ejemplo, la lista (list15).
Para ello, se debe cambiar en las opciones de compilación (seleccionando el tipo Project), la definición de
UnorderedUnboundedByReferenceContainer que está por defecto a
UnboundedSetByReference<$targetClass>> por list<*targetClass>. Además, hay que añadir la librería
list.h, utilizando por ejemplo la pestaña C++ de las especificaciones del componente (sección
AdditionalIncludes).

15
list es una clase parametrizada (plantilla).
Ingeniería del Software-UML 72

El código generado ahora, que puede ser compilado sin problemas, será:

#include <list.h> class ClaseB {


... ...
class ClaseA { };
...
private:
list<*ClaseB> the_ClaseB;
...
};

Rose también tiene especificaciones propias para generar asociaciones en la que los elem entos deben
estar ordenados que podemos adaptar a nuestras librerías o a la STL para generar código compilable.

Una relación de agregación genera un código similar a una asociación. Por ejemplo:

ClaseA ClaseB
1 3

class ClaseA { class ClaseB {


... ...
private:
};
ClaseB *the_ClaseB[3];
...
};

Sin embargo, en la relación de composición, la parte compuesta se tiene como un atributo de la clase
(esto es, por valor):

ClaseA ClaseB
1 3

class ClaseA { class ClaseB {


... ...
private:
};
ClaseB the_ClaseB[3];
...
};

En el caso de relaciones de dependencia, Rose sólo incluye en el código los “includes” que sean
necesarios.
Ingeniería del Software-UML 73

Rose también genera código para las relaciones de generalización. Por ejemplo:

Padre

Hija

class Padre {
...
} ;

class Hija: public Padre


...
};

CÓDIGO GENERADO PARA CLASES PARAMETRIZADAS .


Rose también genera código para clases parametrizadas (plantillas). Por ejemplo:

Plantilla

template <void T>


class Plantilla
{
...
};

EJEMPLO.
Como ejemplo de generación de código, veremos lo que se ge nera en la siguiente asociación:

ClaseA ClaseB
1 0..n

ClaseC
Ingeniería del Software-UML 74

class ClaseA {
...
private:
UnboundedSetByReference<ClaseC> the_ClaseC;
...
};

class ClaseB {
...
};

class ClaseC {
...
private
ClaseB *the_ClaseB;
...
};

Obsérvese que se podría utilizar co mo contenedor una lista para hacer que el código fuera compilable.

ROSE Y LA GENERACIÓN DE CÓDIGO .


Hay muchos aspectos que quedan fuera de la generación de código de Rose. Por ejemplo, una clase
declarada en Rose como persistente no genera ningún código que soporte dicha persistencia. Será misión del
programador hacer que dicha clase sea persistente.

Das könnte Ihnen auch gefallen