Arena. Navegación. Estado de la vista.

Algunas cuestiones pendientes

Nos queda pendiente trabajar sobre dos temas que son comunes al diseñar UIs:

  1. Navegación (cómo es el flujo de una vista a otra y cómo se pasa información desde una vista a otra)
  2. Manejo del estado conversacional de los datos que se cargan en la vista

Pasaje de información entre paneles y navegación

Esto se da en dos oportunidades en nuestro ABM modelo:

  • cuando queremos crear un nuevo socio/celular/etc.
  • cuando queremos editar la información de un socio/celular/etc. existente

En el primero de los casos, la ventana de búsqueda no necesita pasar ninguna información a la pantalla de edición. Generamos un nuevo socio desde cero y luego se lo pasamos al repositorio o home que se encarga de agregarlo al repositorio. Entonces, ¿cómo me aseguro que el panel de búsqueda va a encontrar el socio/celular recientemente cargado?

  • si el repositorio trabaja con una base de objetos que es un archivo externo, este archivo sirve como sincronizador de las dos pantallas
  • si el repositorio o home trabaja con una colección en memoria, no podemos dejar que se creen múltiples homes. Esto quiere decir: si el panel de búsqueda trabaja con un home, y la pantalla de edición crea otro home diferente, esto va a traer problemas cuando volvamos a la búsqueda, porque no vamos a encontrar el socio/celular que acabamos de crear. Entonces el home lo creamos como Singleton, dado que al vivir ambas vistas (búsqueda y edición) en el mismo ambiente donde corre la aplicación, nos aseguramos un único punto de acceso. Claro, el Singleton tiene una desventaja: se parece mucho a una variable global. Por eso no es bueno abusar de singletons en nuestras aplicaciones.

Para editar una entidad sí necesitamos pasar la información de esa entidad del panel de búsqueda al de edición.

Y además tenemos que ver cómo nos encargamos de navegar de una pantalla a otra. Entonces:

  • Hay que abrir una ventana de diálogo: a partir de aquí el control pasa al formulario de edición (porque es una ventana modal)
  • Y setearle el modelo a la pantalla de edición
    • en el caso del alta, es una nueva entidad
    • en el caso de la edición, hay que pasarle el elemento seleccionado de la grilla (es la propiedad selected del application model del panel de búsqueda, está definido en Search<T>)

Esto lo vemos implementado en el ejemplo de los celulares:

Entonces, ¿cómo manejamos la navegación? Hacemos el new de la vista y le enviamos el mensaje open. Tan sencillo como eso.

¿Y cómo pasamos información de una pantalla a otra? Para inyectar dependencias hay dos formas sencillas de hacerlo

  • en el constructor (constructor injection)
  • a partir de un setter (setter injection)

Lo que le pasamos al constructor de la pantalla de edición es el modelo. Esto permite que se asigne como model y todos contentos.

Resumiendo:

  1. se abre la ventana de edición con un objeto nuevo o existente
  2. el usuario edita el objeto
  3. y presiona el botón aceptar (esto actualiza la información)
  4. entonces se dispara una nueva búsqueda (línea onAccept)
  5. que eventualmente envía una notificación a la grilla para que se actualice.

Esta es una forma declarativa de trabajar:

  • tenemos menos control sobre el algoritmo (no nos enteramos de lo que pasa por abajo, pasamos por alto muchos detalles de implementación)
  • necesitamos para eso que alguien resuelva ese algoritmo (en nuestro caso es el framework Arena el que actúa de motor, el que hace la magia)
  • nos concentramos más en el qué y no tanto en cómo lograrlo.

Cuando enviamos el mensaje editor.open() estamos interrumpiendo el flujo de ejecución de la pantalla principal. Entonces toma el control la pantalla de edición que vimos en la primera clase.

Nos detenemos una vez más en la línea

porque plantea algo muy interesante: antes de llamar a la pantalla de edición (mucho antes de que el usuario vea esa pantalla y presione Aceptar) estamos guardando un comportamiento que tiene que ocurrir cuando esa edición termine exitosamente. Esa idea (diferir la ejecución de código) está presente en el Command Pattern [1], y la estamos implementando de esta manera.

Cancelar la transacción

Recordemos que cuando abrimos una pantalla de edición, necesitamos como modelo un socio, un celular, una entidad. Entonces, si el usuario se arrepiente y cancela la acción, la transacción no debe completarse. Una de las maneras de lograr esto es no enviar ningún mensaje al repositorio para que lo actualice. Es importante entender que cuando hacemos un new del objeto de dominio eso no tenga efecto colateral sobre el home, de otra manera debemos deshacer ese new o la modificación propiamente dicha.