Documentación de requisitos

Índice
- Introducción
- Objetivos
- 1.Documentación de requisitos: perspectiva general
- 2.Estilos de documentación de requisitos
- 3.Documentación de requisitos mediante casos de uso
- 4.Documentación del modelo del dominio mediante UML y OCL
- 4.1.El modelo del dominio
- 4.2.El lenguaje OCL
- 4.2.1.Introducción a OCL mediante ejemplos
- 4.2.2.Restricciones de integridad y reglas de derivación en OCL
- 4.2.3.Propiedades
- 4.2.4.Sintaxis básica OCL
- 4.2.5.Variables
- 4.2.6.Colecciones
- 5.Caso práctico
- Resumen
- Actividades
- Ejercicios de autoevaluación
- Solucionario
- Glosario
- Bibliografía
Introducción
Objetivos
-
Saber cuáles son las características deseables de una buena especificación de requisitos.
-
Elegir entre los diferentes estilos de documentación (ágil / exhaustivo, formal / no formal) para un proyecto de software determinado.
-
Saber evitar los errores más frecuentes en la utilización de los casos de uso.
-
Crear un modelo del dominio en lenguaje UML y saber expresar en lenguaje OCL sus restricciones de integridad.
1.Documentación de requisitos: perspectiva general
1.1.Características deseables de la documentación de los requisitos
-
Correcta: Cada uno de los requisitos que constan es un requisito que debe cumplir el sistema que hay que desarrollar.
-
Inambigua: Cada uno de los requisitos especificados solo se puede interpretar de una manera.
-
Completa: Aparecen todos los requisitos del sistema que hay que desarrollar, con independencia del tipo de requisito.
-
Consistente: No contiene ninguna contradicción.
-
Ordenada: Está ordenada en función de la importancia y la estabilidad de los requisitos.
-
Verificable: Cada uno de los requisitos que hay es verificable; es decir, existe un proceso finito y con un coste razonable mediante el cual una persona o una máquina pueden determinar si el sistema cumple o no dicho requisito.
-
Modificable: Permite que se puedan realizar con facilidad cambios en la documentación (por ejemplo, que tenga tablas de contenidos, referencias cruzadas, etc.).
-
Trazable: El origen de cada requisito está claramente identificado y, al mismo tiempo, se facilita la identificación de cada requisito para poder referenciarlo más adelante durante el desarrollo del sistema.
1.2.Buenas prácticas de la documentación de requisitos
2.Estilos de documentación de requisitos
2.1.Clasificación de las necesidades de documentación de requisitos

-
Documentación exhaustiva-ágil
-
Documentación formal - no formal
-
Documentación exhaustiva y no formal (IEEE-830),
-
Documentación exhaustiva y formal (OCL),
-
Documentación ágil y no formal (historias de usuario), y
-
Documentación ágil y formal (especificación por ejemplos).

2.1.1.Documentación exhaustiva/ágil
2.1.2.Documentación en lenguaje no formal - formal
2.2.Documentación exhaustiva y no formal: IEEE-830
2.2.1.Contenidos de la especificación
-
Funcionalidad: ¿Qué tiene que hacer el sistema que hay que desarrollar?
-
Interfaces externas: ¿Cómo interactúa el software con las personas, con el hardware o con otros sistemas software?
-
Rendimiento: ¿Cuál es la velocidad, disponibilidad, tiempo de respuesta, tiempo de recuperación, etc. que esperamos del software?
-
Atributos: ¿Cuáles son las consideraciones respecto a portabilidad, corrección, mantenibilidad, seguridad, etc.?
-
Restricciones de diseño para la implementación: ¿Debe cumplir algún estándar? ¿Presenta alguna restricción por lo que respecta al lenguaje de programación que hay que utilizar? ¿Cuáles son las políticas de gestión de datos (por ejemplo, relativas a la integridad de los datos)? ¿Existen limitaciones con respecto al entorno de operación? Etc.
2.2.2.Estructura de la especificación de requisitos del software
-
Objetivo: Describe qué pretende el documento y a quién va dirigido.
-
Ámbito: Describe cuál es el producto que hay que desarrollar, identificado por su nombre (por ejemplo, “Sistema integral de ventas de viajes UOC”), qué hará y qué no hará el producto que hay que desarrollar, los beneficios que aportará el nuevo sistema a la organización y los objetivos que se espera conseguir.
-
Definiciones, acrónimos y abreviaturas: Contiene la explicación de todos los términos necesarios para entender correctamente la especificación de requisitos del software.
-
Referencias: Contiene tanto la lista completa de documentos referenciados más adelante durante la especificación de requisitos del software, donde cada documento está identificado correctamente (título, número de informe si lo tiene, fecha, editorial), como las fuentes donde se puede obtener dicho documento.
-
Sinopsis: Hace una descripción general del contenido del resto de la especificación de requisitos del software y explica la estructura del documento.
-
Perspectiva del producto: sitúa el producto que hay que desarrollar con respecto a otros productos de software. Por ejemplo, indica si forma parte de un sistema más grande (y, en tal caso, cómo encaja dentro de dicho sistema) o si es un producto autocontenido que funciona de manera aislada. Por lo tanto, contiene la descripción de las interfaces (con los usuarios, con otros sistemas software, con el hardware, etc.) que debe presentar el producto que hay que desarrollar.
-
Funciones del producto: resume las principales funcionalidades que ofrecerá el producto, así como su relación entre ellas (ya sea de forma textual o con la ayuda de algún diagrama).
-
Características de los usuarios: contiene información sobre cómo son los usuarios que se espera que utilicen el software (nivel de estudios, experiencia en el dominio, experiencia con la tecnología, etc.). De nuevo, se trata de dar la visión de por qué existen unos requisitos concretos más que de dar los requisitos en sí.
-
Restricciones: describe las leyes aplicables, limitaciones de hardware, necesidades de auditoría, requisitos de seguridad, etc.
-
Asunciones y dependencias: contiene la lista de factores que pueden afectar a los requisitos en el sentido de que un cambio en uno de estos factores puede afectar a los requisitos. Por ejemplo, si hemos supuesto que cierto sistema operativo estará disponible para el hardware sobre el que queremos ejecutar el software, debemos documentarlo en este apartado porque, si se diera el caso de que ese sistema operativo no estuviera disponible, habría que cambiar algunos de los requisitos del software.
-
Requisitos aplazables: son los requisitos que, a pesar de haberse identificado ya, se pueden aplazar para futuras versiones.
-
Interfaces externas: requisitos de la interfaz gráfica de usuario, interfaces de hardware o de software e interfaces de comunicación.
-
Funciones: requisitos funcionales del sistema.
-
Requisitos de rendimiento: requisitos relativos al rendimiento esperado del software.
-
Requisitos lógicos de bases de datos: requisitos sobre qué datos se tienen que guardar en una base de datos, qué frecuencia de uso tendrán, qué capacidades de acceso a ellos habrá, qué restricciones de integridad de datos, etc.
-
Restricciones de diseño: restricciones impuestas en el diseño, por ejemplo por la presencia de otros estándares, limitaciones del hardware, etc.
-
Cumplimiento de estándares: estándares que debe cumplir el software.
-
Atributos del sistema de software: requisitos no funcionales, como la fiabilidad, la disponibilidad, la seguridad, la mantenibilidad y la portabilidad.
2.3.Documentación exhaustiva y formal: OCL
2.4.Documentación ágil y no formal de requisitos: historias de usuario
-
una descripción corta (una frase) de la historia de usuario, que sirve como recordatorio de que existe la historia y es útil para planificar, etc.;
-
una serie de conversaciones, que sirven para definir y aclarar los detalles de la historia de usuario, y
-
un conjunto de criterios de aceptación, que documentan los detalles y que permiten determinar cuándo está implementada completamente la historia de usuario.

