Download Programación Orientada a Objetos
Document related concepts
no text concepts found
Transcript
PROGRAMACIÓN ORIENTADA A OBJETOS
(PRACTICA DE DISEÑO, CURSO 2011-2012)
OBJETIVO
El objetivo de la práctica es crear una calculadora utilizando el lenguaje Java. Se ha
escogido el ejemplo de la calculadora porque permite aplicar fácilmente principios y patrones de
diseño, pero manteniendo el programa dentro de un tamaño razonable.
Aunque es posible implementar la calculadora sin seguir estos principios (en pocas clases,
siguiendo un paradigma meramente procedimental) es importante resaltar que en la valoración de la
práctica se le da más importancia a cómo se hacen las cosas, que a simplemente mirar si las cosas
funcionan o no.
FUNCIONAMIENTO BÁSICO DE UNA CALCULADORA
Una calculadora se compone de los siguientes elementos básicos que mostramos en la figura
adyacente y que explicamos a continuación:
Pantalla
48
Operadores
unarios
+/-
Operaciones
de memoria
M
Dígitos
X2
MR
MS
SQRT
T
MC
45
+
3
=
48
1/X
M+
Ventana de log
M-
7
8
9
C
AC
4
5
6
*
/
1
2
3
+
-
0
.
Operaciones de
borrado
Operadores
binarios
=
•
Pantalla: Muestra los números que se van introduciendo y los resultados de las operaciones.
•
Operadores unarios: Son operadores que actúan sobre un único operando, que es el que se está
mostrando en ese momento por pantalla. Entre ellos destacaremos el cuadrado (X 2), raíz
cuadrada (SQRT), inversa (1/X) y cambio de signo (+/-)
•
Operadores binarios: Son operadores que actúan sobre dos operandos, el modo de
funcionamiento sería: pulsamos el primer operando, pulsamos el operador binario, pulsamos
el segundo operando y pulsamos la tecla “=” para obtener el resultado. Entre los operadores
binarios destacaremos la suma(+), la resta (-), la multiplicación (*) y la división (/).
•
Operaciones de memoria: Permiten guardar datos en la memoria interna de la calculadora.
Tenemos cinco posibles operaciones: memory recall (MR) recupera la información de la
memoria, memory store (MS) almacena el valor mostrado en la memoria, memory clear (MC)
borra el contenido de la memoria, sumar el valor mostrado al contenido de la memoria (M+) y
restar el valor mostrado al contenido de la memoria (M-). También existe un flag,
representado por la letra M que se enciende cuando la memoria tiene algún valor almacenado.
•
Dígitos: Operandos que se introducen para el cálculo. Existe un botón “.” que permite
introducir valores decimales.
•
Operaciones de borrado: Un botón “AC” permite resetear por completo el estado de la
calculadora y dejarla en el estado inicial. Un botón “C” permite borrar el número de la
pantalla pero sin anular la operación que se está llevando a cabo.
•
Ventana de log: La ventana de log permite ver la secuencia de operaciones que hemos ido
realizando. Sería el equivalente al rollo de papel que tienen algunas calculadoras.
Para cualquier duda sobre el funcionamiento de la calculadora puede consultarse cualquier
calculadora de bolsillo o las calculadoras de los distintos sistemas operativos.
INDICACIONES Y RECOMENDACIONES DE DISEÑO
•
•
•
•
Recomendación general
◦
En primer lugar lo más importante de todo es que la calculadora debe hacer uso de las
características propias de la programación orientada a objetos (herencia, polimorfismo,
sobrecarga, sobreescritura, etc.) utilizando principios y patrones de diseño.
◦
El código desarrollado debe ser flexible y fácilmente ampliable. Por ejemplo, debe ser
sencillo añadir nuevas funciones unarias o binarias a la calculadora tocando lo menos
posible las otras clases ya existentes.
◦
Se deberá evitar en lo posible el uso de clases que controlen prácticamente todo el
programa mientras que las otras clases actúan más como repositorios de información.
Relaciones de generalización/especialización
◦
Como se puede observar en la descripción de la calculadora es fácil ver a primera vista
posibles relaciones de generalización/especialización. Incluso si nos fijamos un poco más
puede haber más de las que en principio pudiera parecer.
◦
La relación de herencia permite tratar de forma genérica objetos concretos con todas las
ventajas que ello conlleva. Además la ligadura dinámica asegura que el código a ejecutar
siempre es el adecuado.
Máquina de estados
◦
Pulsar las mismas teclas puede no tener el mismo funcionamiento dentro de la
calculadora. Por ejemplo si pulsamos “5 + 3” si ahora pulsamos “–” la calculadora
acumula el resultado de la operación anterior mostrando un “8” y se queda a la espera del
segundo operando. Si pulsamos “5 +” y ahora pulsamos “–” la calculadora entenderá que
queremos reemplazar la operación “+” por la operación “–”.
◦
Este comportamiento suele implementarse suponiendo a la calculadora una máquina de
estados y, dependiendo en que estado estemos, la pulsación sobre un botón tendrá un
funcionamiento u otro.
Uso de pilas
◦
Una forma de manejar expresiones aritméticas es utilizando pilas (normalmente visto en la
asignatura de EDI). Podéis considerar su utilización para, por ejemplo, almacenar valores
y operadores antes de pulsar “=” y proceder a su cálculo.
•
•
Interfaz del usuario
◦
Un aspecto importante del interfaz del usuario es que debe estar desligado de las clases
que representan el dominio de la aplicación, siguiendo los principios de diseño que se han
comentado en clase. Para mantener actualizados simultáneamente la pantalla y la ventana
de log pueden utilizarse estrategias de notificación por parte del dominio al interfaz.
◦
El interfaz debe estar realizado con los componentes javax.swing y debe usar layout
managers para su disposición en la ventana (podéis usar el diseñador de NetBeans).
Uso de números decimales
◦
Los valores numéricos deberán representarse con clases como java.math.BigDecimal y no
con clases en coma flotante como double o float. Esto es debido a que la propia
representación en coma flotante puede hacer que aparezcan problemas de precisión. Es
decir, al acabar una serie de operaciones podemos encontrarnos con que en vez de un “1”
obtenemos un “0.99999”.
◦
Básicamente un BigDecimal es un valor decimal en coma fija. La forma recomendada
para crear un valor de este tipo es usar el constructor a partir de Strings
“BigDecimal(String val)” ya que el constructor a partir de valores en coma flotante puede
presentar problemas de precisión.
◦
Una vez creado tenemos que tener en cuenta que el objeto es inmutable, por lo que todas
las operaciones con el mismo crearán un nuevo objeto.
◦
En las operaciones, por ejemplo la división “divide(BigDecimal divisor, int scale,
RoundingMode roundingMode)”, es necesario tener en cuenta la escala (básicamente el
número de dígitos a la derecha de la coma) y el modo de redondeo. Para este último
aunque existen unas constantes en la clase BigDecimal se consideran obsoletas y se
recomienda el uso del enumerado java.math.RoudingMode. El método de redondeo por
defecto en las calculadoras suele ser el HALF_UP, es decir, se redondea al vecino más
cercano y en caso de equidistancia se redondea hacia arriba. Así el valor 2,3333 se
redondea a 2,33, el valor 2,7777 se redondea a 2,78 y el valor 2,5555 se redondea a 2,56.
◦
Por ejemplo el resultado de ejecutar el siguiente código es 2.66667
BigDecimal num1 = new BigDecimal("8");
BigDecimal num2 = new BigDecimal("3");
BigDecimal num3 = num1.divide(num2, 5, RoundingMode.HALF_UP);
System.out.println(num3);
◦
•
Tener en cuenta que las operaciones pueden producir errores si no se da una escala válida
en la que representar los resultados.
Posibles mejoras
◦
A continuación cito una serie de mejoras a la descripción original de la práctica cuya
inclusión es optativa pero que, de realizarlas, tendrán un reflejo final en la nota:
◦
Implementaciones de nuevos operadores, tanto unarios (seno, coseno, tangente, logaritmo
neperiano, etc.) como binarios (módulo).
Visor de resultados en distintos modos (binario, octal, hexadecimal y, por supuesto,
decimal)
Utilización de paréntesis
Permitir grabar a disco o imprimir los contenidos de la ventana de log.
◦
◦
◦
CARACTERÍSTICAS DEL CÓDIGO A ENTREGAR
•
El programa consistirá en un proyecto de la herramienta NetBeans (en su versión instalada
en el laboratorio de prácticas). El programa debe funcionar correctamente en las máquinas
de docencia.
•
El proyecto NetBeans se denominara de la siguiente forma “ApellidoA1-ApellidoA2ApellidoA3-ApellidoA4”. Donde ApellidoAx es el primer apellido de los componentes del
grupo con la única restricción de que el primero que aparezca tiene que ser el primero por
orden de lista y que será el encargado de entregar la práctica. Así, por ejemplo, la práctica de
los alumnos Almagro, Garcia, Martinez, Torre se entregará como “Almagro-Garcia-MartinezTorre”.
•
El proyecto NetBeans debe tener configurada correctamente la “MainClass” del mismo de tal
forma que pulsando F6 (Run Main Project) este se ejecute correctamente.
•
El código debe incluir pruebas JUnit del mismo aunque no es necesario incluir los mensajes
de texto que poníamos en los boletines.
•
El proyecto debe venir con el software de Cobertura integrado de tal forma que se pueda
generar una cobertura de los tests. La cobertura de los mismos debe tener un valor alto para
que pueda ser considerada en la nota.
CARACTERÍSTICAS DE LA MEMORIA A ENTREGAR
•
•
El código deberá venir acompañado de una memoria explicativa. Debido a que muchas veces
esta memoria tiene un formato realmente ilegible os presento a continuación una serie de
recomendaciones a la hora de formatear correctamente la práctica. Son
recomendaciones, si por algún motivo no podéis cumplir alguna no pasa nada, pero recordar
que en la evaluación de la práctica se valora la correcta presentación de la misma:
◦
Tipo de letra Times New Roman tamaño 12 para los textos y proporcional (Courier New o
Monospaced) y de tamaño 8 para el código, espaciado simple.
◦
La ordenación de las clases en la memoria será por orden alfabético de paquetes y luego
de nombres de clases dentro del paquete (igual que NetBeans). Cuando hagáis referencia a
una clase indicar en qué paquete está para que sea fácilmente localizable.
La estructura de la memoria será la que se detalla a continuación
◦
Primera página
◦
Resumen
◦
Título de la práctica, nombre de la asignatura y nombre de todos los integrantes del
grupo de prácticas poniendo en primer lugar al portavoz del mismo (el primero
por orden alfabético). Recordar que si vuestro nombre no aparece en la lista de autores
entenderemos que no habéis participado en la elaboración de la práctica.
Resumen breve en el que describáis sucintamente el contenido de la práctica. Deberá
incluir los patrones de diseño utilizados en la misma, las mejoras opcionales que
habéis incluido en la misma, el funcionamiento básico de la aplicación, etc. No
debería extenderse más allá de una carilla y podrá hacer mención al diagrama general
de clases incluido a continuación.
Diagrama general de clases
Será un diagrama en el que se muestran todas las clases propias desarrolladas. Para
simplificar el diagrama podéis mostrar sólo el nombre de las clases, aunque si es
◦
posible mostrar de forma legible atributos y métodos (excluyendo detalles como tipos
de retorno o parámetros) podéis hacerlo. El objetivo de este diagrama es hacerse una
idea global del diseño y mostrar de forma detallada las relaciones entre las distintas
clases.
Aunque los detalles de las clases pueden estar ocultos en aras de la claridad los
detalles de las relaciones deben estar completos y ser claros.
Recordar que es importante que todo diagrama que presentéis tiene que ser legible.
Explicación de subsistemas:
Un subsistema se entenderá como un conjunto de clases relacionadas entre sí (por
ejemplo, las clases implicadas en el funcionamiento de un patrón de diseño). Para
explicar cada subsistema hay que incluir lo siguiente:
Explicación detallada del funcionamiento del subsistema, de las clases que lo
componen, etc. Esta explicación deberá ir acompañada de los diagramas de clases y de
secuencia que se comentan a continuación. Es importante que el texto y los
diagramas formen un todo relacionado, es decir, el texto debe de comentar y
hacer referencia a lo que vemos en los diagramas.
Un diagrama de clases que muestre todos los detalles de las mismas, incluyendo
los detalles de los métodos, los atributos, las asociaciones, las relaciones de
dependencia, etc. En este caso sólo contemplaremos relaciones entre clases del
subsistema (las relaciones entre todas las clases ya las hemos visto en el diagrama
general de clases). En la relaciones de asociación habrá que incluir adornos como
nombres de rol, multiplicidades, navegabilidad, visibilidad, etc.
Diagramas de secuencia para las operaciones más importantes de dicho subsistema, o
para aquellas que se considere que facilitan la comprensión del funcionamiento
dinámico. Los diagramas de secuencia deben ser una fiel representación de los
algoritmos escritos en Java. Si por razones de legibilidad se realizan simplificaciones
deberían ser indicadas en el diagrama con la correspondiente nota.
FECHA Y FORMA DE ENTREGA
•
La fecha límite de entrega de la práctica es el 13 de Enero de 2012.
•
En el Moodle se habilitará un espacio para que el portavoz de la práctica la entregue. Deberá
entregarse un fichero ZIP que incluya el directorio del proyecto NetBeans y un directorio
“Memoria” que incluya la memoria (DOC, ODT, etc.) y el mismo convertido a PDF. En
nombre de los ficheros de la memoria seguirá la misma estructura de “ApellidoA1ApellidoA2-ApellidoA3-ApellidoA4”.
VALORACIÓN
•
La valoración de la práctica constará de los siguientes apartados:
◦
◦
Documentación (1 punto)
Se entrega todo lo que se pide y como se pide
La memoria es legible, tiene un formato claro, está bien presentada, etc.
Diseño (3 puntos)
Uso adecuado de las características propias de la POO: herencia, polimorfismo,
composición, etc.
Uso adecuado de principios y patrones de diseño
◦
UML (3 puntos)
◦
Los comentarios que acompañan a las explicaciones del diseño son claros, precisos y
lo suficientemente extensos para comprender lo que se está realizando
Calidad, detalle y adecuación al código de los diagramas de clase
Calidad, detalle y adecuación al código de los diagramas de secuencia
Funcionamiento general (3 puntos)
Compila, funciona sin problemas y cumple las especificaciones iniciales
El interfaz gráfico está correctamente realizado
Qué mejoras y/o ampliaciones se han realizado
Se han realizado suficientes pruebas JUnit y su cobertura es adecuada
ASPECTOS IMPORTANTES A TENER EN CUENTA
•
Recordar que es necesario sacar una nota igual o superior a cuatro para poder aprobar la
asignatura.
•
Aquellas prácticas de las cuales se tenga constancia que han sido copiadas (de los
compañeros, de Internet, etc.) serán calificadas con un cero. En el caso de copias entre
compañeros tanto el original como la copia recibirán un cero.
•
Después de entregar la práctica si el profesor lo considera necesario puede llamar a cualquier
grupo para que pase a defender dicha práctica. La no asistencia al acto de defensa de la
práctica o si se constata en dicho acto que el conocimiento de la práctica por parte del alumno
es insuficiente implicará el suspenso de dicha práctica y, por lo tanto, de la asignatura.