¡Buen dia! A modo de práctica para el parcial estoy intentando modelar los ejercicios de la guía en papel, acabo de terminar "El Ferrocarril" y me preguntaba si algunx tenía el tiempo (y las ganas) de darme algún tipo de feedback, lo re agradecería.
Dejo la consigna y la imagen con el intento
El Ferrocarril
Una empresa de servicios ferroviarios europea define los siguientes conceptos:
Tramo: es un recorrido entre dos ciudades sin cambio de tren, con o sin paradas intermedias. Cada tramo tiene un precio dependiendo del tipo de tren y categoría de pasaje (tipo: tren de alta velocidad, tren nocturno, tren común, etc.; categoría: primera, segunda).
Servicio adicional: es un servicio, no gratuito y optativo, que se puede adquirir junto con un tramo, pero que no se vende separado; por ejemplo: “cucheta coche dormitorio”, “cucheta en compartimiento privado”, “cena a bordo”. No se puede combinar cualquier ítem con cualquier adicional; por ejemplo, sólo se puede contratar cuchetas en trenes nocturnos.
Pasaje: es un derecho de viaje para uno o más pasajeros, para un tramo, o un tramo más uno o más adicionales. Su precio se calcula como suma de los precios de los componentes, por la cantidad de pasajeros. Todos los pasajeros viajan en el mismo tren y en la misma categoría.
Viaje promocional: es un conjunto de pasajes, que pueden incluir varios tramos y que tienen un precio promocional en conjunto; por ejemplo, puede haber un precio especial para la “5 pasajes entre París y Marsella, en TGV, segunda clase, viajando con cambio de tren en Lyon”. Los viajes promocionales tienen una vigencia: permanentes, por una estación del año, por día se semana o fin de semana.
Se debe:
- Modelar en UML (diagrama de clases) el problema recién descripto.
Sumo a la consulta lo que sería el cálculo del precio de un pasaje
Hola Lorenzo:
Te dejo mis comentarios acerca de tu modelo:
- No queda clara la responsabilidad de muchas de las clases que creaste. En especial todas aquellas que aparecen como cajas vacías (solo con el nombre) en el diagrama de clases. En ninguna clase describiste los métodos que tendría, que muy probablemente sean más interesantes que sus atributos. En particular son interesantes los métodos que usás en el diagrama de secuencia (es muy importante que todos los diagramas sean coherentes entre sí y con el código). Si querés ocultar información podés elegir prescindir de mostrar algunos atributos, dado que son privados y no importan tanto desde afuera. Lo que más importa es el contrato de cada clase, que queda evidenciado por los mensajes clave que entiende.
- Esto sucede especialmente en clases como "Permanente", "ConVencimiento", "Estado", "Activo", "Vencido", "Categoría", etc. No digo que necesariamente esté mal modelar esas clases, pero así como está no se entiende qué función cumplen en tu modelo. Es importante evidenciar su importancia dentro del modelo y demostrar que no son simples "contenedores de datos".
- Las relaciones de agregación están mal graficadas (el rombo va del otro lado, es decir, en el lado opuesto en el que pondrías una flecha).
- ¿Era necesario modelar una clase "Tipo"? ¿Por qué no hacer que TrenNocturno, TrenComún y TrenDeAltaVelocidad hereden directamente de Tren? (no digo que necesariamente está mal modelado, pero está mal que no se demuestre la necesidad de modelarlo de esa manera).
- ¿Por qué hay relaciones de agregación entre cada una de las clases de servicios y las clases de tipos de trenes correspondientes? Se entiende que es para resolver la parte de la consigna que dice que no se puede combinar cualquier ítem con cualquier adicional pero no se entiende cómo la relación de agregación soluciona eso en tu modelo.
- En el diagrama de secuencia aparecen dos clases (Empresa y Sistema) que no aparecen en el diagrama de clases. Esas clases no son necesarias; nunca se mencionan en el enunciado. Si querés modelar al usuario cliente lo mejor es graficar un mensaje encontrado, como se explica en las páginas 150 y 151 del libro. Se suele dibujar también una personita con palitos (opcionalmente).
- No se entiende por qué las cajas de iteraciones llegan hasta tan arriba. Además, si quisieras hacer loops anidados deberías dibujar una caja de loop adentro de la otra y no al lado.
- Recordá que cada caja principal del diagrama de secuencia representa a un objeto y no a una clase.
Saludos,
Tomás
Muchísimas gracias por todas las observaciones, me hicieron ver que mi modelo era bastante pobre y muy esquelético (creo que en algún punto lo quise llevar a algo como modelo de dominio pero ni siquiera). Me tomé el tiempo de corregir siguiendo los criterios que mencionabas en el diagrama de clases y ahora estoy trabajando con el de secuencia. ¡Nuevamente gracias!
Hola Lorenzo:
Fijate que parece que estás violando el principio "Tell, don't ask" en los métodos "compatibleCon" de cada uno de los trenes. Da la sensación de que esos métodos realizan una consulta y la decisión se hace en otro lado. De cualquier forma el diagrama no termina de dar los detalles suficientes como para que se entienda cómo se resuelve esa parte del problema.
Saludos,
Tomás
Hola Tomás! Los métodos compatibleCon(unServicio) son exclusivamente para determinar si ese tren brinda unServicio. El método incluso podría ser heredado de la clase tren y únicamente redefinir la colección de serviciosValidos en cada tren en particular. No es que se vaya a usar en el diagrama de secuencia, sino que es parte del modelo por la consigna predicar que "No cualquier servicio puede ser dado por cualquier tren" de manera que si un cliente quisiera comprar un tren con cama en uno que no sea nocturno, se lanzaría una excepción. Entiendo que quede muy colgado (por no haber acompañado con el diagrama de secuencia correspondiente)
Gracias por tomarte el tiempo, saludos!