2.4.1.Radiadores de información
-
ser grande y visible a simple vista (no hay que buscarlo);
-
ser fácil de interpretar de un vistazo;
-
estar actualizado, de forma que resulta útil consultarlo con mayor o menor frecuencia, y
-
ser fácil de actualizar.
Panel de tareas

Panel del backlog

2.5.Documentación ágil formal: especificación por ejemplos
Cuando sumamos 5 y 20, el resultado es 25.
3.Documentación de requisitos mediante casos de uso
3.1.Flexibilidad de los casos de uso por lo que respecta al estilo de documentación

2) El sistema muestra la ficha detallada del hotel o del destino.
3) El cliente pide ver todas las recomendaciones sobre aquel hotel o destino.
4) El sistema muestra todas las recomendaciones sobre aquel hotel o destino
3.2.Errores habituales en la documentación de los casos de uso
3.2.1.Casos de uso sin sistema
2) El cliente elige un hotel de la lista y ve la ficha detallada.
3.2.2.Casos de uso sin actor principal
3.2.3.Casos de uso demasiado dependientes de la interfaz de usuario
3.2.4.Objetivos de demasiado bajo nivel
-
Agrupando todas las interacciones que van en una misma dirección en un solo paso. Los pasos uno y dos, por ejemplo, se pueden resumir en uno solo: “El cliente introduce el término de búsqueda y pulsa el botón Buscar”. Sin embargo, a veces nos encontramos con que tenemos dos interacciones que, a pesar de ir en la misma dirección, son bastante diferentes entre sí (por ejemplo, “El cliente introduce sus datos personales” y “El cliente introduce los datos del producto que quiere comprar”). En estos casos, es mejor no agruparlas.
-
Identificando objetivos más generales. Los pasos tres a cinco, por ejemplo, se pueden considerar parte de un único objetivo: “Mostrar el listado de hoteles que cumplen los criterios de búsqueda”. Explicado de este modo, tenemos suficiente con un único paso, ya que no necesitamos detallar cómo se llevará a cabo este paso hasta que lleguemos al diseño del sistema.
-
Agrupando elementos de datos. Los pasos siete a once se pueden resumir como: “El sistema muestra la ficha detallada del hotel”. Si se considera que la ficha detallada es un concepto demasiado ambiguo, siempre se puede especificar exactamente la lista de campos que debe presentar en un glosario y reutilizar el término en las diferentes descripciones de casos de uso que vamos haciendo.
3.2.5.Casos de uso inconsistentes
-
Actor principal. A pesar de que se dice que el actor principal puede ser el cliente o el agente de viajes (tiene sentido que los dos puedan buscar un hotel), a la hora de describir los escenarios, hablamos solo del cliente. Sería preciso o bien considerar solo al cliente como actor principal, o bien modificar la descripción de los escenarios para tener en cuenta también a los agentes de viajes.
-
Intereses y escenarios no alineados. A la hora de describir el escenario, se ha apuntado toda una serie de pasos que no están relacionados con el objetivo del actor principal tal y como está expresado: el caso de uso se denomina “Buscar un hotel”, pero, en cambio, en la descripción se habla de todo el proceso de navegación entre fichas detalladas de hoteles, lo que daría, como mínimo, para un segundo caso de uso.
3.2.6.Otros errores frecuentes
-
Falta de definición del alcance y de los límites del sistema. Si de entrada no queda muy claro lo que consideramos que queda dentro del sistema y lo que no, podemos acabar confundiendo los términos.
-
Inconsistencia en la identificación de actores.
-
Demasiados casos de uso. Este error se puede considerar una variante del error de describir casos de uso a demasiado bajo nivel. Sin embargo, en este caso el error reside en hacer un número de casos de uso excesivo, de granularidad demasiado fina.
-
Relaciones entre actores y casos de uso excesivamente complejos. Si tenemos pocos actores y las relaciones entre actores y casos de uso se convierten en una telaraña indescifrable, quizás sea preciso hacer generalizaciones para detectar actores más generales, que reúnan los casos de uso en común de varios actores más específicos.
-
Especificaciones textuales inexistentes, demasiado largas o confusas.
3.3.Limitaciones de los casos de uso para la documentación de requisitos
3.3.1.Casos de uso para requisitos que no implican una interacción entre actores y el sistema
3.3.2.Carencia de formalismo y de estandarización
3.3.3.Falta de agilidad
3.3.4.Casos de uso para otras actividades de la ingeniería del software
4.Documentación del modelo del dominio mediante UML y OCL
4.1.El modelo del dominio

