Mi cursada - UNQ‎ > ‎Clases‎ > ‎Bitácoras‎ > ‎Bitácoras 2011 S1‎ > ‎

Lunes 21/3/2011

publicado a la‎(s)‎ 21 mar. 2011 20:34 por Nicolas Passerini   [ actualizado el 22 mar. 2011 21:16 por gisela decuzzi ]

Excepciones

Arrancamos planteando algunos conceptos básicos de excepciones y de la forma en que las vamos a utilizar:
  • La forma que tienen los lenguajes modernos de indicar que una tarea no se puede llevar a cabo es mediante una excepción. Según esta forma de pensar, siempre que algo no se puede hacer se debe indicar con una excepción.
  • Mencionamos algunas de las ventajas de usar excepciones, como que tienen más información que utilizar booleanos, nulos o códigos de error, permiten ordenarse estructuralmente. De las ventajas destacamos la interrupción del flujo de ejecución.
  • Desde el punto de vista técnico diferenciamos excepciones chequeadas y no chequeadas. Por distintos motivos nosotros en esta materia preferimos usar excepciones no chequeadas.
  • Desde el punto de vista conceptual, diferenciamos excepciones de programa y excepciones de usuario. Mencionamos que al usar el framework Arena, las excepciones de usuario se indican lanzando UserException.
Algunas ideas de diseño:
  • Preferimos que las validaciones del dominio se encuentren en los objetos de dominio (vamos a volver sobre este punto más tarde).
  • Las excepciones permiten que el dominio le indique a la UI cuando se intenta utilizarlo de una forma inadecuada. Específicamente, el dominio tira una excepción de usuario que la UI atrapa para indicarle al usuario el error que cometió.
  • Muchas veces, las excepciones de una aplicación son atrapadas por la interfaz de usuario, por eso van a tener un papel importante en nuestra materia.
Nos quedará para la próxima clase hablar sobre los lugares en donde vamos a poner las validaciones. Por ahora mencionamos la posibilidad de poner validaciones en los setters.

Segunda parte: Construir nuestra primera aplicación siguiendo el patrón Model-View-Controller

A. La vista

Nos basamos en un ejemplo muy sencillito: una calculadora que convierte millas a kilómetros. Ingresás una distancia en millas, presionás un botón convertir y te la convierte a kilómetros. Dado que vamos a trabajar con interfaces orientadas a objetos, comenzamos pensando qué objetos intervienen en esa interfaz. Rápidamente surgen cuatro objetos bien visibles:
  • Una caja de texto que nos permite ingresar una distancia en millas.
  • Un botón que dispara la conversión.
  • Un label que muestra el resultado.
  • Una ventana que contiene a todos los demás.
Si bien son menos obvios, nos dimos cuenta de que estamos usando dos más:
  • Un panel, que agrupa a los otros tres componentes. En realidad entonces la ventana no contiene a los componentes sino únicamente al panel, y este a los componentes. Esto es por una cuestión técnica, en el framework que vamos a usar, las ventanas tienen un panel principal y los demás componentes se agregan a este panel, en otras tecnologías podrían agregarse directamente a la ventana sin necesidad del intermediario.
  • Un layout, que es el que tiene la responsabilidad de "acomodar" los componentes dentro del panel que los contiene. Más adelante vamos a ver qué tipos de layout hay.
Construimos esos objetos en Arena, para eso hicimos una clase que extendiera de MainWindow; eso nos obliga a implementar el método createContents, que describe el contenido de la ventana, y nos quedó así:
    @Override
    public void createContents(Panel mainPanel) {
        mainPanel.setLayout(new VerticalLayout());

        TextBox millas = new TextBox(mainPanel);

        Button convertir = new Button(mainPanel);
        convertir.setCaption("Convertir");

        Label kilometros = new Label(mainPanel);
    }

Y hacemos en la misma clase un main para poder ejecutarlo:
    public static void main(String[] args) {
        new ConversorWindow().startApplication();
    }

Una cosa a tener en cuenta es que en Arena es obligatorio definirle un layout a todos los paneles. También vimos que los componentes de Arena utilizan el patrón Composite.

B. El modelo

Nuestro modelo es muy sencillo: un objeto Converter con dos propiedades: millas y kilometros (con sus respectivos getters y setters) y un método convertir que toma el valor de millas, lo convierte y lo guarda en el atributo kilometros.

Estos son dos patrones que van a seguir muchos de nuestros objetos de negocio:
  • Las características de nuestros objetos que sean visibles por el usuario estarán representadas por pares getter/setter. Cuando nos referimos a un atributo de un objeto, pensamos en un par getter/setter, si eso tiene un field atrás no es importante para nosotros, nos interesa la interfaz y no la implementación.
    Un detalle es que a veces puede aparecer el getter solamente, esto denota un atributo inmutable.
  • Las acciones de nuestros objetos que son ejecutables por el usuario estarán representadas (muchas veces) por métodos que no reciben parámetros y no devuelven nada. Esto puede resultar un poco restrictivo, pero simplifica mucho la relación entre dominio y vista; y toda la información que se necesite intercambiar se puede hacer casi siempre utilizando atributos.

