Seaside - Diseño avanzado

Qué conocemos hasta aquí

  • Seaside es un framework que permite construir aplicaciones web en Smalltalk
    • diseñamos objetos componente, que se alejan bastante de la página web (no hay get ni post)
    • también tenemos objetos que modelan tareas (WATask), donde definimos una secuencia de pasos: cada paso de la secuencia puede implicar el armado de una página, pero esto es transparente para el programador (el ida y vuelta queda escrito en un único método go)
  • Algunas cosas que podemos notar:
    • escribir la pantalla puede volverse algo tedioso dado que tenemos que armar explícitamente cada control html como un "brush" (esto incluye los controles input type text, input type button pero también el line break, los divs, etc.)
    • el binding es manual, nosotros debemos asociar cada control a una parte del dominio

Diseñando en Seaside

El punto es que los componentes en seaside son objetos y se definen por clases, entonces tenemos las mismas herramientas para diseñar que cuando trabajamos con clases y objetos en cualquier otra parte de nuestro sistema.

Para otra oportunidad

  • Definir componentes decoradores
  • Formularios

Búsqueda de libros en Seaside

Los ejemplos cross como la búsqueda de libros nos permiten dejar fijo el requerimiento y concentrarnos en las diferencias tecnológicas a la hora de implementarlo. En este ejemplo tenemos:

  • Una pantalla de búsqueda de libros con la posibilidad de Eliminar uno o Editar (llama a la pantalla de edición)
  • Un botón "Nuevo Libro" que llama a la pantalla de edición
  • La vista de Edición es compartida para Crear / Modificar al igual que en la mayoría de los ejemplos

Pueden descargar el ejemplo e investigarlo, algunas cosas para destacar.

El modelo de dominio

  • ok, es un Libro con titulo, autor.
  • Con Refactor class > Accesor creamos los getters y setters
  • Redefinimos el printOn: (el equivalente al toString() de Java) para mostrar título y autor por default

Home de libros

  • El Home conoce a muchos libros, es una colección
  • Sabe agregar, eliminar, consultar y modificar libros
    • agregar es un add: a la colección
    • eliminar es un remove: de la colección
    • modificar reemplaza un objeto Libro viejo por uno nuevo,

Vista Búsqueda de libros

  • Hereda de WABusquedaLibrosComponent pero sólo para definir el estilo en un css inline, esta no es una técnica recomendable pero lo hacemos por cuestiones didácticas, esto evita que tengan que configurar un .css por afuera de la category. Para más información vean este link.
  • La búsqueda tiene un solo método: renderContentOn:, si bien es fácil de leer hay que reconocer que es bastante "verboso" y es inevitable que crezca cada vez que le agreguemos más funcionalidad. Pueden ver cómo diseñar al estilo Arena 1.0 en el ejemplo de los celulares, el alcance de la clase no obstante llega hasta este ejemplo.
  • Para definir una grilla hay que utilizar los brushes tableHeading: (TH), tableRow: (TR), tableData: (TD), etc.
  • Para llenar la grilla hay que "recorrer" los libros que están en la home, esto se logra enviando un mensaje al Singleton de HomeLibros. HomeLibros current nos devuelve la instancia de home y a esa instancia le enviamos el getter libros, a la colección la podemos "recorrer" con do:
  • Por cada libro generamos
   html tableData: [ 

(html anchor) callback: [ self show:

((WAEditLibroComponent new)

libro: libro;

alta: false) ];

with: libro titulo ].

Parece difícil de leer pero en realidad:

  • mensaje tableData: genera un TD
  • defino un <a href> con el brush anchor
    • le seteo como callback que dispare un show de un componente de edición, al cual le voy a pasar el libro y un booleano para decir que no estoy dando de alta el libro
    • el anchor muestra como descripción del link el título del libro
  • En la pantalla de edición voy a tener cierta precaución: cuando el usuario selecciona un Libro para modificarlo, yo tengo la misma referencia que el home, si edito el libro y el binding es automático, eso puede disparar una actualización no deseada del libro (si el usuario presiona Cancelar eso no debe tener impacto en el Home). Entonces cuando le seteo el libro desde el callback del anchor voy a quedarme con una copia del libro que le paso, esto se logra enviando un mensaje shallowCopy al libro:
>>setter de WAEditLibroComponent
libro: anObject
      libroOriginal := anObject.

libro := anObject shallowCopy.

  • Para eliminar un libro defino simplemente un callback desde la vista de búsqueda para que envíe un mensaje al home pasándole el objeto Libro que estoy recorriendo. Por ese motivo en el ejemplo no necesitamos identificadores, aún cuando estamos programando en web y el link Eliminar nace del cliente y dispara un request al servidor: volvemos a repetir que esto es felizmente transparente para nosotros.

html tableData: [ (html anchor) callback: [ HomeLibros current eliminarLibro: libro ];

with: 'Eliminar' ] ]

  • El binding de la grilla es manual, cada vez que el usuario presiona buscar se hace un foreach (do:) de los elementos del home. Esto es mucho menos declarativo que la solución que teníamos en la unidad 2 (Arena), donde simplemente le decíamos a la grilla qué propiedades estaban asociadas a cada columna de la grilla y a la grilla misma cuál era su modelo (al que tenía que observar, el modelo tenía la responsabilidad de notificarle los cambios). De la misma manera la pantalla de edición maneja el binding en forma manual, mediante un callback que funciona como observer del libro que es el modelo de la vista.

Si bien nos detenemos en este punto hay mucho más para investigar de esta tecnología que ofrece un interesante punto de partida para desarrollar aplicaciones web.