4.1.1.Restricciones de integridad e información derivada

-
El viaje se tiene que pagar, como mínimo, quince días antes de la fecha de inicio de la reserva del viaje que tenga la fecha de inicio anterior a todas las otras.
-
El viaje se tiene que pagar, como mínimo, quince días antes de su fecha de inicio.
4.1.2.UML como lenguaje formal de documentación de requisitos
-
La notación que ofrece UML no permite expresar todas las restricciones de integridad de los modelos estáticos del dominio.
-
UML no ofrece ninguna notación para expresar cómo se deriva la información derivada.
-
UML no ofrece ninguna notación que permita expresar la semántica de una operación del sistema o de una clase, a pesar de que sí que las hay para expresar el diseño.
-
Se trata de un lenguaje de expresiones. OCL permite enunciar las llamadas expresiones: sentencias que tienen un resultado (como “cierto”, “23” o un conjunto de instancias de la clase Reserva) pero que no tienen efectos laterales; es decir, la evaluación de una expresión OCL no modifica nunca el estado de la población de objetos sobre la que se evalúa.
-
Se trata de un lenguaje formal. Cada expresión OCL correcta solo se puede interpretar de una manera, que es la que describe la especificación del lenguaje. Por lo tanto, no hay ninguna ambigüedad posible.
4.2.El lenguaje OCL
4.2.1.Introducción a OCL mediante ejemplos

4.2.2.Restricciones de integridad y reglas de derivación en OCL
self.fechaFin> self.fechaInicio
self.reserva->forAll(r | r.oclIsTypeOf(ReservaHotel) implies
r.hotel.destino = self.destino)
Viaje.allInstances()->forAll(v1,v2 | v1<>v2 implies not(v1.cliente=v2.cliente and v1.fechaInicio=v2.fechaInicio))
self.viaje->isUnique(fechaInicio)
derive: self.reserva.fechaInicio->min()
4.2.3.Propiedades
-
v1.fechaInicio, de tipo Fecha, uno de los atributos
-
v1.fechaFin, de tipo Fecha, el otro atributo
-
v1.destino, de tipo Destino, el destino asociado al viaje
-
v1.agente, de tipo Agente, el agente asociado al viaje
-
v1.cliente, de tipo Cliente, el cliente asociado al viaje
-
v1.reserva, un conjunto de instancias de Reserva, las reservas asociadas al viaje
Tipo de las propiedades y expresiones
-
Si la propiedad es univaluada (un atributo o extremo de asociación con multiplicidad 1 o 0..1), el tipo de la propiedad es el tipo del atributo o el de la clase de aquel extremo de asociación.
-
Si la propiedad es un atributo o asociación multievaluados (indica una multiplicidad como por ejemplo [*] o [1..*]), el tipo será una colección. Las colecciones se ven más adelante, pero el tipo típico será un Set(T) donde T es el tipo de la propiedad.
Propiedades y herencia
-
self.direccion
-
self.telefono
-
self.viaje (el conjunto de viajes asociados al cliente)
-
self.nombre (el nombre del cliente self, heredado de la clase Persona)
-
self.email (la dirección de correo del cliente self, heredada de la clase Persona)
4.2.4.Sintaxis básica OCL
Restricciones de integridad
invariante
Reglas de derivación
contexto Viaje::duracion:Tiempo derive: duracion = self.fechaFin - self.fechaInicio
Tipos numéricos
Operación |
Ejemplo |
Detalles |
---|---|---|
+, *, / |
3+4 |
Suma, multiplicación y división de dos números. |
- |
-3, 3-4 |
Resta o cambio de signo (sólo Integer y Real). |
abs() |
-2.abs() |
Valor absoluto. |
max(n), min(n) |
3.max(5) |
Máximo y mínimo entre dos números. |
<, <=, >, >= |
3<=6 |
Comparación de dos números. |
toString() |
3.toString() |
Conversión en una cadena de texto. |
div(n) |
15.div(4) |
División entera (solo Integer y UnlimitedNatural). |
mod(n) |
15.mod(4) |
Módulo de la división entera (solo Integer y UnlimitedNatural). |
floor() |
3.4.floor() |
Truncar a entero (solo Real). |
round() |
3.4.round() |
Redondear a entero (solo Real). |
Booleanos
Operación |
Ejemplo |
Detalles |
---|---|---|
or, xor |
a or b |
O no exclusiva / O exclusiva. |
and |
a and b |
Y lógica. |
not |
not(false) |
Negación lógica. |
implies |
a implies b |
Equivalente a not(a) or (a and b). |
If-then-else-endif |
if a then b else c endif |
Devuelve b o c en función de a |
toString() |
false.toString() |
Conversión en una cadena de texto. |
String
Operación |
Ejemplo |
Detalles |
---|---|---|
+ |
‘a’ + ‘b’ |
Concatenación de cadenas. |
concat() |
‘a’.concat(‘b’) |
Equivalente a +. |
size() |
‘a’.size() |
Número de caracteres. |
substring(i,s) |
‘hola’.substring(1,3) |
Extrae una subcadena. |
at(i) |
‘hola’.at(2) |
Carácter en la posición i. |
indexOf(s) |
‘hola’.indexOf(‘ol’) |
Posición ocupada por un string dentro de otro. |
toInteger, toReal, toBoolean |
‘3’.toReal() |
Conversión de tipo. |
toUppercase, toLowercase |
‘hola’.toUppercase() |
Conversión a mayúsculas o minúsculas. |
equalsIgnoreCase(s) |
‘h’.equalsIgnoreCase(‘H’) |
Comparación sin tener en cuenta mayúsculas o minúsculas. |
<, <=, >, >= |
‘a’ < ‘b’ |
Comparación. |
OclAny
Operación |
Ejemplo |
Detalles |
---|---|---|
=, <> |
a = b |
Comparación en función de si los dos valores son el mismo. |
Operación |
Ejemplo |
Detalles |
---|---|---|
oclType() |
‘a’.oclType() |
Devuelve el tipo del objeto sobre el que se invoca. |
oclIsTypeOf(t) |
‘a’.oclIsTypeOf(String) |
Cierto si el objeto es exactamente del tipo indicado. |
oclIsKindOf(t) |
‘a’.oclIsKindOf(Any) |
Cierto si el objeto es del tipo indicado o de uno de sus subtipos. |
oclAsType(t) |
p.oclAsType(Estudiante) |
Devuelve una referencia al objeto del tipo indicado (siempre que sea de un tipo compatible). |
OclVoid y OclInvalid
-
El valor null, de tipo OclVoid, representa la ausencia de valor.
-
El valor invalid, de tipo OclInvalid, representa un error de evaluación de una expresión.
Operación |
Ejemplo |
Detalles |
---|---|---|
oclIsUndefined |
p.departament.oclIsUndefined() |
Indica si un valor es null. |
oclIsInvalid |
‘a’.oclAsType(Real).oclIsInvalid() |
Indica si un valor es invalid. |
4.2.5.Variables
in expresion- que- utiliza- nombre- variable
let fechaHoraSalida:FechaHora = self.salida.fecha in
let fechaHoraLlegada:FechaHora = self.llegada.fecha in
fechaHoraSalida < fechaHoraLlegada
4.2.6.Colecciones
-
Set: colección de elementos sin elementos repetidos y sin orden.
-
OrderedSet: colección de elementos sin elementos repetidos pero en un orden concreto.
-
Bag: colección de elementos donde pueden haber repetidos y sin orden.
-
Sequence: colección de elementos donde pueden haber repetidos y con un orden concreto.
self.reserva->size()>1
Uso de propiedades y colecciones

