jueves, 7 de abril de 2011

~Semana 10. Eventos, excepciones y errores

Semana 10
Materia: Taller de Programación Orientada a Objetos
Jueves M1-M2

Hola a todos, en esta entrada les explicare un poco sobre el uso de excepciones, errores y eventos dentro de mi proyecto. 

Excepciones
Algunas de las excepciones que he agregado a mi proyecto están en la parte de validación de datos por parte del usuario.
package nutrilife.gui;
import nutrilife.dieta.*;
import java.util.InputMismatchException;
/**
 *
 * @author Carmen Suarez
 */
public class Main {

    public static void main(String[] args) {
        
        //Variable that stores that will stream the input from console
        Dieta D = new Dieta();
        boolean control = true;
        do
        {
            try
            {
                InputDieta.input(D);
                control = false;
            }
            catch (InputMismatchException inputMismatchException)
            {
                inputMismatchException.printStackTrace();
                System.out.println("Vuelve a meter los datos");
            }
        }while( control );
    }
}
package nutrilife.gui;
import nutrilife.dieta.*;
import java.util.*;
/**
 *
 * @author Carmen Suarez
 */
public class InputDieta {
    static void input(Dieta D) throws InputMismatchException
    {
        Scanner scan = new Scanner(System.in);
        System.out.println("Dame el numero de energia");
        D.setEnergia(scan.nextDouble());
        System.out.println("Energia: " + D.getEnergia());
        boolean c = true;  //Variable de control
        //Entrar porcentajes
        do
        {
            try
            {
                System.out.print("Dame el porcenaje de carbohidratos: ");
                D.setPorcentajeCarbohidrato(scan.nextDouble());
                System.out.println("Porcentaje de carbohidratos: " + D.getPorcentajeCarbohidrato());

                System.out.print("Dame el porcenaje de proteinas: ");
                D.setPorcentajeProteina(scan.nextDouble());
                System.out.println("Porcentaje de proteinas: " + D.getPorcentajeProteina());

                System.out.print("Dame el porcenaje de lipidos: ");
                D.setPorcentajeLipido(scan.nextDouble());
                System.out.println("Porcentaje de lipidos: " + D.getPorcentajeLipido());

                D.setPorcentajeTotal(); // Calcula el valor para la variable porcentajeTotal

                if( D.getPorcentajeTotal() != 100)
                {
                    throw new MyException();
                }
                c = false;
                D.setCarbohidratos(); // Calcula el valor para la variable carbohidrato
                D.setProteina(); // Calcula el valor para la variable proteina
                D.setLipido(); // Calcula el valor para la variable lipido
            }
            catch(MyException myException)
            {
                myException.getMessage();
                myException.printStackTrace();
            } 
        }while(c); // Termina entrada de porcentajes
        
        //Entrada de Intercambios
        //intercambios de grupo: Leche
        System.out.print("Dame el intercambio de leche descremada: ");
        D.setIntercambioLecheDescremada(scan.nextInt());
        System.out.println("Intercambios para leche descremada: " + D.getIntercambioLecheDescremada());
        System.out.print("Dame el intercambio de leche semidescremada: ");
        D.setIntercambioLecheDescremada(scan.nextInt());
        System.out.println("Intercambios para leche semidescremada: " + D.getIntercambioLecheSemidescremada());
        System.out.print("Dame el intercambio de leche entera: ");
        D.setIntercambioLecheEntera(scan.nextInt());
        System.out.println("Intercambios para leche entera: " + D.getIntercambioLecheEntera());
        System.out.print("Dame el intercambio de leche con azucar: ");
        D.setIntercambioLecheConAzucar(scan.nextInt());
        System.out.println("Intercambios para leche con azucar: " + D.getIntercambioLecheConAzucar());

        //Intercambios de grupo: Fruta
        System.out.print("Dame el intercambio de la fruta: ");
        D.setIntercambioFruta(scan.nextInt());
        System.out.println("Intercambios para la frutar: " + D.getIntercambioFruta());

        //Intercambios de grupo: Verdura
        System.out.print("Dame el intercambio de la verdura: ");
        D.setIntercambioVerdura(scan.nextInt());
        System.out.println("Intercambios para la verdura: " + D.getIntercambioVerdura());

        //Intercambios de grupo: Azucar
        System.out.print("Dame el intercambio de la azucar sin grasa: ");
        D.setIntercambioAzucarSinGrasa(scan.nextInt());
        System.out.println("Intercambios para la azucar sin grasa: " + D.getIntercambioAzucarSinGrasa());
        System.out.print("Dame el intercambio la azucar con grasa: ");
        D.setIntercambioAzucarConGrasa(scan.nextInt());
        System.out.println("Intercambios para la azucar con grasa: " + D.getIntercambioAzucarConGrasa());

        //Intercambios de grupo: Leguminosas y Cereales
        System.out.print("Dame el intercambio la leguminosa: ");
        D.setIntercambioLecheConAzucar(scan.nextInt());
        System.out.println("Intercambios para la leguminosa: " + D.getIntercambioLecheConAzucar());
        System.out.print("Dame el intercambio del cereal sin grasa: ");
        D.setIntercambioCerealSinGrasa(scan.nextInt());
        System.out.println("Intercambios para del cereal sin grasa: " + D.getIntercambioCerealSinGrasa());
        System.out.print("Dame el intercambio del cereal con grasa: ");
        D.setIntercambioCerealConGrasa(scan.nextInt());
        System.out.println("Intercambios para del cereal con grasa: " + D.getIntercambioCerealConGrasa());

        //Intercambios de grupo: Alimentos de origen animal
        System.out.print("Dame el intercambio la carne muy magra: ");
        D.setIntercambioAlimentoMuyMagro(scan.nextInt());
        System.out.println("Intercambios para la carne muy magra: " + D.getIntercambioAlimentoMuyMagro());
        System.out.print("Dame el intercambio la carne magra: ");
        D.setIntercambioAlimentoMagro(scan.nextInt());
        System.out.println("Intercambios para la carne magra: " + D.getIntercambioAlimentoMagro());
        System.out.print("Dame el intercambio la carne semigrasa: ");
        D.setIntercambioAlimentoSemigraso(scan.nextInt());
        System.out.println("Intercambios para la carne semigrasa: " + D.getIntercambioAlimentoSemigraso());
        System.out.print("Dame el intercambio la carne grasa: ");
        D.setIntercambioAlimentoGraso(scan.nextInt());
        System.out.println("Intercambios para la carne grasa: " + D.getIntercambioAlimentoGraso());

        //Intercambios de grupo: Aceites
        System.out.print("Dame el intercambio de aceite sin proteina: ");
        D.setIntercambioAceiteSinProteina(scan.nextInt());
        System.out.println("Intercambios para de aceite sin proteina: " + D.getIntercambioAceiteSinProteina());
        System.out.print("Dame el intercambio de aceite con proteina: ");
        D.setIntercambioAceiteConProteina(scan.nextInt());
        System.out.println("Intercambios para de aceite con proteina: " + D.getIntercambioAceiteConProteina());
    }
}
La clase IOUser lo que hace es crear una dieta con valores default y mandar a llamar a al método estático input de la clase InputDieta para que pueda inicializar los datos de la dieta. Este llamado está dentro de un bloque try, lo que nos permite atrapar cualquier excepción que se arroje dentro de él. 

