MIT OpenCourseWare


6.170 Curso práctico en Ingeniería de Software.

Página principal
¿Qué es OCW?
Ayuda
Feedback
Preguntas frecuentes
Glosario
 
 
Página principal del curso
Programa
Calendario
Material de clase
Trabajos
Exámenes
  Lecturas obligatorias
  Otras fuentes
  Prácticas
  Clases de repaso
  Herramientas
  Proyectos

   MIT

   
 

Ejercicio 2

Plazo de entrega: 3ª semana

Introducción

En este boletín de problemas, practicará tanto la lectura e interpretación de las especificaciones, como la lectura y escritura del código fuente de Java™. Implementará un par de clases que completarán la implementación de una calculadora gráfica de polinomios, y responderá a preguntas tanto del código que se le ha facilitado, como del código que usted ha creado.

Para completar este boletín de problemas, necesitará saber:

  • Álgebra básica (aritmética de polinomios y aritmética racional).
  • Cómo leer especificaciones procedurales (requires, modifies, effects) e invariantes de representación.
  • Cómo leer y escribir código básico en JavaT:
    • Estructura de código y acomodamiento (definición de clase y método, declaración de campo y variable).
    • Llamadas a métodos.
    • Estructuras de control: bucles (while y for) y ramificaciones condicionales (if, then, else).
    • Operadores para:
      • La creación de un objeto: new.
      • El acceso a campo y a método.
      • Asignación: =.
      • Comparación: ==, !=, <, > , <=, >=.
      • Aritmética: +, -, *, /.
  • Cómo ejecutar un compilador de JavaT como JavaTc para crear ficheros .class.
  • Cómo ejecutar la Máquina Virtual JavaT (MVJ) como Java, para ejecutar tanto el código como las librerías que el personal le facilita.


Problema 1: RatNum (15 puntos)

Lea las especificaciones para RatNum, una clase que representa los números racionales. Luego, repase la implementación que el personal ha puesto a su disposición, RatNum.java. Puede que le sea útil leer detenidamente el código en RatNum.Test.java para ver ejemplos de cómo se utiliza la clase RatNum (aunque en vez de verlos en el código de una aplicación, los verá en el contexto de un gestor de pruebas). Responda a las siguientes preguntas y escriba sus respuestas en el fichero problema1.txt.

¿Qué finalidad tienen los comentarios de una única línea al comienzo de los métodos add, sub, mul y div? Tenga en cuenta que todos estos métodos requieren que "arg!=null". La razón es que todos los métodos consiguen acceder a los campos de 'arg' sin antes comprobar si el valor de 'arg' es null. No obstante, los métodos también acceden a los campos de 'this' sin comprobar el valor 'null'; ¿por qué no aparece "this !=null" en la cláusula requires de los métodos? RatNum.div(RatNum) comprueba si su argumento es NaN (no es un número). RatNum.add(RatNum) y RatNum.mul(RatNum) no hacen eso. Explique: ¿por qué es RatNum.parse(String) un método estático? ¿Qué otra alternativa a los métodos estáticos nos permitiría lograr el mismo objetivo de generar una RatNum a partir de una entrada de tipo String? Imagine que el invariante de representación fuese debilitado de modo que no necesitásemos que los campos numer y denom se guardasen en forma reducida. Esto significa que las implementaciones del método no podrían asumir ya que ese invariante se mantuviese en la entrada al método, pero tampoco haría falta que éstas hicieran cumplir al invariante a la salida. Luego el nuevo invariante de representación sería:


// Rep Invariant for every RatNum r: ( r.denom >= 0 )

¿Qué implementaciones del método o del constructor habría que cambiar? Para cada parte del código modificado, describa los cambios de manera informal e indique cuán más o menos complejo sería el resultado (teniendo en cuenta tanto la claridad del código como la eficacia de ejecución). Observe que las nuevas implementaciones deben ceñirse a la especificación determinada; en especial, RatNum.unparse() necesita generar fracciones en forma reducida.

Problema 2: RatPoly (45 puntos)