Colección de todas las instancias de una clase
Select y reject
def: reservasCortas:Set(Reserva) = self.reserva->select(fechaFin=fechaInicio)
def: reservasCortas:Set(Reserva) = self.reserva-> select(r|r.fechaFin=r.fechaInicio)
def: reservasCortas:Set(Reserva) = self.reserva->reject(fechaFin<>fechaInicio)
collectNested y collect
coleccion ->collectNested(var | expresion-con-var)
def: codigosReserva:Set(String) = self.reserva -> collectNested(r|r.codigo)
def: codigosReserva:Set(String) = self.reserva->collect(r|r.codigo)
def: codigosReserva:Set(String) = self.reserva.codigo
forAll y exists
coleccion->forAll(v | expresion- booleana- con-v)
coleccion->exists(expresion-booleana)
coleccion-> exists(v | expresion-booleana-con-v)
def: tieneViajesABcn:Boolean = self.viaje -> exists(v|v.destino.nombre=“Barcelona”)
self.viaje->forAll(v|v.destino.nombre=”Barcelona”)
Otras operaciones básicas
Operación |
Ejemplo |
Detalles |
---|---|---|
size() |
v.reserva->size() |
Número de elementos. |
isEmpty(), notEmpty() |
v.reserva->isEmpty() |
Indica si la colección está vacía o no. |
includes(o), excludes(o) |
d->includes(“Barcelona”) |
Indica si la colección incluye el objeto o no. |
count(o) |
dests->count(“Barcelona”) |
Devuelve el número de veces que aparece el objeto en la colección. |
includesAll(c), excludesAll(c) |
d->includesAll(prefDests) |
Indica si una colección incluye o excluye todos los elementos de otra. |
max, min, sum |
v.reserva.fechaInicio->min() |
Devuelve el máximo, mínimo o suma de los valores de una colección (tienen que ser valores numéricos). |
def:numViajesABerlin:Integer =
self.viaje -> select(v|v.destino.nombre=”Berlin”) -> size()
def: numViajesATokio:Integer = self.viaje.destino.nombre->count(“Tokio”)
def: conoceNuevaYork:Boolean = self.viaje.destino.nombre->includes(“Nueva York”)
def: primerViaje:Fecha = self.viaje.fechaInicio->min()
-
Cuando pasamos de una colección con repetidos a una que no los tiene, se eliminan los repetidos.
-
Cuando pasamos de una colección sin orden a una con orden, el orden no está definido. En el caso contrario, sencillamente se pierde el orden de los elementos.
Operación |
---|
asSet() |
asOrderedSet() |
asSequence() |
asBag() |
flatten() |
def destinosDiferentes:Set(String) = self.viaje.destino.nombre -> asSet()
def codigosReserva:Set(String) = self.viaje.reserva.codigo ->asSet()
def codigosReserva:Set(String) =
self.viaje -> collectNested(reserva.codigo) -> flatten() -> asSet()
Operaciones sin orden
Operación |
Detalles |
---|---|
union(s:Set(T)): Set(T) |
Unión de self y s. |
union(b:Bag(T)): Bag(T) |
Unión de self y b. |
intersection(s:Set(T)): Set(T) |
Intersección de self y s. |
intersection(b:Bag(T)): Bag(T) |
Intersección de self y b. |
- (s:Set(T)): Set(T) |
Elementos de self que no están en s. |
symmetricDifference(s:Set(T)): Set(T) |
Elementos que están en self o en s pero no en los dos. |
including(o:T): Set(T) |
Conjunto de los elementos de self y, además, o. |
excluding(o:T): Set(T) |
Conjunto de todos los elementos de self excepto o. |
Operación |
Detalles |
---|---|
union(s:Set(T)): Bag(T) |
Unión de self y s. |
union(b:Bag(T)): Bag(T) |
Unión de self y b. |
intersection(s:Set(T)): Bag(T) |
Intersección de self y s. |
intersection(b:Bag(T)): Bag(T) |
Intersección de self y b. |
including(o:T): Set(T) |
Conjunto de los elementos de self y, además, o. |
excluding(o:T): Set(T) |
Conjunto de todos los elementos de self excepto todas las ocurrencias de o. |
Operaciones con orden
Operación |
Detalles |
---|---|
append(o:T):OrderedSet(T) |
Conjunto de los elementos de self seguidos de o. |
prepend(o:T): OrderedSet(T) |
Conjunto formato por o seguido de los elementos de self. |
insertAt(i:Integer,o:T): OrderedSet(T) |
Conjunto de los elementos de self con o insertado en la posición i. |
subOrderedSet(i:Integer, f:Integer):OrderedSet(T) |
Subconjunto de self entre las posiciones i y f. |
at(i:Integer): T |
Elemento que ocupa la posición i de self. |
indexOf(o:T): Integer |
Posición que ocupa el elemento o en self. |
first():T, last():T |
Primer/Último elemento de self. |
reverse(): OrderedSet(T) |
Los elementos de self en el orden opuesto. |
Operación |
Detalles |
---|---|
union(s:Sequence(T)): Sequence(T) |
La secuencia formada por self seguida de los elementos de s. |
append(o:T): Sequence (T) |
Secuencia de los elementos de self seguidos de o. |
prepend(o:T): Sequence (T) |
Secuencia formada por o seguido de los elementos de self. |
insertAt(i:Integer,o:T): Sequence (T) |
Secuencia de los elementos de self con o insertado en la posición i. |
including(o:T):Sequence(T) |
Sinónimo de la operación append. |
excluding(o:T): Sequence(T) |
Secuencia de todos los elementos de self salvo todas las ocurrencias de o. |
subSequence(i:Integer, f:Integer): Sequence (T) |
Subsecuencia de self entre las posiciones i y f. |
at(i:Integer): T |
Elemento que ocupa la posición i de self. |
indexOf(o:T): Integer |
Posición que ocupa el elemento o en self. |
first():T, last():T |
Primer/Último elemento de self. |
reverse(): Sequence(T) |
Los elementos de self en el orden opuesto. |
Operaciones de iteración
Operación |
Detalles |
---|---|
isUnique |
Devuelve cierto si la expresión se evalúa con un valor diferente para cada elemento de la colección. |
any |
Devuelve un elemento cualquiera para el cual la expresión se evalúe a cierta, o a null si no hay ninguno. |
one |
Devuelve cierto si y solo si exactamente uno de los elementos de self evalúa la expresión a cierta. |
sortedBy |
Devuelve una colección ordenada donde los elementos de self están ordenados según el resultado de evaluar la expresión. |
def: unViajeARoma:Viaje = self.viaje->any(v | v.destino.nombre=”Roma”)
def: soloUnaVezATarragona:Boolean = self.viaje.destino.one(d | d.nombre=”Tarragona”)
def: viajesPorFechaInicio:OrderedSet(Viaje) = self.viaje->sortedBy(v|v.fechaInicio)
5.Caso práctico
5.1.Documentación formal y exhaustiva: modelo del dominio en UML y OCL