El bloque catch solamente imprime el StactTrace de la excepción que es una descripción de donde se origina el error de la excepción y todos los saltos que dio para llegar al try. Estuve leyendo que esta manera de desplegar, aunque es un tanto gorrosa para el usuario sirve mucho para hacer debugs de los programas y saber exactamente donde se origina el error.

Lo que hice fue meter los bloques try y catch dentro de un do-while para que el usuario vuelva a meter todos los datos desde el principio, ya que no se puede asegurar que ciertos datos estén bien y otros no (Como es en el caso de que la excepción se mande en la validación de porcentajeTotal). Este do-while solamente finaliza cuando el método input retorna el control del programa al método que lo llamo y después la variable booleana que controla el do-while es asignado con un valor falso para que salga. Si ocurre una excepción dentro del método input, no se ejecuta la instrucción de control es falso. Si no ocurre una excepción el programa continuara con la instrucción control es falso y saldrá del do-while.

Error

Los errores, como bien mencione en la entrada pasada, son en su mayoría errores tanto del JVM (memoria llena, errores internos, stak overflow, etc.) como de errores en la lectura de los recursos externos del programa como lo son lecturas de archivos, conexiones a bases de datos, etc.
package nutrilife.gui;
import java.sql.*;

/**
 *
 * @author Carmen Suarez
 */
