Universidad Nacional de Educación a Distancia D EPARTAMENTO DE L ENGUAJES Y S ISTEMAS I NFORM ÁTICOS Fundamentos de Informática Práctica Obligatoria Curso 2014/2015 Índice general 1. Introducción 1.1. Descripción de la práctica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2. ETAPA 0 Diseño de la práctica: Diagrama de clases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 3 2. ETAPA 1 2.1. ETAPA 1.1 Orientación a Objetos: La clase Pelı́cula . . . 2.1.1. Objetivos . . . . . . . . . . . . . . . . . . . . . 2.1.2. Requisitos previos . . . . . . . . . . . . . . . . 2.1.3. Enunciado: Implementación de la clase Pelı́cula . 2.2. ETAPA 1.2 Ejecución de Aplicaciones: La clase Principal 2.2.1. Objetivos . . . . . . . . . . . . . . . . . . . . . 2.2.2. Requisitos previos . . . . . . . . . . . . . . . . 2.2.3. Enunciado: Creación de la clase principal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4 4 4 4 5 5 6 6 3. ETAPA 2 3.1. ETAPA 2.1 Composición: Salas y Sesiones . . . . . . . 3.1.1. Objetivos . . . . . . . . . . . . . . . . . . . . . 3.1.2. Requisitos previos . . . . . . . . . . . . . . . . 3.1.3. Enunciado: Creación de las clases Sala y Sesión . 3.2. ETAPA 2.2: Gestionando el cine . . . . . . . . . . . . . 3.2.1. Objetivos . . . . . . . . . . . . . . . . . . . . . 3.2.2. Requisitos previos . . . . . . . . . . . . . . . . 3.2.3. Enunciado: Implementando la clase Cine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 7 7 7 8 9 9 9 9 . . . . . . . . . . . . . . . . 10 10 10 10 10 11 11 11 11 12 12 12 12 13 13 13 13 4. ETAPA 3 4.1. ETAPA 3.1: Vendiendo entradas . . . . . . . . . . . . . . . . . . . . . . . 4.1.1. Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.2. Requisitos previos . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.3. Enunciado: Añadir funcionalidad de venta de entradas . . . . . . . 4.2. ETAPA 3.2: Herencia y Polimorfismo: añadiendo distintos tipos de entradas 4.2.1. Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.2. Requisitos previos . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.3. Enunciado: Implementando entradas del dı́a del espectador . . . . . 4.3. ETAPA 3.3: Ordenando las entradas vendidas . . . . . . . . . . . . . . . . 4.3.1. Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.2. Requisitos previos . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.3. Enunciado: Ordenando las entradas vendidas respecto a las pelı́culas 4.4. ETAPA 3.4: Mejorando el diseño para la reutilización de código . . . . . . 4.4.1. Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4.2. Requisitos previos . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4.3. Enunciado: Reutilizando la cartelera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Í NDICE GENERAL 5. Fechas y normas de entrega 5.1. Fechas . . . . . . . . . . . . 5.2. Normas de entrega . . . . . 5.3. Evaluación de la práctica . . 5.4. Preguntas al equipo docente 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 14 14 15 15 Capı́tulo 1 Introducción La práctica se realizará utilizando Java como lenguaje de programación orientado a objetos. El primer concepto que se debe conocer para programar utilizando el paradigma orientado a objetos es el de objeto. En este paradigma, todo está basado en los objetos, que tienen vida cuando nuestro programa está en ejecución. Por tanto, un programa Java se diseñará en base a objetos, que además, podrán relacionarse entre si de diversas maneras, proporcionando al programador las funcionalidades necesarias para resolver una amplia gama de problemas. La definición de un objeto viene dada por lo que se conoce como clase, siendo esta la entidad que en realidad diseñaremos y programaremos, en términos de sus campos o atributos y métodos. Estos campos y métodos nos permiten definir las caracterı́sticas y funcionalidades de la clase. Una vez definida, a partir de la clase podremos crear objetos, que son los que en realidad llevarán a cabo la funcionalidad de nuestro programa en tiempo de ejecución. Por tanto, podemos ver los objetos como los componentes que nos servirán para diseñar nuestro programa, y las clases como las definiciones de dichos objetos. Una misma clase puede por tanto dar lugar a muchos objetos diferentes, cada uno con caracterı́sticas diferentes que vendrán dadas por los valores de sus campos. 1.1. Descripción de la práctica El objetivo principal de esta práctica es el diseño e implementación de una parte de la funcionalidad de un gestor de un cine multi-sala. En el sistema que vamos a desarrollar nos centraremos en dos operaciones básicas que se pueden realizar en un gestor de un cine: gestionar todo lo relativo a la cartelera de pelı́culas que se están proyectando y gestionar la venta de entradas para las distintas sesiones. Además, se tendrá que tratar alguna funcionalidad sencilla referente a las butacas disponibles para las distintas sesiones de las salas. Para la realización de la práctica seguiremos un enfoque iterativo, es decir, el desarrollo se dividirá en etapas. En cada etapa partiremos del diseño y desarrollo de la etapa inmediatamente anterior, añadiéndole nuevas funcionalidades, poniendo en juego los conceptos del temario que se van estudiando progresivamente. RECOMENDACIÓN: la práctica se realiza a lo largo del cuatrimestre y forma parte del estudio de la asignatura. Para cada etapa se indican fechas de entrega. Es conveniente hacer una primera lectura completa de este documento para tener una visión global de lo que se solicita, y organizar adecuadamente el estudio de la asignatura. 1.2. ETAPA 0 Diseño de la práctica: Diagrama de clases Cuando afrontamos el desarrollo de una aplicación informática, es indispensable y necesaria realizar una fase previa donde se analicen los requisitos y diseñen las entidades, en nuestro caso clases, necesarias para llevar a cabo las funcionalidades requeridas, ası́ como la relación entre las mismas. Para llevar a cabo esta tarea, antes de comenzar a implementar cada una de las etapas en las que ha sido dividida la práctica, se debe realizar una lectura completa de la etapa a abordar, realizando un diagrama de clases donde se representen las clases necesarias, con sus atributos y métodos, y cómo se relacionan entre ellas, para posteriormente comenzar la fase de implementación de las mismas. Por tanto, se debe realizar un primer diagrama de clases en la primera etapa, que posteriormente se irá refinando y/o modificando en cada una de las siguientes etapas, siempre como requisito previo a comenzar a implementar el código de la etapa. El diagrama de clases obtenido en la última etapa debe ser entregado junto al código de la práctica. 3 Capı́tulo 2 ETAPA 1 2.1. ETAPA 1.1 Orientación a Objetos: La clase Pelı́cula 2.1.1. Objetivos En esta primera etapa de la práctica se van a afianzar los conceptos básicos de la programación orientada a objetos: clase, objeto, atributos y métodos (constructores, métodos que ayudan a la encapsulación de la clase y métodos de visualización). Además, se hará uso de tipos enumerados para definir el conjunto de valores que puede tomar un atributo. Veámoslo con un ejemplo que nos permita comenzar esta primera etapa de la práctica. Como ya hemos mencionado en la sección 1.1 la práctica consiste en el diseño e implementación de un gestor de un cine multisala, por tanto, una entidad básica en este dominio es la pelı́cula. Es decir, nuestro gestor debe ser capaz de manejar información relativa a las pelı́culas que forman la cartelera del cine. Para ello, vamos a empezar la práctica diseñando e implementando una clase denominada pelı́cula, que nos permita encapsular la información de las distintas pelı́culas que se van a proyectar en el cine. De esta manera, cada pelı́cula concreta será modelada mediante un objeto de dicha clase, con sus caracterı́sticas especı́ficas para los atributos definidos por la propia clase. Ası́ pues, el objetivo de esta etapa será la definición de una clase que represente a las pelı́culas que conformen la cartelera del cine. 2.1.2. Requisitos previos Para la realización de esta primera etapa se requiere haber estudiado los temas 4, 5 y 6 del temario detallado de la asignatura, correspondientes a los capı́tulos 1, 2 y 3, ası́ como el apartado 6.13.1 y los apéndices A, B, C, D y F del libro de referencia de la Unidad Didáctica II. 2.1.3. Enunciado: Implementación de la clase Pelı́cula En esta primera etapa realizaremos el modelado inicial de alguno de los componentes principales del sistema. Como ya hemos explicado, uno de estos elementos son las pelı́culas que tiene en cartelera la sala de cine, y que como hemos comentado serán modeladas como objetos. Ası́ pues, necesitaremos definir una clase denominada pelı́cula que nos permita crear las distintas instancias. En el sistema que queremos implementar cada pelı́cula se caracteriza por los siguientes atributos: Tı́tulo, este campo representa el tı́tulo de la pelı́cula. Director, representando al director de la misma. Año, este atributo identifica el año de estreno de la pelı́cula. Sinopsis, representa un breve resumen de la pelı́cula. Género, este atributo permite almacenar el género de la pelı́cula. Para simplificar el problema asumiremos que este atributo únicamente puede tomar los valores: COMEDIA, ACCIÓN, TERROR y CIENCIA FICCIÓN. Además, un objeto de esta clase Pelı́cula nos debe permitir consultar y modificar todos estos campos a través de una serie de métodos creados a tal efecto: por cada atributo debe haber dos métodos, uno para consultar su valor y otro para modificarlo. Por ejemplo, para el campo tı́tulo tendremos los métodos getTitulo() y setTitulo() para consultar su valor y modificarlo, respectivamente. Asimismo, deberá existir un método, llamado mostrarInfoPelicula(), que escriba por pantalla la información de una 4 2.2. ETAPA 1.2 E JECUCI ÓN DE A PLICACIONES : L A CLASE P RINCIPAL pelı́cula concreta, con un formato legible como, por ejemplo, el mostrado en la figura 2.1. Para ello, podemos hacer uso del método System.out.println() sobre el que podemos encontrar información en el capı́tulo 2.9 del libro de texto. Pelı́cula: <Tı́tulo de la pelı́cula> Director: <Director> Año: <Año de estreno> Género: <Género> Sinopsis: <Sinopsis> Figura 2.1: Formato de salida por pantalla con la información de una pelı́cula El texto entre los sı́mbolos ’<’ y ’>’ representa el valor de los atributos correspondientes a la clase pelı́cula. RECOMENDACIÓN: jugar con BlueJ creando objetos de la clase pelı́cula, modificando el valor de sus atributos, mostrándolos por pantalla, etc. 2.2. ETAPA 1.2 Ejecución de Aplicaciones: La clase Principal 2.2.1. Objetivos Es importante comprender que Java y BlueJ son cosas diferentes. Java es un lenguaje de programación, mientras que BlueJ es un entorno de programación que nos permite programar en Java. BlueJ está pensado para el aprendizaje de Java, y proporciona distintas herramientas que permiten inspeccionar las partes de un programa, tanto en la parte de diseño (cuando estamos escribiendo el código) como en la de ejecución (cuando el código se ejecuta, se crean los objetos en memoria, etc.) Una de las herramientas de BlueJ que pueden resultar más útiles es el banco de objetos u object bench (capı́tulo 1 del libro), que en conjunto con otras herramientas como el inspector de objetos, resulta muy interesante para jugar con los objetos en tiempo de ejecución de forma interactiva. Podemos ver un ejemplo de los mismos en la figura 2.2, donde se muestran varios objetos de la clase pelı́cula en el banco de objetos y uno de ellos es inspeccionado mostrando los valores de sus atributos Figura 2.2: BlueJ con varias pelı́culas creadas en el banco de objetos BlueJ nos permite ejecutar nuestras aplicaciones mediante la invocación de los métodos de sus objetos, pero no es ésta la única manera de hacerlo. Java, más allá de BlueJ, nos permite ejecutar los programas que creamos de forma independiente. A 5 C AP ÍTULO 2. ETAPA 1 estas alturas sabemos que cada clase dispone de una serie de métodos y campos, que son propios de los objetos que creamos a partir de dicha clase, es decir, que para poderlos utilizar necesitamos crear primero un objeto. Por ejemplo, la clase Pelı́cula que hemos creado, tiene un método para consultar su tı́tulo, que sólo podrá ser invocado una vez tengamos algún objeto de esta clase. Pues bien, existe otro tipo de métodos que no son propios de los objetos, sino de las clases. De esta forma, no necesitamos una instancia particular de la clase para invocarlos. La ejecución fuera de BlueJ comienza sin que exista ningún objeto (en BlueJ primero se creaban objetos que se almacenan en el banco de objetos para posteriormente invocar sus métodos). Antes de tener objetos, lo único que tenemos son las clases que los definen, por lo que deberemos usar un método de clase para poder iniciar la ejecución. Un caso particular de estos métodos de clase es el método main, que es el que se utiliza como punto de partida para iniciar la ejecución de un programa en Java (véase el apartado 2.2.2). RECOMENDACIÓN: Al final de este apartado deberı́a entender la diferencia entre ejecutar un programa en BlueJ y hacerlo de forma independiente, esto es, por ejemplo, ejecutarlo desde la lı́nea de comandos (sı́mbolo de sistema en Windows). 2.2.2. Requisitos previos Además de los expuestos en la sección 2.2.1, debe consultarse el libro de texto, capı́tulo 6.15, sobre métodos de clase. Además, en el apéndice E del libro de texto puede encontrar más información sobre el método main(), en concreto en el apartado E1. Puede consultar también el capı́tulo 3.9 “Objetos que crean objetos” del libro de texto si necesita más información acerca de la creación de objetos desde el código. 2.2.3. Enunciado: Creación de la clase principal Para ejecutar nuestro programa de manera independiente de BlueJ y crear el flujo principal del sistema, crearemos una clase llamada Principal, donde implementaremos el método main(). Esta clase por tanto será la encargada de crear el gestor del cine, las pelı́culas, etc. y de realizar simulaciones de operaciones (todo esto se realizará en posteriores etapas). En esta etapa debe implementar el método main() y crear unas cuantas pelı́culas, con sus respectivos valores de sus atributos, para después modificar estos valores mediante los métodos creados para tal efecto. Para ver los cambios realizados puede utilizar el método mostrarInfoPelicula() creado anteriormente. Ejecute el programa tanto desde BlueJ como desde la lı́nea de comandos (terminal o sı́mbolo de sistema dependiendo del sistema operativo que utilice). NOTA IMPORTANTE: La presente práctica debe poderse ejecutar independientemente de BlueJ de cara a su entrega y corrección. 6 Capı́tulo 3 ETAPA 2 3.1. ETAPA 2.1 Composición: Salas y Sesiones 3.1.1. Objetivos Una manera muy usual de relacionarse los objetos en la programación orientada a objetos es mediante la composición. Esta relación se produce cuando un objeto contiene a otros objetos para realizar alguna tarea con ellos. En Java tenemos distintas estructuras de datos para almacenar objetos permitiéndonos realizar estas relaciones de composición. Algunos ejemplos son las listas, los conjuntos o los mapas. De este modo, en esta etapa haremos uso de la composición para representar la relación que existe entre cada sala del cine y las sesiones que en ella se proyectan. En la figura 3.1 podemos observar la relación de composición que existe entre las salas del cine y las sesiones que se proyectan en cada una de las salas. Sala int id int butacas List<Sesion> sesiones eliminarSesion(Date fecha) añadirSesion(Sesion sesion) Sesión getSesion(Date fecha) mostrarInfoSesiones() mostrarInfoSesion(Date fecha) Sesion Date fecha Pelicula pelicula int butacas int butacas_disponibles actualizarButacasVendidas(int vendidas) mostrarInfoSesion() Figura 3.1: Diagrama de clases representando la relación entre una sala y las sesiones que se proyectan en dicha sala Por otro lado, es una buena práctica de programación documentar todo el código que se va realizando, no sólo con el objetivo de que terceras personas puedan comprender nuestro programa, sino también para que nosotros mismos podamos entender nuestro código de cara a futuras extensiones, mejoras o modificaciones. Para la generación de documentación, Java nos ofrece la herramienta Javadoc, que por medio de determinado tipo de comentarios añadidos en nuestro código fuente, nos permite la generación posterior de toda la documentación de las distintas clases. 3.1.2. Requisitos previos Para la realización de esta etapa se deben estudiar los temas 7, 8 y 9 del temario detallado de la asignatura. Encontrará información más detallada sobre el mecanismo de composición y la generación de documentación en el libro de texto de la asignatura en los capı́tulos 4 y 5. Las lecturas de las secciones de 6.3 a 6.6 (ambas inclusive) sobre buenas prácticas en el diseño de aplicaciones es también recomendable. 7 C AP ÍTULO 3. ETAPA 2 3.1.3. Enunciado: Creación de las clases Sala y Sesión RECOMENDACIÓN: Lea primero los requisitos completos antes de tomar decisiones acerca de cómo desarrollar la solución. Como hemos introducido previamente, nuestra aplicación va a gestionar un cine multisala, donde en cada sala se proyectarán diversas pelı́culas en cada una de sus sesiones. Por tanto, lo primero que necesitamos en esta etapa es crear una nueva clase Sesion que debe tener las siguientes funcionalidades: 1. cada sesión está identificada por la fecha en la que se proyecta. Esta fecha debe estar compuesta por el dı́a, mes, año y la hora y minutos de comienzo de dicha sesión. 2. Como hemos dicho, en cada sesión se proyecta una pelı́cula, por tanto es necesario almacenar la misma. 3. En cada sesión se debe almacenar el número de butacas que tiene de capacidad. Este número vendrá determinado por la sala en la que se proyecta la sesión. 4. También se desea almacenar el número de butacas que tiene disponible cada sesión, es decir, el total de butacas que tiene la sesión, menos las butacas que se hayan vendido (esta funcionalidad se verá en las siguientes etapas). Para cumplir con esta funcionalidad deberemos implementar un método denominado actualizarButacasVendidas(int vendidas) que actualice el número de butacas disponibles, con el argumento que reciba indicando las butacas que se han vendido. 5. Cada sesión debe contener un método denominado mostrarInfoSesion() que muestre por pantalla la información de la sesión (de manera similar a lo realizado en la clase pelı́cula en la etapa anterior). 6. Para facilitar la funcionalidad del sistema, queremos almacenar en cada sesión la sala en la que se proyecta (a continuación se especificará dicha clase.) Por otro lado, vamos a necesitar el concepto de sala del cine, por tanto, vamos a crear una nueva clase denominada Sala que: 1. esté identificada por un número, el número de sala. Este atributo no se debe poder modificar, pero sı́ consultar. Para ello se debe proporcionar como atributo en el constructor de la clase Sala; 2. almacene la capacidad de dicha sala, es decir, el número de butacas que tiene; 3. almacene las sesiones que se proyectan en dicha sala. Para ello se podrá usar cualquier estructura que nos permita almacenar un conjunto de objetos; 4. sea capaz de eliminar una sesión concreta a partir de su fecha de proyección; 5. añadir una nueva sesión de proyección en dicha sala; 6. devolver la sesión, a partir de la fecha de proyección; 7. mostrar por pantalla la información de todas las sesiones que se proyectan en la sala. Esta funcionalidad se encapsulará en un método denominado mostrarInfoSesiones(); 8. mostrar por pantalla la información de una sesión concreta, identificada por la fecha de su proyección. Para ello, utilizaremos un método llamado mostrarInfoSesion(Date fecha) que reciba como parámetro la fecha de proyección de la sesión que queremos mostrar. A la hora de desarrollar una aplicación informática es muy importante el manejo de los errores, es decir, contemplar las situaciones anómalas en las que la propia aplicación se podrá encontrar. Por tanto, además de las funcionalidades pedidas, se deben manejar, en las propias clases creadas, los casos anómalos producidos por algún error. Ası́ pues, contemplaremos casos como por ejemplo intentar eliminar una sesión de una fecha que no existe en la sala, disminuir el número de butacas disponibles en una sesión con un número mayor que el disponible, etc. Estos casos se deben gestionar informando de esta situación, por ejemplo mostrando un mensaje al usuario, para lo que se puede utilizar el propio método System.out.println. En esta etapa se deben documentar todas las clases creadas hasta ahora. En el apartado 5.10.2 del libro de texto se detalla la mı́nima documentación que se deberı́a incluir. Por último, vamos a modificar el método main() creado en la etapa anterior de tal manera que ahora creemos distintas sesiones donde se proyecten pelı́culas, y se asocien a distintas salas creadas previamente. A continuación, añada nuevas sesiones a una sesión, busque alguna sesión concreta y muestre su información por pantalla, elimine alguna de las sesiones de una sala y muestre por pantalla la información de todas las sesiones de la sala, comprobando que ha sido eliminada correctamente la sesión elegida. 8 3.2. ETAPA 2.2: G ESTIONANDO EL CINE 3.2. ETAPA 2.2: Gestionando el cine 3.2.1. Objetivos El objetivo de esta etapa es la implementación del propio gestor del cine multisala. En concreto vamos a implementar varias funcionalidades básicas, como son: la gestión de la cartelera del cine, de las salas y las sesiones que se proyectan. 3.2.2. Requisitos previos Para la realización de esta etapa es necesario dominar los conceptos de objeto, clase y composición estudiados hasta este punto. 3.2.3. Enunciado: Implementando la clase Cine En esta etapa vamos a crear la clase que nos permita realizar la gestión del cine. Para ello, debemos crear una nueva clase denominada Cine con la siguiente funcionalidad: 1. debe tener un atributo que permita almacenar el nombre del cine; 2. también queremos almacenar la dirección donde se encuentra el cine; 3. debe almacenar la cartelera que tiene en cada momento. La cartelera está compuesta por el conjunto de pelı́culas que se están proyectando en el cine, es decir, un conjunto de objetos de la clase Pelı́cula; 4. debe almacenar el conjunto de salas que conforman el cine; 5. debe ser capaz de mostrar la cartelera, es decir, la información del conjunto de pelı́culas que tiene en cartel; 6. debe permitir la gestión de la cartelera, es decir, añadir y eliminar pelı́culas del conjunto que forman la cartelera del cine. Se debe tener en cuenta que cuando una pelı́cula es eliminada de la cartelera, se deben eliminar todas las sesiones en las que se proyecta dicha pelı́cula; 7. debe permitir la gestión de las salas del cine, es decir, añadir y eliminar salas del cine. Igualmente que con las pelı́culas, al eliminar una sala desaparecerán todas sus sesiones; 8. debe permitir la asignación de la proyección de una pelı́cula en una sesión en una sala concreta. Se debe tener en cuenta que al asociar una sesión a una sala, las butacas de la sesión se deben actualizar con la capacidad que tiene la sala donde se va a proyectar; 9. debe permitir la eliminación de una sesión concreta, dado su fecha de proyección, de una sala concreta; 10. debe mostrar la información de las sesiones en las que se proyecta una pelı́cula, dado el tı́tulo de la pelı́cula; 11. debe mostrar la información de las pelı́culas que se proyectan en una fecha concreta (dı́a, mes y año). Ahora modifique la clase Principal para crear un cine, es decir, cree un objeto de la clase Cine, cree varias salas en el cine, cree varias pelı́culas y actualice la cartelera del cine con dichas pelı́culas. Ahora cree sesiones donde se proyecten alguna de las pelı́culas en cartel y ası́gnelas a alguna de las salas del cine. Muestre la información de la cartelera del cine, las sesiones en las que se está proyectando alguna de las pelı́culas que hay en cartel y las pelı́culas que se están proyectando en una fecha concreta que tenga alguna sesión. A continuación modifique la cartelera del cine, eliminando alguna de las pelı́culas y muestre nuevamente la información de las sesiones en las que se proyecta dicha pelı́cula. Elimine alguna sesión y/o sala y muestre nuevamente la información. Recordamos que además de la funcionalidad solicitada, se deben controlar los posibles errores, en este caso se debe contemplar, por ejemplo, que una pelı́cula se está proyectando en alguna sesión, que en la fecha solicitada existe alguna sesión, que la sala que se desea eliminar existe o que la pelı́cula que se desea eliminar existe en la cartelera. Todos los errores que se manejen se deben gestionar informando al usuario mediante un mensaje, utilizando el método System.out.println. 9 Capı́tulo 4 ETAPA 3 4.1. ETAPA 3.1: Vendiendo entradas 4.1.1. Objetivos En esta parte de la práctica vamos a extender el sistema para que nos permita realizar operaciones de venta de entradas para las sesiones del cine. Para esto necesitaremos incluir el concepto de entrada, lo que nos llevará a crear una nueva clase que nos permita representar una entrada para una sesión concreta. Además, se deberá modificar la funcionalidad del gestor del cine para que permita realizar operaciones de venta de entradas, manteniendo actualizado el número de butacas disponibles para las distintas sesiones. 4.1.2. Requisitos previos Para llevar a cabo esta última etapa es recomendable un alto dominio de los conceptos de objeto, clase y composición estudiados hasta este punto. 4.1.3. Enunciado: Añadir funcionalidad de venta de entradas Como hemos introducido previamente, para extender la funcionalidad de nuestro programa permitiendo la venta de entradas para las sesiones del cine, lo primero que necesitamos es la creación de una nueva clase denominada Entrada con las siguientes caracterı́sticas y funcionalidad: 1. cada entrada permite el acceso a la sesión donde se proyecta una pelı́cula de la cartelera del cine; 2. cada entrada representa una butaca de carácter general que tiene un precio asociado y que es constante para todas las entradas; 3. las entradas deben tener un método denominado getPrecio() que devuelva lo que cuesta cada entrada, en este caso, al ser entradas de carácter general todas devolverán el mismo precio. Una vez que hemos añadido el concepto de entrada a nuestro programa, debemos añadir la funcionalidad que nos permita realizar la venta de entradas para las distintas sesiones y llevar un registro de las mismas. Para ello, debemos añadir la siguientes funcionalidades a la clase que representa el gestor del cine (clase Cine) : 1. almacenar el conjunto de entradas que se vendan en el sistema, para permitir llevar un registro de las mismas y mostrar datos de interés; 2. debe permitir la realización de una venta de un número x de entradas para una sesión concreta, es decir, para una fecha y una pelı́cula concreta. En primer lugar se debe comprobar que existe en el cine alguna sesión con dichos datos, es decir, que en la fecha pedida se proyectará la pelı́cula que se pide. En caso afirmativo, se debe comprobar que el número de entradas pedidas no excede el número de butacas disponibles para esa sesión. Por último, se deberán crear tantos objetos de la clase entrada como cantidad de entradas se desean comprar, para posteriormente almacenarlas y actualizar el número de butacas disponibles de la sesión concreta; 3. limitar el número máximo de entradas vendidas en una transacción a 6. Es decir, sólo se podrán comprar 6 entradas al mismo tiempo, en la misma invocación de la operación; 4. mostrar recaudación total para una pelı́cula. Se mostrará el dinero recaudado con la venta de entradas para todas las sesiones en las que se proyecta la pelı́cula. Para ello se proporcionará únicamente el tı́tulo de la pelı́cula sobre la que se desea consultar. 10 4.2. ETAPA 3.2: H ERENCIA Y P OLIMORFISMO : A ÑADIENDO DISTINTOS TIPOS DE ENTRADAS Es importante destacar que en todo momento estamos asumiendo que las sesiones y, por tanto las entradas, no son numeradas. Es decir, lo único que se debe tener en cuenta es el número de butacas disponibles en cada sesión. RECORDATORIO: Recuerde realizar la gestión de los posibles errores, informando al usuario de ellos, ası́ como la documentación de todas las clases implementadas. 4.2. ETAPA 3.2: Herencia y Polimorfismo: añadiendo distintos tipos de entradas 4.2.1. Objetivos El siguiente paso en la práctica es añadir distintos tipos de entradas con un precio reducido, por ejemplo cuando la sesión coincida en un dı́a concreto de la semana, declarado como el dı́a del espectador o entrada reducida para niños. Estas entradas son idénticas que las creadas hasta el momento, con la única peculiaridad del precio, que tendrá una reducción sobre el precio de las entradas generales. Por tanto, estas nuevas entradas podrán ser modeladas como un tipo especial de las entradas generales, con la particularidad de la reducción que tendrá cada una de ellas sobre el precio original. Para este tipo de situaciones, los lenguajes orientados a objetos, como Java, disponen de un mecanismo llamado herencia. La herencia nos permite construir una nueva clase heredando las caracterı́sticas de una clase ya existente. Por tanto, la clase “heredera” o “hija” tiene toda la funcionalidad de la clase de la que hereda, clase “padre”, permitiendo además la inclusión de nuevos métodos y campos para extender dicha funcionalidad. Además de la herencia, en la programación orientada a objetos disponemos del polimorfismo. Como la propia palabra indica, polimorfismo se refiere a la posibilidad de que un elemento tenga varias formas. En Java podemos tener polimorfismo en varias entidades: atributos o variables y métodos. En el caso de las variables, el polimorfismo permite que una variable pueda contener objetos de diferentes clases, ya sea de la propia clase declarada o de cualquier clase que herede de ésta. Por ejemplo, si declaramos la siguiente variable: Entrada e; y definimos una nueva clase EntradaDiaEspectador heredando de la clase Entrada, la variable e puede contener tanto objetos de la clase Entrada como de la clase EntradaDiaEspectador. El otro tipo de polimorfismo que podemos tener en Java es a nivel de método, de tal forma que una llamada a un método puede invocar diferentes métodos dependiendo, como en el caso anterior, del contexto. El método invocado dependerá del tipo dinámico de la variable usada para hacer la invocación. Por tanto, el objetivo de esta etapa es implementar un nuevo tipo de entrada llamado EntradaDiaEspectador, que tendrán una reducción del 40 % sobre el precio de la entrada general. Para ello, declararemos como dı́a del espectador los jueves. Es decir, todas las entradas que se vendan para una sesión cuya fecha coincida en jueves, serán de dicho tipo, en lugar del tipo general. 4.2.2. Requisitos previos Para la realización de esta etapa se requiere haber estudiado el tema 10 del temario detallado de la asignatura, y los capı́tulos 7 y 8 del libro de texto para todo lo relacionado con la herencia. Para entender el mecanismo de polimorfismo se requiere haber estudiado los temas 10, 11 y 12 del temario detallado de la asignatura, que corresponden a las Secciones de la 6.3 a la 6.6, y los Capı́tulos 6, 8 y 9 del libro base para la Unidad Didáctica II. En concreto, la sección 8.7.4 y relacionadas; y el capı́tulo 9; particularmente el apartado 9.6 y relacionados. 4.2.3. Enunciado: Implementando entradas del dı́a del espectador Como ya hemos explicado anteriormente, vamos a añadir a nuestro programa un nuevo tipo de entrada. La diferencia entre una entrada general implementada en las etapas anteriores y la nueva entrada del dı́a del espectador debe ser el precio, en concreto, el segundo tipo será un 40 % más barata que la entrada general. Teniendo en cuenta esto, debe crear una nueva clase EntradaDiaEspectador que nos permita almacenar el porcentaje de descuento, respecto al precio de la entrada general. Este valor debe ser constante y el mismo para todos los objetos de la clase. Por tanto, el método encargado de devolver el precio de una entrada, en este caso debe ser capaz de calcular el nuevo precio en función de dicho descuento, para este nuevo tipo de entrada. La venta de este nuevo tipo de entradas será automática, es decir, se deberá modificar la funcionalidad del programa encargada 11 C AP ÍTULO 4. ETAPA 3 de realizar la venta de un número de entradas, para que cuando la sesión que se solicita coincida con el dı́a marcado como dı́a del espectador (el jueves), en lugar de generar entradas generales, se generarán entradas del dı́a del espectador. Por último modifique la clase Principal para realizar la venta de distintas entradas para sesiones que no coincidan con el dı́a del espectador, muestre la recaudación total y la de una pelı́cula concreta. A continuación, realice la venta de varias entradas para sesiones que coincidan en jueves y vuelva a mostrar la recaudación de las entradas vendidas. RECOMENDACIÓN: Se recomienda realizar distintas operaciones con el cine, desde la clase Principal del programa, para comprobar que la funcionalidad es correcta y que los posibles errores como consecuencia de búsquedas, eliminaciones, etc. incorrectas, son manejados y el usuario es informado de los mismos, mediante mensajes en pantalla. RECORDATORIO: De la misma manera, se recuerda la necesidad de documentar todas las clases generadas hasta el momento. 4.3. ETAPA 3.3 (Opcional para las especialidades de Mecánica y Tecnologı́a Industrial): Ordenando las entradas vendidas 4.3.1. Objetivos Esta última parte de la práctica es de carácter opcional para las especialidades de Mecánica y Tecnologı́a Industrial y obligatoria para las otras dos especialidades. El objetivo de esta última etapa se centrará en extender la funcionalidad de la aplicación de manera que ésta sea más óptima y más “amistosa” para los usuarios encargados de utilizar el gestor del cine. Hasta el momento, las entradas vendidas son almacenadas en el orden en el que se realizó la venta de las mismas. Sin embargo, este orden puede influir negativamente si lo que queremos es facilitar el análisis de ventas al calcular, por ejemplo, las entradas vendidas para una pelı́cula concreta. Para conseguir esto de manera más eficiente, nos interesarı́a tener ordenadas por pelı́culas las entradas vendidas, de manera que nos permitiese saber más rápidamente las pelı́culas que más dinero recaudan. 4.3.2. Requisitos previos Para llevar a cabo esta etapa es recomendable haber estudiado y dominar todos los conceptos estudiados hasta este punto. 4.3.3. Enunciado: Ordenando las entradas vendidas respecto a las pelı́culas El objetivo de esta etapa es mostrar las entradas vendidas ordenadas en función de la pelı́cula. Para ello, tenemos dos opciones: almacenar las entradas con el orden deseado, es decir, en función de la pelı́cula, u ordenarlas en el momento de mostrarlas por pantalla. Si eligiésemos esta última opción, cada vez que se mostrase las entradas vendidas por cada pelı́cula deberı́amos recorrer toda la lista de entradas, buscando las que son de una pelı́cula concreta. Sin embargo, para evitar esta búsqueda, podemos almacenar las entradas directamente agrupadas por pelı́cula, lo que nos permitirá mostrar las entradas vendidas para cada una de ellas, recorriendo una única vez el conjunto de entradas. Para conseguir esto, podemos utilizar la misma estructura de datos que tenemos, pero modificando la manera en la que se almacenan las entradas. Ahora en lugar de simplemente añadirlas, tendremos que buscar previamente la posición en la lista donde comienzan a almacenarse las entradas de la pelı́cula que estamos buscando e insertarlas a partir de dicha posición. Recaudación por pelı́cula: Pelı́cula: <Tı́tulo de la pelı́cula> Entradas vendidas: <nº total entradas vendidas> Dinero recaudado: <total dinero recaudado> Pelı́cula: <Tı́tulo de la pelı́cula> Entradas vendidas: <nº total entradas vendidas> Dinero recaudado: <total dinero recaudado> Figura 4.1: Formato de salida por pantalla con la información de las entradas vendidas y la recaudación conseguida por cada pelı́cula Una vez realizada esta extensión, se debe implementar la funcionalidad que nos permita ver la recaudación total por pelı́culas. Es decir, se debe mostrar por cada pelı́cula el número de entradas vendidas y el dinero recaudado con la venta de 12 4.4. ETAPA 3.4: M EJORANDO EL DISE ÑO PARA LA REUTILIZACI ÓN DE C ÓDIGO dichas entradas. Para ello, se utilizará la mejora introducida al almacenar las entradas. En la figura 4.1 podemos observar un ejemplo de salida por pantalla que se mostrará con consecuencia de esta etapa. 4.4. ETAPA 3.4: Mejorando el diseño para la reutilización de código 4.4.1. Objetivos El objetivo de esta última etapa de la práctica es mejorar el diseño de la aplicación, con el objetivo de mejorar la futura posible reutilización del código, un aspecto éste muy importante en la programación orientada a objetos. Para facilitar la reutilización un factor clave es la cohesión de las entidades y la reducción del acoplamiento, reduciendo las dependencias entre las entidades que conforman el sistema, facilitando de esta manera las posibles modificaciones y extensiones futuras. 4.4.2. Requisitos previos Para llevar a cabo esta etapa es recomendable haber estudiado y dominar todos los conceptos estudiados hasta este punto, en concreto el capı́tulo 6 del libro base de la asignatura, donde se explican los conceptos de cohesión y acoplamiento para mejorar el diseño y la reutilización de clases. 4.4.3. Enunciado: Reutilizando la cartelera Imaginemos que, como desarrolladores de este sistema, queremos reutilizar parte del código del mismo, para realizar otro sistema en el mismo dominio del cine. En concreto, queremos reutilizar el concepto de cartelera, como un conjunto de pelı́culas que se están proyectando en un cine, el cual puede ser modificado añadiendo o eliminando pelı́culas del mismo. En este apartado debe pensar en cómo deberı́a diseñarse la cartelera para facilitar este hecho. En caso necesario, modifique el diseño, es decir, el diagrama de clases realizado hasta este momento, explicando los cambios necesarios que introducirı́a. En esta etapa no es necesario modificar el código, únicamente se debe modificar el diseño de la práctica, es decir, el diagrama de clases que debe entregar junto al código de la práctica, siempre que considere que es necesario. 13 Capı́tulo 5 Fechas y normas de entrega 5.1. Fechas La realización de la práctica se llevará a cabo en los centros asociados, siendo las sesiones organizadas y supervisadas por el tutor de la asignatura. Habrá como mı́nimo tres sesiones presenciales de obligatoria asistencia. En cada sesión se abordará cada una de las partes de las que consta la práctica. Los alumnos deberán ponerse en contacto con su centro asociado para informarse acerca de cuándo tendrán que asistir a las sesiones. Las fechas orientativas para la realización de cada una de las etapas serán: Finales de Marzo. Realización de la primera etapa. Finales de Abril. Realización de la segunda etapa. Mediados de Mayo. Realización de la tercera etapa. 5.2. Normas de entrega La entrega de cada etapa de la práctica constará de dos entregables: Una memoria de no más de 6 páginas donde se explique la especificación y el diseño realizados en cada parte de la práctica. Los ficheros fuente y el código compilado, ası́ como un fichero .jar que permita la ejecución de cada una de las etapas. NOTA IMPORTANTE: Los nombres de los ficheros y carpetas/paquetes que compongan la práctica entregada, deben contener SÓLO caracteres correspondientes a las letras de la A a la Z, tanto mayúsculas como minúsculas, números del 0 al 9 y los caracteres especiales ’-’ y ’ ’. No deben utilizarse otros, tales como tildes o sı́mbolos. Los tutores de la asignatura deberán mandar un informe1 y una calificación orientativa de cada alumno antes del dı́a 22 de Mayo de 2015. Además, deberán enviar mediante correo electrónio a la dirección rcenteno@lsi.uned.es) un fichero comprimido con el código fuente y objeto (ÚNICAMENTE DE LA ÚLTIMA ETAPA) de todas las prácticas de los alumnos de su centro asociado, de modo que el equipo docente pueda revisarlas2 . NOTA IMPORTANTE: Los tutores tienen que cumplir una serie de requisitos ante los alumnos debido a que la práctica cuenta para la calificación de la asignatura. Por tanto, antes de entregar las calificaciones al equipo docente deberán: 1. Publicar la nota de las prácticas en un lugar accesible para los alumnos (ya sea vı́a web o mandar un fax al centro asociado) 2. Establecer un dı́a de revisión de prácticas (previo al perı́odo de entrega de las calificaciones al equipo docente), dado que éstas forman parte de la evaluación del alumno. Es importante que se mantengan todos los identificadores definidos en el enunciado, es decir, el nombre de las clases, atributos y métodos deben ser tal y como se definen en este enunciado. 1 Los informes se mandarán al equipo docente a través de una herramienta Web que estará disponible a partir de Mayo. preparar dicho fichero deben seguir las pautas que aparecen en el documento Orientaciones para el tutor, que podrán encontrar en el foro de los tutores de la asignatura. 2 Para 14 5.3. E VALUACI ÓN DE LA PR ÁCTICA 5.3. Evaluación de la práctica Las prácticas tienen carácter INDIVIDUAL, para evitar posibles copias todas las prácticas pasarán por un software detector de copias. La detección de prácticas copiadas implicará un SUSPENSO en TODO el curso, es decir, convocatorias de Junio y Septiembre, para todos los implicados. Es requisito indispensable para aprobar el examen, la asistencia a las 3 sesiones obligatorias de la práctica, ası́ como superar la propia práctica. El informe del tutor se considera a efectos de subir nota. Las prácticas NO se guardan de un curso para otro. 5.4. Preguntas al equipo docente El equipo docente atenderá preguntas de carácter metodológico y de diseño, preferentemente a través de los foros del curso virtualº de la asignatura. Las preguntas relativas a la instalación del entorno de desarrollo, puesta en funcionamiento y errores de compilación deben ser remitidas a los tutores de los centros asociados. Felisa Verdejo Maillo, Catedrática de Universidad Tutorı́as: Jueves de 15:00 a 19:00 Teléfono: 91 398 64 84 Mail: felisa@lsi.uned.es Enrique Amigó Cabrera, Profesor Contratado Doctor Tutorı́as: Jueves de 15:00 a 19:00 Teléfono: 91 398 86 51 Mail: enrique@lsi.uned.es Victor Fresno Fernández, Profesor Contratado Doctor Tutorı́as: Jueves de 15:00 a 19:00 Teléfono: 91 398 82 17 Mail: vfresno@lsi.uned.es Roberto Centeno Sánchez, Profesor Ayudante Tutorı́as: Jueves de 15:00 a 19:00 Teléfono: 91 398 96 96 Mail: rcenteno@lsi.uned.es 15