5.1.1.Modelo del dominio en UML

5.1.2.Restricciones de integridad e información derivada
Restricciones de integridad e información derivada en lenguaje natural
Restricciones de integridad e información derivada en OCL
self.fecha < e.fecha
self.llegada.anteriorA(t.salida) or t.llegada.anteriorA(self.salida)
Información derivada
self.reserva.fechaInicio->min()
self.reserva.fechaFin ->max()
5.2.Historias de usuario
-
El agente puede escoger el destino de una lista predefinida.
-
La opinión se publica en cuanto se envía.
-
La opinión queda asociada al agente y al destino.
-
El comercial puede escoger el destino de una lista predefinida.
-
Una vez hecha la oferta, esta queda asociada al destino y se registran las fechas de vigencia de la oferta.
-
El propietario puede escoger al cliente de una lista de clientes de la agencia o elegir su nombre de usuario.
-
La oferta consiste en un tanto por ciento de descuento y es acumulable a otras ofertas.
-
La oferta solo está disponible si nos identificamos como el usuario en concreto para quien se ha hecho la oferta.
Resumen
Actividades
-
Una canción titulada Sing, sing, sing, de Benny Goodman, con una duración de 8:40, perteneciente al álbum The Essential Benny Goodman.
-
Una canción titulada Shout, sister, shout, de Sister Rosetta Tharpe y Lucky Millinder and his Orchestra, de 2:44, perteneciente al álbum The A-Z of Jazz.
-
El artista de nombre Benny Goodman tiene una pequeña biografía que nos explica que debutó en la era del swing y aparece una fotografía suya. Está relacionado con los artistas Glenn Miller, Duke Ellington y Ella Fitzgerald.
-
Hay una fotografía del artista Lucky Millinder and his Orchestra, pero no hay ninguna biografía en el sistema ni artistas relacionados.
-
La artista Sister Rosetta Tharpe tiene una fotografía y una pequeña biografía que la sitúa entre los cantantes de gospel de su generación. Está relacionada con los artistas Bassie Smith y Fats Waller.
-
El álbum The Essential Benny Goodman tiene una fotografía de la portada, una reseña de la crítica y una lista ordenada de cuarenta canciones, donde Sing, sing, sing ocupa la sexta posición.
-
Sing, sing, sing está a la venta en Estados Unidos y en Francia. En Estados Unidos cuesta 0,99 $, mientras que en Francia cuesta 0,79 €. También tiene un enlace de descarga.