public class CreateSQLConnection {
    static final String DRIVER = "com.mysql.jdbc.Driver";
    static final String DATABASE_URL = "jdbc:mysql://localhost/3306/Dieta";
    static final String USUARIO = "root";
    static final String PASSWORD = "";
    public static void connection()
    {
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        
        try {
            Class.forName(DRIVER);
            connection = DriverManager.getConnection(DATABASE_URL, USUARIO, PASSWORD);
            statement = connection.createStatement();
            resultSet = statement.executeQuery("Select * from FichaIdentificacion");
            ResultSetMetaData metaData = resultSet.getMetaData();
            int numberOfColumns = metaData.getColumnCount();

            for ( int i = 1; i <= numberOfColumns; i++ )
            {
                System.out.printf( "%-8s\t", resultSet.getObject(i));
            }
            System.out.println();

            while(resultSet.next())
            {
                for ( int i = 1; i <= numberOfColumns; i++ )
                    System.out.printf( "%-8s\t", resultSet.getObject(i));
                System.out.println();
            }
            
        }
        catch (SQLException sqlException) {
            sqlException.getMessage();
            System.out.println();
            sqlException.printStackTrace();
            throw new Error();
        }        
        catch(ClassNotFoundException classNotFoundException)
        {
            classNotFoundException.getMessage();
            System.out.println();
            classNotFoundException.printStackTrace();
        }
        finally
        {
            try {
                resultSet.close();
                statement.close();
                connection.close();
            } catch (Exception exception) {
                exception.getMessage();
                exception.printStackTrace();
            }
        }      
    }
}
Por lo tanto decidí que si el programa no puede establecer una conexión con la base de datos, esta finalice ya que el programa no sirve para nada sino tiene los datos de pacientes o dietas. 
En la parte
connection = DriverManager.getConnection(DATABASE_URL, 
                                         USUARIO, PASSWORD);
Si no obtiene una conexión con la base de datos, esta lanza una excepción que la tengo que agarrar porque se trata de una clase que lanza excepciones "checked" que a fuerzas se tienen que manejar. La excepción es agarrada por un catch que imprime su StackTrace y lanza un error para finalizar el programa.
También use los bloques finally porque de esta manera puedo asegurarme que aunque se lance o no se lance una excepción y/o error, el programa liberara los recursos de la base de datos. 

La clase todavía le falta bastante para obtener todos los datos, pero necesito ver cómo voy a estructurar las tablas del paciente en la base de datos junto con las tablas de las dietas.

Bueno esto es lo que corresponde a eventos, excepciones y errores de mi proyecto. Espero que hayan entendido, cualquier duda o comentario me lo hacen saber ;) saludos!

miércoles, 6 de abril de 2011

~Semana 10. Eventos, excepciones y errores

Semana 10
Materia: Programación Orientada a Objetos
Martes M1-M3

Hola a todos, en esta entrada les hablaré sobre eventos, excepciones y errores.

Bueno primero que nada se preguntarán que son cada uno de ellos, cuando utilizamos cada uno de estos, entre otras cosas.

Eventos
Un evento es una acción que realiza el usuario, estos eventos avisan al programa que ha realizado el usuario para así que el programa pueda manejarlo de alguna manera. Por ejemplo, cuando presionamos una tecla, cuando damos click en un botón se están generando eventos. 

Esto se debe de tomar muy en cuenta cuando estamos realizando nuestro código ya que debemos de pensar que tipos de eventos pueden llegar a ocurrir y manejar estos eventos de alguna manera. Por ejemplo en mi proyecto yo me pongo a pensar mucho en que va a haber botones por ejemplo de guardar o de crear cita y cosas así y yo tengo que avisarle a mi programa que al momento de que el usuario presione el botón de guardar, tiene que realizar los métodos necesarios para guardar todos los datos. 

La forma de manejar estos eventos en programación orientada a objetos se conoce como emisor/receptor donde el emisor se hace cargo de enviar el evento mientras el receptor lo recibirá y lo manejará de la forma que sea mas conveniente.




Algunos tipos de eventos. 
  • ComponentEvent:  Se produce este evento cuando el usuario mueva un componente.
  • FocusEvent:  Se produce este evento cuando se cambia el foco de un componente.
  • KeyEvent:  Se produce este evento cuando el usuario pulsa una tecla.
  • MouseEvent:  Se produce cuando el usuario realiza un movimiento con el mouse o haga un click.
  • ContainerEvent:  se produce cuando se añaden o eliminen componentes en el contenedor.
  • WindowEvent:  se produce cuando se realice algún tipo de operación con la ventana como abrirla y cerrarla.
  • ActionEvent:  Se produce cuando se efectúe alguna acción sobre un componente, por ejemplo, cuando pulsas un botón.