C. El controller

Habiendo hecho vista y modelo pasamos a pensar en el controller. Como verán, en este modelo muy simple hay una relación casi uno a uno entre los conceptos de la vista y los del modelo:
  • Tenemos una ventana para el Conversor
  • Un TextBox para la propiedad millas
  • El Button puede asociarse al método convertir
  • Y el Label muestra el valor de la propiedad kilometros
En la medida de lo posible es una buena práctica mantener este tipo de asociaciones uno a uno entre vista y modelo, porque simplifican mucho establecer la relación entre ambos, que en muchos casos es la parte más complicada de la UI.


La forma preferida de vincular vista y modelo es a través de eventos. Tanto la vista como el modelo pueden tirar eventos y obviamente escuchar los eventos que tira el otro. El patrón detrás del concepto de evento es el observer (o listener) y lo que nos permite es tener una comunicación bidireccional sin producir un acoplamiento.

C1. Asociar un listener a un evento de la vista

El caso más fácil de evento es el que se produce al presionar el botón "convertir". Para asociarle un observer a ese evento utilizamos el mensaje onClick, que recibe algún objeto que implemente la interfaz Action.
La implementación más sencilla de esa interfaz es la clase MessageSend, que recibe un objeto y un nombre de método (sí un String) y lo invoca por reflection.

C2. Disparar eventos desde el modelo

Esta parte depende mucho de las posibilidades que den los distintos lenguajes para manejar eventos. En Java utilizamos los eventos de java.beans, para más información vayan a la página de documentación de Manejo de Eventos en Java.

La forma más simple que tiene el framework Arena para disparar un evento ante la modificación de una propiedad de un objeto del domino es:
  1. Hacer que nuestro modelo extienda de ObservableObject.
  2. Programar nuestros setters utilizando setProperty, en lugar de acceder al atributo directamente:

        public static final String MILLAS = "millas";

        private double millas;

        public void setMillas(double millas) {

            this.setProperty(MILLAS, millas);
        }

    Donde el String "millas" hace referencia al nombre del field millas.

    Naturalmente la constante MILLAS no es necesaria, pero es una herramienta útil para reducir el riesgo de errores al usar tantos Strings (van a ver que el trabajo con reflection produce una proliferación de esos Strings que representan nombres de métodos, atributos o fields).
Nótese la diferencia que hacemos entre fields y atributos. Llamamos field a la variable de instancia, es una cuestión de implementación. Por otro lado con atributo o propiedad nos referimos a un par de métodos getter/setter, es decir es una cuestión de interfaz.

En este caso, como en muchos, la implementación del atributo es a través de un field con el mismo nombre, pero vamos a ver que eso no tiene por qué ser así.

Finalmente, el método setProperty es útil solamente en este caso simple en el que atributo y field coinciden, en los casos más complejos se debe disparar el evento manualmente, invocando a firePropertyChange.

C3. Binding

El siguiente paso sería poner listeners entre el TextBox y la propiedad millas. Lo que este listener tiene que hacer es bastante simple: escucha el evento que se produce al cambiar el valor del TextBox y en ese momento actualiza el atributo millas.

Como este tipo de listeners es muy común, existe un mecanismo de más alto nivel que lo hace más sencillo, denominado binding (es decir: vinculación).

El caso más simple de binding es el que vincula (o "bindea") una característica de la vista (por ejemplo el valor de un TextBox) con una propiedad del modelo. En Arena esto se indica de la siguiente manera:

    TextBox millas = new TextBox(mainPanel);
    millas.bindValueToProperty(Conversor.MILLAS);

Aunque en este caso no es necesario, por defecto el binding es bidireccional, es decir los cambios pueden provenir tanto del modelo como de la vista y ambos valores se van a mantener sincronizados. En nuestro ejemplo vemos ambos tipos de comunicación:
  • Los cambios en el valor del TextBox se propagan a la propiedad millas.
  • Los cambios en el valor de la propiedad kilometros se reflejan en el Label.
Más adelante vamos a ver ejemplos más complicados de binding.

Tareas para las próximas clases

  • Si no lo hicieron es la última oportunidad para repasar sobre patrones. En esta clase mencionamos Observer, Composite, Template Method y Command.
    Si tienen dudas sobre algunas de las tecnologías que usamos (Java, Eclipse, svn) por favor hágannoslo saber así les vamos pasando material al respecto.
  • Para el jueves 31 hay que tener andando el dominio, con sus respectivos tests y validaciones. El que tiene ganas de adelantar algo de UI tanto mejor, pero no es indispensable. Para esto último les tenemos que pasar bien la info sobre las dependencias del maven, en el transcurso del fin de semana van a recibir eso.
  • Los apuntes sobre elementos de Java los van a encontrar en esta página. De eso les recomiendo leer:
  • Por otro lado, recomiendo leer sobre JavaBeans, ya que es una herramienta que va a aparecer en todos los frameworks Java.

Les debemos algún apunte (no dejen que me olvide), pero creo que con esto ya tienen para un rato.




Comments