-
No modeléis ninguna pieza de información que no aparezca en las pantallas.
-
Si pensáis que alguna información de la que aparece en el esbozo es derivada de información que se tiene que conocer pero que no aparece, indicadla igualmente como derivada. Por ejemplo, el número de artículos asociados a un proyecto se calcula a partir de los artículos que el proyecto tiene asociados, que no aparecen aquí; por lo tanto, en el diagrama UML indicaremos que este número de artículos es derivado.
-
Haced las suposiciones que creáis convenientes para tratar las fechas y otros tipos de datos como si fueran numéricos en OCL.
-
En particular, suponed que restando dos fechas obtenéis el número de días de diferencia y que podéis obtener fechas con N días de diferenciasumando o restando enteros de fechas.

-
No volváis a modelar lo ya hecho en la actividad anterior. Centraos en los artículos y comentarios. Si necesitáis una clase que ya habíais modelado, ponedla en el diagrama, pero no pongáis más atributos que los que son relevantes para los artículos y comentarios.
-
Haced las suposiciones que creáis convenientes para tratar las fechas y otros tipos de datos como si fueran numéricos en OCL.
-
En particular, suponed que restando dos fechas obtenéis el número de días de diferencia y que podéis obtener fechas con N días de diferenciasumando o restando enteros de fechas.

-
Como ya hemos dicho, no volváis a modelar lo ya modelado en la actividad anterior. Centraos en los datos mostrados en este esbozo. Si necesitáis una clase que ya habíais modelado, ponedla en el diagrama pero no pongáis más atributos que los que son relevantes a los datos mostrados en el esbozo.
-
Haced las suposiciones que creáis convenientes para tratar las fechas y otros tipos de datos como si fueran numéricos en OCL.
-
En particular, suponed que restando dos fechas obtenéis el número de días de diferencia y que podéis obtener fechas con N días de diferencia sumando o restando enteros de fechas.
Ejercicios de autoevaluación
Solucionario

Album.allInstances()->isUnique(titulo)
Cancion.allInstances()->forAll(c1,c2 | c1 <> c2 implies
c1.album <> c2.album or c1.titulo <> c2.titulo)
Artista.allInstances()->isUnique(nombre)
Pais.allInstances()->isUnique(nombre)
self.tieneRelacionados->excludes(self) and self.esRelacionadoDe->excludes(self)

Registro.allInstances()->isUnique(termino)
Acepcion.allInstances()->forAll(a1,a2 | a1 <> a2 implies
a1.registro <> a2.registro or a1.num <> a2.num)
self.acepcion->exists(a | a.num = 1) and
self.acepcion->forAll(a | a.num = 1 or self.acepcion->exists(a’ | a’.num = a.num - 1))
-
La CategoriaGramatical y el AreaTematica son enumerations. Puesto que no nos han proporcionado la lista válida de valores, no se han modelado como parte de la solución.
-
El atributo num de la clase Acepcion es el número que se puede ver delante de cada acepción, antes de la categoría gramatical. Dado que indica un orden, se habría podido hacer la composición entre Registro y Acepcion {ordered} (al lado de Acepcion) y omitir el atributo num, o bien hacerlo derivado a partir de la posición que la acepción ocupe dentro de su registro.
self.importe + self.importe*self.iva/100
self.importe > 0
def: pendienteFacturar:Boolean = self.fechaUltimaEntrega > self.fechaUltimaFactura
not(self.fechaPago.oclIsUndefined())
facturasPendientes = self.factura->select(f|not(f.pagada))
facturasPendientes = self.factura->reject(f|f.pagada)
listadoProyectos:Set(String) = self.proyecto.nombre
self.factura->forAll(f|f.pagada)
-
Administrador: consultar proyectos pendientes de moderación.
-
Administrador: moderar un proyecto (decidir si lo acepta o lo rechaza).
-
Usuario: consultar proyectos por varios criterios.
-
Usuario: consultar los detalles de un proyecto.
-
Mecenas: hacer una promesa de aportación a un proyecto.
-
Usuario: consultar un perfil de usuario.
-
Calendario: finalizar la financiación de un proyecto.
-
Artista: cobrar un proyecto financiado con éxito.
-
Los casos de uso en los que el actor es “Usuario” son aquellos que normalmente usará un posible mecenas pero que también pueden usar los artistas.
-
El penúltimo caso de uso se inicia cuando pasa cierto número de días desde que se propuso un proyecto. El actor Reloj o Calendario representa todos aquellos casos de uso que se inician en una fecha o en un momento en el tiempo en lugar de ser iniciados por un usuario.

-
La clase Usuario tiene otros atributos que no aparecen en esta pantalla.
-
Proyecto: titulo
-
Usuario: nombreUsuario
-
Sesion: proyectoEscenico + fechaHora
-
Pregunta: proyecto + pregunta
-
Respuesta: pregunta (las respuestas se identifican por la pregunta a la que responden, puesto que cada pregunta solo puede tener una respuesta o ninguna).
-
Recompensa: proyecto + cantidad
-
La fecha de cada pregunta de un proyecto tiene que ser posterior o igual a su fecha de creación.
-
La fecha de cada respuesta tiene que ser posterior o igual a la fecha de la pregunta que responde.
-
Un proyecto con 0 días restantes está, obligatoriamente, en estado éxito o fallido según si el importe conseguido alcanza el objetivo o no. Un proyecto con algún día restante solo puede estar en estado buscandoFinanciacion, propuesta o noAceptado.
-
La fechaHora de cada sesión de un proyecto escénico tiene que ser, como mínimo, cuarenta días posterior a la fecha de creación del proyecto.
-
Recompensa::aportacionesRestantes, Proyecto::conseguido, Proyecto::numArticulos y Proyecto::numComentarios no se pueden derivar con los datos de este diagrama, pero se derivan de otros datos que no aparecen aquí.
-
Proyecto::diasRestantes es la diferencia entre cuarenta y el número de días desde que el proyecto se creó hasta la fecha actual, o cero si ya han pasado más de cuarenta días.
context Proyecto inv:
Proyecto.allInstances()->isUnique(titulo)
Usuario.allInstances()->isUnique(nombreUsuario)
context Sesion inv:
Sesion.allInstances()->forAll(s1, s2 | s1 <> s2 implies
s1.proyectoEscenico <> s2.proyectoEscenico or
s1.fechaHora <> s2.fechaHora)
Pregunta.allInstances()->forAll(p1, p2 | p1 <> p2 implies
p1.proyecto <> p2.proyecto or p1.pregunta <> p2.pregunta)
Respuesta.allInstances()->isUnique(pregunta)
-- En este caso, dado que una Pregunta solo puede tener una respuesta y una Respuesta solo puede tener una pregunta, esta restricción no es necesaria.
Recompensa.allInstances()->forAll(r1, r2 | r1 <> r2 implies
r1.proyecto <> r2.proyecto or r1.cantidad <> r2.cantidad)
context Pregunta inv:
self.fecha >= self.proyecto.fechaCreacion
self.fecha >= self.pregunta.fecha
self.diasRestantes = 0 implies
((self.conseguido >= self.objetivo and self.estado = EstadoProyecto.exito) or
(self.estado = EstadoProyecto.fallido))
context Proyecto inv:
self.diasRestantes > 0 implies
self.estado <> EstadoProyecto.exito and self.estado <> EstadoProyecto.fallido
self.fechaHora >= self.proyecto.fechaCreacion + 40
context Proyecto.diasRestantes:int derive:
let antiguedad:int = now() – self.fechaCreacion in min(0, 40 – antiguedad)
-- Nota: La operación now() no existe en OCL, pero la necesitamos para poder hacer referencia a la fecha actual.