Como lo mencioné en mi proyecto se utilizarán varios eventos para cuando presionen los botones que espero que tenga mi programa como por ejemplo cuando den click a un botón guardar que esto ocasione que los datos se guarden, así pasará con todos los botones que tenga mi programa. También quiero que mi programa tenga diferentes pestañas que por ejemplo cuando elijas ver un paciente de la base de datos y te despliegue sus datos personales que tenga pestañas como historial, dieta del paciente y cosas así entonces yo creo que un evento también sería cuando cambia de pestaña y le despliega algo diferente.


Excepciones
Las excepciones se utilizan para la detección y corrección de errores. Si hay un error el programa no debería tronar y cerrarse, esto se debe evitar por medio de excepciones. Se lanza un throw con una excepcion para después poner un catch que captura el error y lo resuelve. Esto es para que el programa no se cierre y siga en funcionamiento. 

Tipos de excepciones.
  • Error: excepciones que indican problemas muy graves, de los que normalmente no se pueden recuperar.
  • Exception: Excepciones no definitivas, pero que se detectan fuera del tiempo de ejecución.
  • RuntimeException: Excepciones que se dan durante la ejecución del programa.

Todas las excepciones tienen como clase base la clase Throwable que es la que maneja todos los errores y excepciones. 

En mi programa se manejan muchas excepciones como las siguientes:

  • Una excepción que podría ser es cuando tenemos un paciente que tiene una enfermedad o por ejemplo que sea intolerante a la lactosa pues obviamente no tolera la leche con lactosa entonces se las podriamos eliminar, o en caso de que seleccione esta puede mandarle un mensaje que esto le puede hacer daño.
  • Otra excepción que quiero poner es por ejemplo en el caso de los intercambios de energía o todos los datos que deseamos ingresar, si el usuario en ves de poner un número pone un string el programa manejará una excepción que haga que muestre un mensaje para que vuelva a ingresar el dato correctamente.
  • También en algunas operaciones como en la dieta el porcentaje total de carbohidratos, proteinas y lípidos debe de dar 100% entonces si no da esto mandar un mensaje que no están bien los porcentajes.

Estas excepciones son las que he pensado pero creo que puede haber más, creo que cuando ya tenga la interfaz gráfica podrán salir más errores ya que al estarlo probando ya podré saber que otros errores pueden presentarse. 


Errores.
Como lo mencioné en un apartado de excepciones los errores son problemas que son imposibles de reparar, o sea que cuando sucede un error grave el programa se cerrará. Esto lo usaré en el peor de los casos que ya no se pueda hacer nada. Por ejemplo en la conexión con la base de datos creo que puede ser útil ya que si por ejemplo no se encuentra la base de datos el programa no puede hacer nada para resolver este problema y tendrá que cerrarse. 

Bueno esto es lo que corresponde a eventos, excepciones y errores de mi proyecto. Espero que hayan entendido, cualquier duda o comentario me lo hacen saber ;) saludos!

~Semana 9. Patrones de Diseño

Semana 9
Materia: Programación Orientada a Objetos
Martes M1-M3

Hola a todos, en esta entrada les hablaré sobre los patrones de diseño.
Abstact Factory 
El propósito de este patron de diseño proporciona un contacto para crear familias de objetos relacionados o dependientes sin tener que especificar su clase concreta.

Por ejemplo. 
Si tienes que administrar información de contactos con sus respectivos teléfonos y direcciones, como se hace en una agenda. Se tendrían que crear clases para administrar direcciones, números de teléfono y nombre de contactos. Estas clases tendrán que almacenar información de los contactos con ciertos formatos. Por ejemplo en Norteamérica todos los números de teléfono están limitados a 10 dígitos y el código postal también tiene cierto formato. 

También puede ser que administrando los contactos, algún contacto tenga números de teléfono de otros países, por ejemplo Holanda, en Holanda tienen diferentes reglas para los números de teléfono o direcciones válidas por lo que se tienen que realizar validaciones. Cada vez que se agreguen más y más contactos esto se irá extendiendo de más y más reglas y se tendrá que estar modificando y recompilando el código. 

