Página 1 de 10
Enunciado
Teniendo en cuenta el siguiente modelo estático, correspondiente a los requisitos de información de un sistema de reservas de vuelos:
En el documento de requisitos, encontramos los siguientes extractos relativos a los requisitos funcionales del sistema:
Página 2 de 10
2) El caso de uso “Reservar Vuelos”
Se pide:
1) Expresar con OCL el cómputo del número de plazas libres, que se correspondería a “la capacidad de la aeronave que opera el vuelo menos el número de titulares que tiene cada reserva de dicho vuelo”.
2) Proponer un prototipo de interfaz de usuario para dicho caso de uso, suponiendo una aplicación móvil.
3) Obtener el diagrama secuencial correspondiente. 4) Definir mediante OCL las operaciones de sistema. 5) ¿Hay algún conflicto? ¿Qué aspectos pueden mejorar?
Página 3 de 10
SOLUCIÓN
1) Expresar con OCL el cómputo del número de plazas libres, que se correspondería a “la capacidad de la aeronave que opera el vuelo menos el número de titulares que tiene cada reserva de dicho vuelo”.
context Salida::libres: Integer
derive: libres = aeronave.capacidad
- vuelo.reserva->collect(titular->size())->sum()
Pero, ¿tiene sentido que “Reserva” y “Vuelo” estén relacionados?
Parece más razonable que se relacione con “Salida”…
Entonces
:
context Salida::libres: Integer
derive: libres = aeronave.capacidad
Página 4 de 10
2) Proponer un prototipo de interfaz de usuario para dicho caso de uso, suponiendo una aplicación móvil.
Página 5 de 10
Página 6 de 10
4) Definir mediante OCL las operaciones de sistema. Context Sistema::ObtenerAeropuertoInfo(fechaReserva: Date):
Bag(Tuple(codAeropOr:String; codAeropDst: String; plazas: Integer)) Pre: --
Body:
salida-> select(fecha = fechaReserva) ->collect(Tuple{
codAeropOr = vuelo.origen.cod, codAeropDst = vuelo.destino.cod, plazas = libres } )
¿Realmente estoy modelando adecuadamente el vuelo y cada una de las salidas que tiene un vuelo? Veamos la siguiente operación de sistema:
context Sistema::ObtenerVuelosInfo(codAeropOr: String; codAeropDst: String; fechaReserva: Date; horaReserva: Time): Bag(Tuple(codVuelo:String; HoraS: Time; FechaLl: Date; HoraLl:Time)) Pre:
aeropuerto->one(cod=codAeropOr) and aeropuerto->one(cod=codAeropDst) Body:
Let
aor: Aeropuerto = aeropuerto->any(cod = codAeropOr), adst: Aeropuerto = aeropuerto->any(cod = codAeropDst) in
salida->select(vuelo.origen = aor and adst = vuelo.destino
and fecha = fechaReserva and hora >= horaReserva) ->collect(Tuple{
codVuelo = vuelo.cod, horaS = hora,
fechaLl = vuelo.llegada.fecha,
Página 7 de 10
¿Qué devuelve exactamente la expresión “vuelo.llegada”? ¿Hay una llegada para cada salida? En realidad, la llegada es información derivada si renombramos “Salida” como “Operación” asociada a un “Vuelo” en una fecha y duración determinada.
context Sistema::ObtenerVuelosInfo(codAeropOr: String; codAeropDst: String; fechaReserva: Date; horaReserva: Time): Bag(Tuple(codVuelo:String; HoraS: Time; FechaLl: Date; HoraLl:Time)) Pre:
aeropuerto->one(cod=codAeropOr) and aeropuerto->one(cod=codAeropDst) Body:
Let
aor: Aeropuerto = aeropuerto->any(cod = codAeropOr), adst: Aeropuerto = aeropuerto->any(cod = codAeropDst) in
operación->select(vuelo.origen = aor and adst = vuelo.destino
and fecha = fechaReserva and vuelo.hora >= horaReserva) ->collect(Tuple{
codVuelo = vuelo.cod, horaS = vuelo.hora, fechaLl = fechaLleg, horaLl = horaLleg})
Página 8 de 10
context Sistema::GenerarReserva(fechaReserva: Date): Integer Pre: --
Post: Let
r: Reserva = reserva-> any(numero = nres), nres: Integer = reserva->size()@pre+1 in
r.oclIsNew() = true and r.numero = nres and
r.fechaRealización = fechaReserva and result = nres
context Sistema::AñadirVueloAReserva(nres: Integer; codV: String; fechaR: Date) Pre:
reserva->one(numero=nres) and
operación->one(vuelo.cod = codV and fecha = fechaR) // ¿Hay sólo uno? Post:
Let
r: Reserva = reserva -> any(numero=nres),
op: Operación = operación->any(vuelo.cod = codV and fecha = fechaR) in
r.operación->includes(op) and op.reserva->includes(r)
Página 9 de 10
context Sistema::AñadirTitularAReserva(nres: Integer; nomT:String) Pre: reserva->one(numero=nres) Post: Let r:Reserva = reserva->any(numero=nres), t:Titular in
t.oclIsNew() = true and titular->exists(nom = nomT) and t.nom = nomT and
r.titular->includes(t) and t.reserva->includes(r)
Página 10 de 10
5) ¿Hay algún conflicto? ¿Qué aspectos pueden mejorar?
a) Conocer desde el inicio el número de titulares, que se puede pedir en la primera pantalla de la aplicación
b) Pedir un rango de fechas para reservar de inicio, en lugar de una fecha c) Añadir la denominación de los aeropuertos, así como la información GPS
d) ¿Umbrales sobre cuántas plazas libres debe haber para que se muestren con otros colores los destinos posibles?
e) Añadir la información de precio de vuelos y las compañías, así como si tiene servicio de maletas o no incluido en el precio
f) ¿Cómo identificamos las operaciones concretas de un vuelo?
g) Especificar cómo se calcula el número de reservas, puesto que (temporalmente) el esquema de asignación es el más básico y propenso a errores ¿cuáles?
h) El último paso del caso de uso no es consistente con lo que propone la IU de la aplicación
i) ¿Vuelos con escalas?
j) ¿Se pueden repetir los titulares? En estos sistemas, sólo piden nombres y apellidos sin más, no siempre completos
k) ¿Tipos de asiento y número? ¿Política de precios dinámica?
Reflexión, conforme avanza el análisis, surgen múltiples cuestiones a resolver como se ha podido comprobar en clase, lo que obliga a modificar muchas cosas incluso en documentos anteriores que dábamos por “hechas”.