-
Artículo: proyecto + fecha
-
Comentario: artículo + posición que ocupa en la asociación
-
La fecha de un artículo tiene que ser posterior a la fecha de creación del proyecto.
-
La fecha de un comentario tiene que ser posterior a la fecha del artículo que comenta.
-
Proyecto::numArticulos es el número de artículos que el proyecto tiene asociados.
-
Proyecto::numComentarios es el número total de comentarios que los artículos del proyecto tienen asociados.
context Proyecto inv:
self.articulo->isUnique(fecha)
-- No hay que escribir la clave de comentario porque está implícita
-- en el hecho de que la asociación es {ordered}
context Articulo inv:
self.fecha >= self.proyecto.fechaCreacion
self.fecha >= self.articulo.fecha
context Proyecto::numArticulos:int derive:
self.articulo->size()
self.articulo.comentario->size()
-- Nota: self.articulo.comentario es un Set(Comentario) que contiene los comentarios de
-- todos los artículos del proyecto.

-
La fecha de una aportación tiene que ser posterior a la fecha de creación del proyecto.
-
Si una recompensa tiene maximoAportaciones, entonces no puede tener más de maximoAportaciones aportaciones asociadas.
-
Recompensa::aportacionesRestantes es el máximo de aportaciones de la recompensa menos el número de aportaciones ya asociadas a la recompensa o nulo si no hay un máximo de aportaciones.
-
Proyecto::conseguido es la suma de la cantidad de cada aportación al proyecto.
context Aportacion inv:
self.fecha >= self.recompensa.proyecto.fecha
not(self.maximoAportaciones.oclIsUndefined()) implies
self.aportacion->size() <= self.maximoAportaciones
context Recompensa.aportacionesRestantes:int derive:
if self.maximoAportaciones.oclIsUndefined() then null
else self.maximoAportaciones – self.aportaciones->size()
self.recompensa->collect(r|r.cantidad * r.aportacion->size())->sum()
-- Nota: El collect devuelve una colección donde hay, para cada recompensa, el importe
-- de todas las aportaciones de dicha recompensa. Por lo tanto, al sumar se obtiene el importe
-- total.
2. Conviene no dar por supuesta una determinada solución, como por ejemplo no dar por supuesta una interfaz gráfica de usuario. Véase el subapartado 1.2.
3. Decimos que la documentación de requisitos es formal cuando se usa un lenguaje formal a la hora de describir los requisitos. Por lo tanto, se trata de utilizar un lenguaje definido formalmente y creado para no admitir ambigüedades y, a la vez, facilitar la verificación y la comprobación de la consistencia de la documentación de requisitos. Véase subapartado 2.1.2.
4. Una aproximación ágil y formal a la documentación de los requisitos consiste en escribir los criterios de aceptación en forma de pruebas automatizadas. Véase el subapartado 2.5.
5. Los componentes básicos de una historia de usuario son una descripción, una serie de conversaciones y un conjunto de criterios de aceptación. Véase el subapartado 2.4.
6. Una de las ventajas de los casos de uso es que son muy flexibles por lo que respecta nivel de formalismo y la exhaustividad de su descripción. La misma técnica se puede aplicar en los cuatro estilos de documentación vistos. Véase el subapartado 3.1.
7. No, puesto que, en realidad, los casos de uso es pueden utilizar para documentar requisitos de forma exhaustiva, pero también para documentarlos de forma mucho más ágil. En todo caso, es cierto que las metodologías ágiles suelen preferir las historias de usuario. Véase el apartado 3.
8. Una restricción de integridad es una regla o condición que los datos del software tienen que cumplir para que podamos decir que los datos son consistentes. Véase el subapartado 4.1.1.
9. No, OCL permite escribir una misma restricción de formas diferentes. Véase el subapartado 4.2.2.
10. Atributos, extremos de asociación y propiedades definidas en OCL. Véase el subapartado 4.2.4.
11. Bag y Sequence. Se diferencian en que en Bag no hay ningún orden definido, mientras que en Sequence el orden es relevante. Véase el subapartado 4.5.
Glosario
- actor m
- Ente con capacidad de interactuar con el sistema y que tiene un comportamiento propio. Puede ser una persona, pero también una organización o un sistema (de software o de otro tipo) externos al propio sistema.
- actor de apoyo m
- Actor externo al sistema que proporciona un servicio al sistema.
- actor iniciador m
- Actor que comienza la interacción con el sistema. Puede ser el actor principal, pero también puede ser un intermediario entre este y el sistema. También puede ser que el caso de uso se inicie de forma automática o en respuesta a un acontecimiento externo, en cuyo caso el actor iniciador sería el reloj o dicho acontecimiento, respectivamente.
- actor principal m
- Actor que hace una petición al sistema para recibir uno de los servicios y así satisfacer un objetivo.
- atributo derivado m
- Véase información derivada.
- backlog m
- Lista de historias de usuario, ya sea de todas las historias de un proyecto en desarrollo (product backlog) o de las que se incluyen en una iteración.
- cardinalidad de un atributo f
- Número de valores que una determinada instancia tiene en un atributo.
- cardinalidad de una asociación f
- Número de instancias que una determinada instancia tiene asociadas por medio de una asociación concreta.
- caso de uso m
- Documento que recoge el contrato entre el sistema y sus stakeholders. Describe el comportamiento del sistema y las interacciones en varios escenarios mostrando la forma en que el sistema responde a las peticiones y objetivos de los stakeholders.
- clave de una clase de dominio f
- Atributo o conjunto de atributos que identifica las instancias de la clase de forma única, de modo que no puede haber más de una instancia con los mismos valores en aquel o aquellos atributos.
- contrato de una operación m
- Documentación detallada del comportamiento de una operación que incluye su firma y las precondiciones y poscondiciones.
- criterio de aceptación m
- Descripción de las condiciones mediante las cuales se decidirá si determinado requisito, por lo general una historia de usuario, es considerado satisfecho o no. Véase también prueba de aceptación.
- diagrama de clases m
- Diagrama estándar de UML utilizado para modelizar las clases de objetos y sus relaciones.
- enumeración f
- Tipo de datos en el que el conjunto de valores es una lista finita de valores que se enumera en la definición del tipo de datos.
- escenario de un caso de uso m
- Secuencia de acciones e interacciones que se producen en un caso de uso bajo ciertas condiciones, expresadas sin ramificaciones condicionales o con muy pocas.
- escenario principal de un caso de uso m
- Escenario descrito completamente por un caso de uso desde el inicio del caso de uso hasta su finalización y que lleva al actor principal a cumplir su objetivo. A pesar de que es un escenario de éxito, no tiene que ser necesariamente el único del caso de uso.
- especificación de software f
- Documentación del conjunto de requisitos que debe satisfacer el software.
- garantía mínima de un caso de uso f
- Aquello que podemos asegurar que sucederá al finalizar el caso de uso, sea cual sea el escenario que se produzca.
- historia de usuario f
- Técnica de documentación de requisitos que pone énfasis en la comunicación verbal y minimiza la documentación escrita. Se compone de tres elementos: el nombre, la conversación entre los desarrolladores y los clientes y la lista de pruebas que hay que hacer para verificar que se ha implementado correctamente.
- información derivada f
- Atributo o asociación presente en un modelo, por lo general un modelo del dominio en UML, cuyo valor se calcula a partir de otros elementos del modelo.
- invariante m
- Predicado que es cierto en todo momento. En un modelo de clases UML, un invariante es un predicado, una afirmación sobre el modelo, que siempre es cierta. Las restricciones de integridad y las reglas de derivación de la información derivada son, por lo tanto, invariantes.
- multiplicidad f
- Restricción que indica qué cardinalidades son válidas para un atributo o asociación.
- object constraint language m
- Lenguaje formal estándar de restricciones: lenguaje estándar de UML para la expresión
de restricciones que se puede utilizar, entre otras cosas, para escribir restricciones
de integridad y reglas de derivación.
sigla OCL - Object Management Group m
- Consorcio americano sin ánimo de lucro, creado el 1989, que tiene por objetivo la
estandarización y promoción de la modelización orientada a objetos.
sigla OMG - OCL m
- Véase object constraint language.
- OMG m
- Véase Object Management Group.
- panel Kanban m
- Véase panel de tareas.
- panel Scrum m
- Véase panel de tareas.
- panel de tareas m
- Radiador de información que suele mostrar las funcionalidades que hay que desarrollar
durante una iteración, su descomposición en tareas y el progreso de cada una.
sin compl. según la metodología de desarrollo utilizada, panel Kanban o panel Scrum - propiedad de una clase f
- Elemento genérico que hace referencia a atributos y a extremos de asociación de la clase.
- prueba de aceptación f
- Prueba que tiene por objetivo determinar si el sistema se adecua a los requisitos de los clientes y, por lo tanto, si estos aceptarán o no el sistema desarrollado. Por definición, pues, es una prueba de sistema.
- radiador de información m
- Herramienta utilizada en entornos de desarrollo ágil para representar información relevante para el desarrollo, como por ejemplo los requisitos. Se trata de un elemento visual ubicado de tal manera que las personas lo tienen visible mientras trabajan o cuando pasar por delante de él.
- requisito m
- Condición exigida o necesaria para algo. En el campo de la ingeniería del software, necesidad o restricción que afecta a un producto de software definiendo qué soluciones son adecuadas (lo cumplen) y cuáles no (no lo cumplen) desde el punto de vista de dicha necesidad o restricción. Una solución será adecuada si satisface todos los requisitos del sistema.
- requisito candidato m
- Necesidades o restricciones obtenidas en una primera etapa de obtención de requisitos y que se convertirán en requisitos solo si son seleccionadas como tales a la hora de definir el alcance del proyecto por desarrollar.
- requisito funcional m
- Requisito que describe la funcionalidad esperada del sistema; es decir, que describe el comportamiento del sistema ante los estímulos que le llegan del exterior.
- requisito no funcional m
- Requisito que restringe el conjunto de soluciones posible, por lo general en forma de restricción, sin hablar de la funcionalidad.
- restricción de integridad f
- Limitación que se aplica sobre un modelo del dominio en el sentido de que no puede ser que el predicado no se satisfaga (es decir, se tiene que evaluar a cierto en cualquier momento).
- stakeholder m y f
- Persona o entidad con un interés sobre el producto que estamos desarrollando.