Abstact Factory es una solución a este problema ya que con este patrón se define una clase AdressFactory para generar objetos que siguen un patrón general pata Address y PhoneNumber. En tiempo de ejecución esto se asocia con un número de fábricas para distintos países y cada país tiene su propia versión de las clases Address y PhoneNumber.

Este patrón es aplicado cuando:

  • El cliente debe ser independiente del proceso de creación de los productos.
  • La aplicación debe configurarse con una o más familias de productos.
  • Es necesario crear los objetos como un conjunto, de forma que sean compatibles. 
  • Desea proporcionar una colección de clases y únicamente quiere revelar sus contratos y relaciones, no sus implementaciones.
Ventajas y desventajas

Una Abstact Factory ayuda a incrementar la flexibilidad general de una aplicación. Durante el diseño, no se tiene que predecir todos los usos futuros de la aplicación, se crea un framework general y se desarrollan implementaciones independientes del resto de la aplicación. En tiempo de ejecución, la aplicación puede integrar fácilmente nuevas características y recursos.

Otra ventaja es que se puede simplificar la comprobación del resto de la aplicación. Implementando unas clases TestConcreteFactory y TestConcreteProduct puede servir para simular el comportamiento esperado de los recursos.

Si el producto abstracto no está definido apropiadamente, puede resultar difícil o incluso imposible generar productos concretos deseados.



Abstact Factory en mi Proyecto.  
Según lo que entendí y con este ejemplo que puse creo que podría utilizar este patrón de diseño en Dietas, ya que habrá diferentes tipos de dietas con diferentes formatos ya que algunas dietas tendrán ciertas excepciones, pienso que en la cuestión de los alimentos se puede utilizar este tipo de patrón. 


Prototype
Este patrón de diseño facilita la creación dinámica al definir clases las cuales sus objetos pueden crear copias de si mismos.

Aplicado a mi Proyecto.
Cuando se necesite copiar algún objeto con el fin de que el usuario no tenga que introducir manualmente toda la información cuando se crea un nuevo paciente por ejemplo. Una solución a este problema es.
Crear un nuevo objeto Paciente y copiar los valores del objeto Paciente existente.

La desventaja de este patrón es que viola el principio de encapsulación de la orientación a objetos, esto me hace estar un poco indecisa en usar o no usar este patrón. Para poder llegar a esta solución se tienen que hacer llamadas a métodos para copiar la información necesaria. Esto quiere decir que es más difícil mantener el código de la clase Paciente porque se extenderá en todo el proyecto. Además que también dificulta la reutilización de la clase Paciente.



Ventajas
El patrón de diseño Prototype es muy útil porque permite que los sistemas generen una copia de un objeto, con variables ya establecidas a un valor significativo.


Adapter
Este patron de diseño es de tipo estructural, sirve como intermediario entre dos clases, convirtiendo las interfaces de una clase para que pueda ser utilizada por otra.

Una de las ventajas de la programación orientada a objetos citada con mayor frecuencia es que permite la reutilización del código. Como los datos y el comportamiento se centralizan en una clase, puede mover una clase de un proyecto a otro y reutilizar su funcionalidad.

Por ejemplo, si estas realizando un gestor de información personal y un amigo de otro país decide cooperar contigo ya que tu amigo ha estado trabajando en un proyecto similar y puedes proporcionarle una implementación comercial de un sistema. Pero al momento de recibir los ficheros, la interfaz no corresponde con las interfaces que el ha estado utilizando en su aplicación y también puede que el código esté en otro idioma que el no conoce.

Tendrías dos soluciones posibles.

  • La primera opción sería reescribir el componente para que implemente todas las interfaces requeridas. Reescribir el nuevo componente es algo menos recomendable porque tendrías que hacer esto mismo cada vez que recibas la última versión de tu amigo.
  • La segunda opción es reescribir su propia aplicación y empezar a utilizar nuevas interfaces. La desventaja es que tendrías que recorrer todo su código para cambiar todas las ocurrencias de la interfaz antigua.
Lo que se necesita es un traductor -un componente que traduzca las llamadas de una interfaz en llamadas a otra interfaz distinta.
La verdad no se si esto aplique en mi proyecto, aunque si lo voy a comercializar sería bueno pensar en este tipo de patrón de diseño. 

Bueno, esto es todo de patrones de diseño, cualquier comentario ya saben pueden hacerlo :D saludos