Vuelva a leer las especificaciones para las clases RatTerm, RatTermVec y RatPoly. Se le ha facilitado la implementación de RatTerm y RatTermVec (no necesita escribir el código). Asegúrese de que comprende la idea general de RatPoly y las especificaciones para los determinados métodos. Lea la escueta implementación de RatPoly.java que se le ha dado. Las partes más significativas del fichero que se le ha facilitado son los comentarios que describen cómo debe usar los campos que se le dan para implementar esta clase. Es muy importante que entienda bien el comentario acerca del invariante de representación, puesto que los invariantes que defina pueden tener un efecto drástico en las implementaciones que están permitidas para los métodos de RatPoly.

Complete la implementación para los métodos en la especificación de RatPoly. Puede definir nuevos métodos helper privados en la medida que desee; nosotros le hemos sugerido unos cuantos, completos con especificaciones, pero no está obligado a usarlos. (No obstante, el personal docente piensa que si los usa, simplificará enormemente su implementación).

Además, le hemos facilitado una suite de prueba bastante rigurosa en RatPolyTest.java. Puede ejecutar esta suite con JUnit a la vez que puede programar y evaluar su progreso y la exactitud de su código. Para ejecutar la suite de prueba sobre RatPoly, escriba el siguiente comando:

athena% java junit.swingui.TestRunner ex2.RatPolyTest

Para ejecutar JUnit mediante un método alternativo no gráfico, utilice junit.textui.TestRunner en vez de junit.swingui.TestRunner, como aparece indicado en página de consejos.

Indique claramente con comentarios dentro del código fuente si el código pasa o no todos los tests. Si no pone ningún comentario, daremos por hecho que el código falla.


Problema 3: RatPolyStack (25 puntos)

Siga el mismo procedimiento del problema 2, pero esta vez, rellene los espacios en blanco para RatPolyStack.java. Puede aplicar las mismas reglas aquí (puede añadir métodos helper privados si lo desea). Le hemos facilitado una suite de prueba en RatPolyStackTest.java. Puede ejecutar esta suite con JUnit mientras programa y evalúa su progreso y la exactitud de su código. Para ejecutar la suite de prueba sobre RatPolyStack, escriba el siguiente comando:

athena% java junit.swingui.TestRunner ex2.RatPolyStackTest

Indique claramente con comentarios dentro del código fuente si el código pasa o no todos los tests. Si no pone ningún comentario, daremos por hecho que el código falla.

Problema 4: PolyCalc (5 puntos)

Ahora que ya ha implementado las dos clases que faltaban en el sistema, puede ejecutar la aplicación PolyCalc. Dicha aplicación le permitirá introducir polinomios y realizar operaciones aritméticas sobre ellos a través de una interfaz de usuario de tipo point-and-click (señalar y activar). La calculadora también realiza una representación gráfica de los polinomios resultantes. Para ejecutar PolyCalc, escriba el siguiente comando:

athena% java ex2.PolyCalcFrame

Se abrirá una ventana con una pila a la izquierda, un visualizador gráfico a la derecha, un área de texto para introducir los polinomios y una serie de botones al final. Pulse los botones para introducir los polinomios y manejar los que se encuentren en la pila. El visualizador gráfico se irá actualizando sobre la marcha, mostrando la representación gráfica de los cuatro primeros elementos de la pila.

Entregue sus cuatro expresiones polinómicas favoritas dentro del fichero problema4.txt en el formato de RatPoly.unparse.

Problema 5: Diagrama de dependencia de módulos (10 puntos)

