Programación 3

Universidad de Alicante, 2023–2024

Práctica 1

Peso relativo de está práctica en la nota de prácticas: 15%

Introducción a la programación orientada a objetos

En esta primera práctica trabajaremos los conceptos introducidos en la primera unidad de teoría. Para ello implementaremos las clases que describimos a continuación.

P1.1 Clase Coordinate

Implementa la clase Coordinate en el paquete es.ua.dlsi.prog3.p1 conforme se muestra en el UML adjunto. Esta clase representará coordenadas dentro de un espacio n-dimensional. Para que el espacio permita almacenar n dimensiones usaremos un array de elementos como componentes de la coordenada.

Figura 1. Diagrama de clases UML.
Figura 1. Diagrama de clases UML de la P1.1.

Los métodos deben cumplir los siguientes contratos:

  • Coordinate(double[]): en caso de que el array proporcionado sea null, se creará una coordenada de 0 dimensiones (this.components = new double[0])
  • getComponents: devuelve una copia defensiva de la propiedad components.
  • getDimensions: retorna el número de dimensiones que corresponde al tamaño del array components.
  • equals y hashCode: dos coordenadas se considerarán iguales cuando representan exactamente el mismo punto n-dimensional.

Deberás cumplir las siguientes restricciones:

  • La clase será inmutable. Lee el enlace Objetos inmutables para saber como hacer que una clase sea inmutable.

Aquí tienes una versión en C++ de la clase Coordinate, que puedes usar como ejemplo para ‘traducir’ a Java. Esta clase es como la de la práctica 1, excepto por que no tiene el método hashCode() y no cumple algunas condiciones para que la clase sea inmutable. Lee el fichero README.txt que acompaña al código en C++ para más detalles sobre las equivalencias (¡y diferencias!) entre C++ y Java.

P1.2 Clase SummaryStatistics

Implementa la clase SummaryStatistics en el paquete es.ua.dlsi.prog3.p1 conforme se muestra en el UML adjunto. La responsabilidad de esta clase es la de calcular valores estadísticos básicos a partir de la lista de enteros que almacena: máximo, mínimo, media y número de elementos. Se utiliza aritmética entera para calcular las estadísticas.

Figura 2. Diagrama de clases UML.
Figura 2. Diagrama de clases UML de la P1.2. El uso de ArrayList y el nombre del atributo del constructor no se suelen especificar de esta forma en UML. Lo hemos hecho de esta forma por ser ésta la primera práctica y no disponer todavía de los recursos necesarios para hacerlo de manera estándar.

Cada objeto creado tendrá un identificador id diferente. Para mantener la secuencia de identificadores únicos utilizaremos la propiedad de clase NEXT_ID. Esta propiedad será consultada por COUNT_INSTANCES() para saber cuántas instancias de la clase SummaryStatistics se han creado.

Los métodos deben cumplir los siguientes contratos:

  • Para que cada instancia tenga un id distinto, cualquier constructor asignará NEXT_ID al id del objeto a crear e incrementará el valor de NEXT_ID.
  • Tanto el constructor a partir del vector de enteros, como el de copia, realizarán copia defensiva, y por tanto profunda. Ten en cuenta que para realizar esta copia profunda sólo es necesario crear un nuevo ArrayList y podemos copiar las referencias a los valores Integer contenidos en él porque la clase Integer es inmutable.
  • getAverage: retorna la media de los valores almacenados en values. Si values está vacío devolverá null.
  • getMin: retorna el valor mínimo entre los valores almacenados en values. Si values está vacío devolverá null.
  • getMax: retorna el valor máximo entro los valores almacenados en values. Si values está vacío devolverá null.
  • add: añade un elemento a values en cualquier posición.
  • getSize: devuelve el número de elementos en values.
  • COUNT_INSTANCES() retorna el número de instancias creadas de la clase usando como base el valor NEXT_ID.

Deberás asimismo cumplir las siguientes restricciones:

  • Para implementar getMin y getMax debes apoyarte de los métodos elementos de las librerías de Java. Sólo se usará un condicional if o el operador ternario ?: para comprobar si el array values está vacío.
  • En el constructor, el nombre del parámetro debe ser obligatoriamente values.

Pruebas unitarias

Proporcionamos pruebas unitarias en el siguiente fichero que comprueban parcialmente el adecuado comportamiento de las clases. Los test usados en la corrección serán más exhaustivos. Es importante que entiendas qué se prueba y cómo se hace.

Documentación

Este apartado no se realizará en el control

