Estuve algunos días ocupado con otras cosas, y el SWT/ST2JS/etc no
avanzaron mucho. Ahora estoy por volver a la actividad, y como el
movimiento se demuestra andando les comento en que estado estamos.
Sigo detenido en el punto MVC-Distribuido. Si bajan las últimas
versiones, verán que está funcionando relativamente bien.
La versión actual prueba (creo, decidan ustedes mismos) que es posible
hacer una aplicación MVC donde el M(odel) esté en el server (Smalltalk)
y el V(iew)/C(ontroller) esté en el cliente (Browser de Internet). Para
lograr tiempos de respuesta adecuados, algunas optimizaciones ya fueron
hechas y funcionan bastante bien.
Para acelerar los tiempos de respuesta, básicamente hay que reducir la
cantidad de requests desde los clientes.
Mensajes Asincrónicos/Cola de mensajes asincrónicos:
----------------------------------------------------
En una aplicación típica MVC, el View se conecta a MUCHOS eventos del
modelo. Cada suscripción implica un envío de mensaje. Si el Modelo
está remoto, eso implica 1 request por internet. Imaginemos un simple
objeto de clase Cliente, con algunos aspectos como #nombre, #apellido,
#fechaDeNacimiento y #dni. Para crear una Vista con esos aspectos, el
View/Controller deberá suscribirse a los eventos de nombre #nombre,
#apellido, #fechaDeNacimiento y #dni... es decir: 4 requests.
Si a eso le sumamos que, antes de suscribirse hay que hacer un request
para pedir una referencia remota, tendremos que hacer N+1 requests para
crear una vista sobre un objeto con N aspectos.
El caso empeora cuando cargamos un objeto en la vista y descargamos
otros. En ese caso necesitamos N+1 requests para el objeto nuevo
(siendo N la cantidad de aspectos del objeto nuevo) y M requests para
desuscribirse de los eventos del objeto viejo (siendo M la cantidad de
aspectos del objeto viejo).
Por supuesto eso mataría la velocidad del cliente.
Sin embargo encontré una forma de optimización que funciona muy bien, y
logra resolver el caso dado (con o sin objeto viejo) haciendo SIEMPRE 2
requests: 1 para obtener la referencia remota al objeto nuevo, y 1 para
hacer (en batch) TODAS las desuscripciones y suscripciones.
El truco consiste en lo siguiente:
- Cuando hacemos un envío de mensaje al #serverSide, y no
necesitamos un valor de respuesta, podemos hacer el envío
asincrónico. Para poder tomar ventaja de esto, el proxy
generado del ServerApplication incluye 2 métodos por cada método
del ServerApplication, uno para invocarlo sincrónicamente y otro
para hacer asíncrono.
- El framework permite encolar muchos envíos de mensajes
asincrónicos en 1 sólo pedido, simplemente haciendo algo como:
aRemoteModel. "Referencia remote obtenid"
self isolatedAsynchronousRPCMethods: [
mainPanel clearWidgets. "Limpia los widgets viejos, causando que el browser se desconecte de los eventos al modelo anterior."
mainPanel addWidget: aRemoteModel defaultView. "Crea la nueva vista al nuevo modelo, causando la conexión a los eventos del modelo nuevo."
].
(Ver senders/implementors de #isolatedAsynchronousRPCMethods:)
Eventos extendidos:
-------------------
Otro patrón típico de las aplicaciones MVC es que el View envíe un
mensaje (por ejemplo el mensaje #nombre) cuando se entera que el modelo
cambió (por estar suscripto al evento de nombre #nombre). Si tenemos en
cuenta que el Modelo está en el servidor, y que las Vistas/Controladores
están en los browsers, veremos que cuando el modelo cambia (y el evento
se propaga a los browsers, usando la conexión Comet) todas las vistas
enviarán un mensaje al Server para obtener el nuevo valor del modelo.
Para optimizar ese caso, expandí (levemente) el mecanismo de eventos.
Así se suscribe un Aspecto (SWTAspect) al modelo.
self model
when: self eventName
send: #modelChanged:
to: self
withResultsOfSelectors: {self getter}
La clave está en la última parte del mensaje: "withResultsOfSelectors:
{self getter}". Cuando ocurre un evento de nombre "self eventName", el
modelo enviará el mensaje "#modelChanged:" a "self", INCLUYENDO en el
envío el resultado de enviar el mensaje "self getter" al modelo.
Con ese "truco", el evento se propaga con la información extra necesaria
evitando que los clientes (browsers) tengan que hacer un pedido.
¿Cómo sigue el trabajo? --> Hay que lograr que un usuario del framework
no tenga que manejar a mano la complejidad inherente a tener un MVC
distribuido. Para eso el framework debe auto-optimizarse (usando estos
trucos, y otros que se nos ocurran) desde el uso normal. Este objetivo
está, en parte, también resuelto: Si uno se limita a usar los Aspects
entregados por SWTModel para crear las vistas, tendremos todas estar
optimizaciones ya hechas.
Entonces ahora toca encontrar una forma de describir los modelos, que
sea Smalltalk-way, pero que tenga el nivel de abstracción correcto para
poder meter optimizaciones por debajo. En la versión actual la
sobre-cargada-de-responsabilidades clase SWTAspect, y la clase
SWTRemoteModel logran esconder la complejidad... pero, como les dije,
SWTAspect es casi un engendro de mezclas de responsabilidades.
Después de esta sábana de email, les dejo estas preguntas:
- ¿Qué framework de hacer UIs (de Smalltalk u otro lenguaje) les
parece más poderoso?
- ¿Qué tipo de framework permitiría crear vistas automáticas?
-- ¿Cuanto de difícil es tunear a mano esas vistas automáticas?
- ¿Vieron el NakedObjects (http://nakedobjects.org/)? ¿Qué les
parece?
Saludos,
-- Diego
--
==========================================
Diego Gomez Deck
------------------------------------------
http://diegogomezdeck.blogspot.com/
http://smalltalk.consultar.com/
==========================================
Respondo entre lineas...
>
> Despu s de esta s bana de email, les dejo estas preguntas:
>
> - Qu framework de hacer UIs (de Smalltalk u otro lenguaje) les
> parece m s poderoso?
Recuerdo lo bien que la pasaba cuando hacía UIs con el WindowBuilder
de SmalltalkV.
Ahora hay cosas "mas modernas" (para el framework SWT de java, el
www.swt-designer.com es bastante piola para usar...)
>
> - Qu tipo de framework permitir a crear vistas autom ticas?
Estoy leyendo bastante y haciendo pruebas con Magritte y lo encuentro
muy potente y simple de usar. Además uno describe una clase y despues
puede verla de distintas maneras:
- En Morphs escribiendo algo como:
result := aModel asMorph
addButtons;
addWindow;
callInWorld.
- Para seaside:
result := self call: (aModel asComponent
addValidatedForm;
yourself).
- Se podría pensar en generar vistas de SWT2.0
> -- Cuanto de dif cil es tunear a mano esas vistas autom ticas?
Con Magritte uno cuenta con la posibilidad de definir como quiere que
se vean lo que se genera a partir de los descriptores. Por ejemplo
debería hacer una clase SWT2EntryField para permitir la entrada de
texto y esa clase sería la que estaría bindeada con un atributo del
model e interactuaría con el server.
>
> - Vieron el NakedObjects (http://nakedobjects.org/)? Qu les
> parece?
si, lo ví hace un tiempo... pero me quedo con Magritte porque me
parece mucho más customizable
>
> Saludos,
>
> -- Diego
Saludos!
Pablo.-