Cátedra: Fontela
Fecha: 1ra Oportunidad - 2do Cuatrimestre 2006
Día: 02/10/2006
Nota importante: todo el código que escriba deberá hacerlo en Java o C#, a su elección. Los ejemplos que se muestran correspoden a Java, pero en todos los casos admiten traducción directa a C#
Dado el siguiente diagrama de clases:
Muestre un caso (ejemplo concreto) en el que las excepciones, por utilizar un enfoque optimista del tratamiento de problemas, puede mejorar el desempeño de un aplicación (media carilla)
Explique las diferencias entre pruebas de caja blanca y caja negra. (hasta 3 renglones)
1.-
import Java.util.*; Public class IteradorColTiempos implements Iterator{ private int posicion; private ColTiempos vColTiempos; public IteradorColTiempos(colTiempos vColTiempos){ this.posicion=0; this.vColTiempos=vColTiempos; } public boolean hasNext(){ boolean resultado=false; if (this.posicion==vColTiempos.size()){ //size no existe, no se como sacarlo, por eso lo dejé así. En el parcial esto está **mal** resultado=true; } return resultado; } public Object next() throws eSinMasElem{ Object objeto=null; if (!this.hasNext()){ throw (new eSinMasElem); }else{ objeto=this.vColTiempos[posicion]; posicion++; } return objeto; } } public class eSinMasElem extends Exception{} //en ColTIempos public Iterator iterator(){ return (new IteradorColTiempos(this.vec)); }
UML de la resolución
2.-
public int Suma(){ int segundos=0; //segundos totales Tiempo tiempoAuxiliar=new Hora(); //supongo que el constructor de Hora inicializa todos sus atributos en cero Tiempo tiempoSiguiente; Iterator iterador = this.iterator(); while (iterador.hasNext()){ tiempoSiguiente=(Tiempo)iterador.next(); segundos+=tiempoSiguiente.segundosEntre(tiempoAuxiliar); tiempoAuxiliar.setSegundos(segundos); } return segundos; }
3.-
public class ColTiempos implements Collection,Comparable{ // codigo de ColTiempos public int compareTo(Object otraColTIempos){ int resultado; if (this.suma()>(ColTIempos)otraColTiempos.suma()){ resultado=1; }else{ if ((this.suma==(ColTiempos)otraColTiempos.suma()){ resultado=0; }else{ resultado=-1; } } return resultado; }
Al implementar comparable, uno puede comparar distintas ColTiempos para saber cual tiene la suma de todos sus elementos mas grande, sin importar que elementos tiene, sean días, segundos, años, siglos, etc. De esta manera uno obtiene la diferencia de la suma de los tiempos entre los dos objetos, abstrayendose del contenido de los objetos que esté utilizando. El beneficio mas destacado es que uno puede utilizar soluciones genericas, como por ejemplo Arrays.sort(colTiempos.getVec()), ya que esta forma de ordenar vectores no utiliza internamente nada mas que el metodo compareTo de la clase que pongo como parametro.
4.-
public class ComparadorTiempo extends Comparator{ public int compare (Object o, Object p){ Tiempo dato1,dato2; int resultado,tiempoEntre; dato1=(Tiempo)o; dato2=(Tiempo)p; tiempoEntre=dato1.segundosEntre(dato2); if(tiempoEntre>0){ resultado=1; }else{ if (tiempoEntre==0){ resultado=0; }else{ resultado=-1; } return resultado; } }
El beneficio de este tipo de comparadores es que uno puede crear varios tipos de comparadores para una misma clase.
Un caso comun de tratamiento de excepciones es la división por cero.
El problema consiste en realizar la división de la sumatoria de los componentes de una colección de enteros por la sumatoria de los componentes de otra colección de enteros. Mostramos dos ejemplos uno con enfoque optimista y el otro no.
public void MiFuncion(){ MiColeccionDeEnteros dividendo; MiColeccionDeEnteros divisor; float division; ... //se llenan las dos colecciones if (divisor.sumatoria().equals(0)){ division=dividir(dividendo,divisor); }else{ //Codigo en caso de q sea cero la sumatoria } //...sigue el codigo } public float dividir (MiColeccionDeEnteros a, MiColeccionDeEnteros b){ return a.sumatoria()/b.sumatoria(); } ...
public void MiFuncion(){ MiColeccionDeEnteros dividendo; MiColeccionDeEnteros divisor; float division; ... //se llenan las dos colecciones try{ division=dividir(dividendo,divisor); }catch(DivisionPorCeroException e){ //codigo para manejo de la excepcion. } //...sigue el codigo } public float dividir (MiColeccionDeEnteros a, MiColeccionDeEnteros b) throws DivisionPorCeroException{ Integer divisor; divisor=b.sumatoria(); sif divisor.equals(0) throw new DivisionPorCeroException; return a.sumatoria()/divisor; }
Este es un caso donde es conveniente usar el método optimista dado que hay una optimizacion del codigo cuando ahorramos realizar una sumatoria.
Otra respuesta posible:
El enfoque optimista del que se habla al mencionar a las excepciones, es el que supone que todos los parámetros de entrada serán válidos para ser usados dentro de un método. De esta forma, se obvian las verificaciones y, en caso de que algo salga mal, se lanza una excepeción comunicándolo. Un caso típico es aquel donde hay que realizar operaciones matemáticas. Al tener calcular, por ejemplo, una división, el 0 como divisor representa un peligro, así como los números negativos como radicandos para raíces pares. Sin embargo, esas verificaciones son sencillas, y en más de una ocasión resulta más eficiente validar antes que utilizar excepciones. Un caso más complejo es el de las matrices. Un método que invierta una, podría lanzar una excepción al intentar invertir una matriz no inversible. El motivo de la mejora, en este caso, es que en casi todos los métodos de inversión matricial, se puede descubrir su no inversibilidad mientras se opera. Por lo tanto, no se hacen cálculos extra de verificación, sino que, en caso de que la operación se pueda llevar a cabo, los cálculos intermedios que permiten validar, son en pos del objetivo.
Las pruebas de caja blanca son aquellas en las que el desarrollador observa un método y analiza los posibles errores que puede tener, para luego realizar las pruebas correspondientes en base a estos posibles errores. En cambio, las pruebas de caja negra son una serie de pruebas que se realizan sin analizar internamente el código a probar.
comentario acá.
1.Para seguir con el patrón de diseño implementado en las colecciones java el Iterador debe ser una clase interna y privada de la colección. De este modo se le da al iterador acceso a la implementación de la colección y se le delega todo el control de la forma de recorrer la misma.
Habría que sacar el ejemplo de división por cero dado que es un mal ejemplo de enfoque optimista. El ejemplo y definición dado en “otra respuesta posible” es correcto, fletaría poner un código que lo ejemplifique.
1- En el método hasNext() hay que verificar que el tamaño del arreglo sea mayor que la posición. Para eso, se debe poner:
if(this.posicion < vColTiempos.size()) …..
2- La clase IteradorColTiempos implementa la interfaz Iterator, por lo tanto, sus métodos deben tener exactamente el mismo encabezado que en la interfaz. Entonces el método next() debería ser
public Object next(){…}
Si se quiere lanzar una Excepción, se debe usar excepciones no chequeadas, que no necesitan declararse en el encabezado. Estas descienden de RunTimeException, y no de Exception (en el caso de Java).