Cree un diagrama de dependencia entre módulos en el que se muestren todas las clases e interfaces utilizadas en la ejecución del programa final, con sus relaciones de dependencia y asociación. No hace falta que incluya PolyCalcFrame. Debería hacer una valoración razonable y decidir qué interfaces y librerías de clases de Java™ va a incluir.
Puede que usted (y su monitor de prácticas) encuentren útil la utilización de Visio para generar los MDDs (Diagramas de dependencia de módulos. Consulte la hoja de herramientas para obtener más información sobre Visio.

Clases que se han facilitado:
Se le han facilitado todas estas clases ya compiladas:

  • Con el código fuente también incluido:
    ex2.RatNum
    ex2.RatNumTest
    ex2.RatPolyTest
    ex2.RatPolyStackTest
    ex2.Cons (como parte del código de inicio de RatPolyStack.java)
  • Sin el código fuente:
    ex2.PublicTest
    ex2.PolyGraph
    ex2.PolyCalcFrame
    ex2.RatTerm
    ex2.RatTermVec

Sumérjase

Antes de programar, asegúrese de que ha seguido las instrucciones sobre el directorio de instalación y el manejo de Java™ que se detallan en la hoja de herramientas:
Cree un directorio con el nombre ex2 y copie en él los archivos que le hemos facilitado:

mkdir ~/6.170/ex2
cp -p /mit/6.170/www/psets/ex2/ex2-spec/* ~/6.170/ex2

Luego, edite los ficheros de especificación dentro de su implementación y pruébela. No hace falta que compile los otros ficheros de código fuente que le hemos dado; los archivos de clase ya compilados están listos para ser utilizados en el directorio del curso 6.170. Observe las Especificaciones para las clases que implementará, y aquellas que le hemos facilitado.

Al final del boletín de problemas, en su directorio ex2, debería tener los siguientes archivos listos para entregar: problem1.txt , RatPoly.java, RatPolyStack.java y problem4.txt, junto con el archivo Manifest, en el que se enumeren todas las entradas.

Consejos

  • Observe las directrices y los consejos del boletín de problemas.
  • ¡Piense antes de empezar a escribir el código! Las funciones aritméticas de los polinomios no son difíciles, pero si empieza a desarrollar la implementación sin un plan previo específico, es fácil que se vea envuelto en una terrible enramada.
  • JUnit vuelve a cargar todas las clases cada vez que se ejecuta un test, así que no es necesario reiniciar la aplicación JUnit después de hacer cambios en el código de Java (aunque sí hace falta que vuelva a compilar su código para que los cambios se apliquen).
  • Para ejecutar JUnit mediante un método alternativo no gráfico, utilice junit.textui.TestRunner en vez de junit.swingui.TestRunner.
  • Las suites de prueba que se le han facilitado en el boletín de problemas 1 son las mismas que usaremos para evaluar su implementación; en los posteriores boletines de problemas, no se le facilitará una serie de casos de prueba tan rigurosa para que ejecute sus implementaciones, pero para esta serie de problemas, puede dar por supuesto que el conjunto de tests que se le ha facilitado es lo suficientemente riguroso como para no tener que escribir uno propio.
  • La división de polinomios entre números racionales es igual que la gran división que uno aprende en la escuela primaria. Le damos un ejemplo aquí:

Errata

Había un pequeño error en la implementación del código que se facilitó, en RatPoly.java. Esto hizo que los estudiantes encontraran errores NaN al ejecutar los casos de prueba. Para solucionarlo, haga lo siguiente:
Inserte las siguientes líneas de código en RatPoly.appendTerm(StringBuffer sb, RatTerm rt):
                   if(sb.toString().equals("NaN"))
                     {
                     return;
                     }
                     
                     if(c.isNaN())
                     {
                     sb.replace(0, sb.length(), "NaN");
                     return;
                     }

justo después de las declaraciones:
                     RatNum c = rt.coeff;
                     int e = rt.expt;

al comienzo del método.

En el Problema 2 se expuso de manera incorrecta que "la suite de prueba depende enormemente de la implementación del método de RatPoly.unparse(); si la suite de prueba afirma que todos o muchos de los tests están fallando, el motivo del problema podría ser que hay un error en su implementación de unparse()." El método unparse() se le facilita implementado.

Preguntas & Respuestas

En esta sección se enumerarán una serie de aclaraciones y respuestas a las típicas preguntas que suelen surgir en relación a los boletines de problemas. Intentaremos mantenerla lo más actualizada posible, así que este debería ser el primer lugar que usted consultara (después de haber releído atentamente las especificaciones y el boletín de problemas entregado en clase) cuando le surgiera cualquier tipo de problema.

Pregunta: ¿Qué debería devolver RatPoly.eval() en una clase RatPoly en la que isNaN() es igual a "true"?

Respuesta: La clase java.lang.Double tiene una variable estática final de tipo double llamada Double.NaN que representa un NaN. Esto es lo que le debería devolver en este caso.

Pregunta: ¿Debería RatPoly(0,n) dar/crear (make) un polinomio de grado "0"? ¿Como se supone que debo implementar polinomios de grado "0"? ¿Puedo representarlo como un término con coeficiente cero?

Respuesta: Si, RatPoly(0,n) debería dar un polinomio de grado "0". Sin embargo, no puede crear un término con coeficiente cero para representarlo, porque violaría el invariante de representación de RatPoly. Debería leer atentamente el último enunciado de la función de abstracción de RatPoly: " Si no hay términos, RatPoly representará el polinomio de grado cero".

Pregunta: Pero no lo entiendo... ¿No dice el invariante de representación que los términos no pueden tener valor "null"? ¿Cómo es que entonces puede no haber términos?

Respuesta: Claro, pero puede estar vacío. Dése cuenta de que mientras el invariante de representación declara que el campo de los términos no puede ser "null", puede que el campo de los términos haga referencia a un objeto RatTermVec que no contiene ningún término. (Esto haría que terms.size() devolviera el valor 0). Por favor, póngase en contacto con su monitor de prácticas si aún sigue con dudas sobre esto. (Por favor, échele un vistazo a los comentarios del código de RatPoly para la función de abstracción y el invariante de representación).

Pregunta: ¿Por qué el argumento coeff es un int, en lugar de un RatNum, para el constructor de Ratpoly?

Respuesta: Nuestros casos de prueba utilizan este constructor. No proporcionamos otro constructor que tome un RatNum (numero racional) como coeficiente porque RatPoly.parse() es un método mucho más útil para crear nuevos RatPolys (polinomios racionales).

Pregunta: Pero no lo entiendo... ¿No dice el invariante de representación que los términos no pueden tener valor "null"? ¿Cómo es que entonces puede no haber términos?

Respuesta: Claro, pero puede estar vacío. Dése cuenta de que mientras el invariante de representación declara que el campo de los términos no puede ser "null", puede que el campo de los términos haga referencia al objeto RatTermVec que no contiene ningún término. (Esto haría que terms.size() devolviera el valor 0). Por favor, póngase en contacto con su monitor de prácticas si aún sigue con dudas sobre esto. (Por favor, échele un vistazo a los comentarios del código de RatPoly para la función de abstracción y el invariante de representación).

Pregunta: Tuve un problema con Visio 2000; al arrancarlo se abría un cuadro de diálogo de error que decía: "The procedure entry point GBL could not be located in the dynamic link library VISLIB32.DLL?" ("¿No se ha podido localizar el punto de entrada al método GBL en la librería de enlaces dinámicos VISLIB32.DLL?"). Estoy instalando Visio 2000 en un ordenador con plataforma Windows 2000.

Respuesta: Consulte la Ayuda de Microsoft: Visio2000: Mensaje de error: The Procedure Entry Point GBL Could Not Be Located in the Dynamic Link Library Vislib32.dll. (El punto de entrada al método GBL no podría ubicarse en la librería de enlaces dinámicos Vislib32.dll).

Pregunta: ¿Podría hacer el Ejercicio 2 en el ordenador de mi casa (no es un Athena)?

Respuesta: Claro, pero deberá descargarse en su ordenador de casa los correspondientes archivos jar que se encuentran en el directorio del curso 6.170. Para el Ejercicio 2, necesitará los archivos junit.jar y ex2-lib.jar que están en el directorio /mit/6.170/lib. Sin embargo, su código DEBE funcionar en Athena, así que por favor, dedíquele unos cuantos minutos para asegurarse de que funciona correctamente en Athena antes de entregar los Ejercicios. [Descargar ex2-lib.jar] [Descargar junit.jar]

Pregunta: ¿Dónde puedo encontrar la API de JUnit?

Respuesta: Puede encontrar aquí la API de JUnit.

Massachusetts Institute of Technology © 2003 MIT | Información Jurídica | Privacidad
Todo uso del sitio de MIT OpenCourseWare y sus materiales de curso queda sujeto a las condiciones y términos de uso detallados
en la sección sobre Información Jurídica
Copyright © 2003 Portal Universia S.A. Todos los derechos reservados
(Avda. de Cantabria s/n - Edif. Arrecife, planta 00.28660 Boadilla del Monte) - Madrid. España.
Contacta con nosotros: Usuarios | Empresas-Instituciones-Medios comunicación
Código Ético | Aviso Legal | Política de confidencialidad | Quiénes somos: Sala de Prensa