Debes incluir en los ficheros fuente todos los comentarios necesarios en formato javadoc. Estos comentarios deben definirse para:  

  • Ficheros: debe incluir nombre y dni de los autores usando la anotación @author
  • Clases: propósito de la clase: mínimo 3 líneas
  • Operaciones/métodos: 1 línea para funciones triviales, y un mímimo de 2 líneas, parámetros de entrada, parámetros de salida y funciones dependientes para operaciones más complejas.
  • Atributos: propósito de cada uno de ellos: como mínimo 1 línea  

Documenta además los siguientes aspectos:

  • Indica si los atributos y métodos son de instancia o de clase (excepto constructores).
  • Para cada constructor que definas, indica si es constructor por defecto, sobrecargado o constructor de copia.
  • Indica si el constructor de copia realiza copia superficial o profunda.
  • Indica que estás usando copia defensiva allí donde lo hagas.
  • Indica cuando se realiza boxing o unboxing (implícito o explícito) en la sentencia donde se use.
  • Indica, para cada argumento de un método, si se pasa por valor o por referencia.
  • Explica en el javadoc de la clase cómo has conseguido que la clase Coordinate sea inmutable

Puedes usar un comentario no javadoc cuando sea necesario. Véase el siguiente ejemplo:


/**
    Esta clase es un ejemplo de....
    Para hacer la clase inmutable ...
*/
class Example {
    
    /**
    *    Constructor por defecto
    */
    public Example() {
        Integer i = 3 ; // boxing
    } 
    
    /**
    * Atributo de instancia
    * Almacena el estado de bla, bla...
    */
    private int a; 

    /**
    * Atributo de clase
    * Indica la posición actual de bla, bla...
    */
    private static int b; 

    /**
    *   Método de instancia
    *   Realiza copia defensiva del atributo ...
    *
    *   Descripción: Este método ....
    *   ....
    *   ....
    *    @param i : paso por referencia
    *    @param x : paso por valor
    *    @param v : paso por referencia 
    */
    public void f(Integer i , double x, int v[]) {
        ... 
    }

No es necesario generar en HTML la documentación javadoc.

Requisitos mínimos para evaluar la práctica

  • La práctica debe poder ejecutarse sin errores de compilación.
  • Ninguna operación debe emitir ningún tipo de comentario o mensaje por salida estándar, a menos que se indique lo contrario. Evita también los mensajes por la salida de error.
  • Se debe respetar de manera estricta el formato del nombre de todas las propiedades (públicas, protegidas y privadas) de las clases, tanto en cuanto a ámbito de visibilidad como en cuanto a tipo y forma de escritura. En particular se debe respetar escrupulosamente la distinción entre atributos de clase y de instancia, así como las mayúsculas y minúsculas en los identificadores.
  • La práctica debe estar suficientemente documentada, de manera que el contenido de la documentación que se genere mediante la herramienta javadoc sea significativo.

Entrega de la práctica

La práctica se entrega en el servidor de prácticas del DLSI.

Debes subir allí un archivo comprimido con tu código fuente (sólo archivos .java). En un terminal, sitúate en el directorio ‘src’ de tu proyecto Eclipse e introduce la orden

tar czvf prog3-p1.tgz *

Sube este fichero prog3-p1.tgz al servidor de prácticas. Sigue las instrucciones de la página para entrar como usuario y subir tu trabajo.

Evaluación 

La corrección de la práctica es automática. Esto significa que se deben respetar estrictamente los formatos de entrada y salida especificados en los enunciados, así como la interfaz pública de las clases, tanto en la signatura de los métodos (nombre del método, número, tipo y orden de los argumentos de entrada y el tipo devuelto) como en el funcionamiento de éstos. Así, por ejemplo, el método Clase(int,int) debe tener exactamente dos argumentos de tipo int.

Tienes más información sobre el sistema de evaluación de prácticas en la ficha de la asignatura.

Además de la corrección automática, se va a utilizar una aplicación detectora de plagios. Se indica a continuación la normativa aplicable de la Escuela Politécnica Superior de la Universidad de Alicante en caso de plagio:

“Los trabajos teórico/prácticos realizados han de ser originales. La detección de copia o plagio supondrá la calificación de”0” en la prueba correspondiente. Se informará la dirección de Departamento y de la EPS sobre esta incidencia. La reiteración en la conducta en esta u otra asignatura conllevará la notificación al vicerrectorado correspondiente de las faltas cometidas para que estudien el caso y sancionen según la legislación vigente”.

Aclaraciones

  • Aunque no se recomienda, se pueden añadir los atributos y métodos privados que se considere oportuno a las clases. No obstante, eso no exime de implementar TODOS los métodos presentes en el enunciado, ni de asegurarse de que funcionan tal y como se espera, incluso si no se utilizan nunca en la implementación de la práctica. 
  • Cualquier aclaración adicional aparecerá en este enunciado.