Sunday, September 16, 2007

Probando, probando

Pues como íbamos diciendo en posts anteriores, ya es hora de ir escribiendo algo de código. He puesto en el repo de twinpanel un ejemplo mínimo de inspector/vista/controlador llamado mvc.py.

Tal como hablábamos Oscar y yo, no es posible desacoplar totalmente vista y modelo cuando se usa "gtk.TreeView", ya que obliga a que el formato del modelo (colores y demás atributos) también esté en el modelo. A pesar de que rompe la idea de MVC, parece conveniente apostar por TreeView porque nos da gran parte del trabajo ya hecho.

Otro problema de TreeView es que, al menos en el uso habitual, la configuración de las columnas "visibles" (TreeViewColumn, TVC) se realiza en base al modelo (store) disponible, con lo cual hay mucho acoplamiento entre ambos. Y esto va totalmente en contra de nuestra idea de hacer vistas "plugables" que puedan utilizarse con muchos inspectores diferentes.

Afortunadamente, TreeView dispone de un mecanismo que permite rellenar las columnas utilizando un callback en lugar de indicar una columna de un store: set_cell_data_func(). Utilizando esta alternativa y definiendo un metamodelo (que describe el modelo) es posible hacer vistas totalmente genéricas, que se autoconfiguran en base a la información facilitada por cada inspector concreto.

En cualquier caso, TreeView sigue necesitando un store. Hemos optado por hacerlo lo más simple posible: un array de objetos. La clase de esos objetos la define cada inspector, y su metamodelo indica cómo obtener los datos a partir de los objetos contenidos en el store. De modo que es muy flexible y con el acoplamiento más pequeño posible (de los que se nos han ocurrido).

Tal cómo está implementado en el programa que refería, este sistema tiene algunas limitaciones:
  • Cada elemento del metamodelo corresponde a una columna de la vista. Por cada TVC, se crea un único 'cellrenderer' (indicado en el metamodelo). Se podría enriquecer el metamodelo para soportar varios cellrenders pero personalmente aquí aplicaría KISS.
  • Cada elemento del metamodelo sólo puede afectar a un atributo de la columna correspondiente. Esta puede que sea una limitación inadmisible, habrá que discutirlo. Puede que en este caso esté justificado enriquecer el metamodelo para hacerlo posible.
  • El store es una lista (ListStore) lo que implica que, en principio, no sería posible hacer vistas arbóreas. Yo creo que esto no es una limitación perjudicial en lo referente al store.
  • Raramente será admisible cargar toda una jerarquía en el modelo. Yo creo que sería más adecuada una solución similar a la de nautilus: sólo se cargan los hijos cuando se expande el árbol. Para lograr eso podríamos crear un nuevo inspector para ese directorio y combinar los nuevos objetos en el store existente. Aquí hay varias alternativas de implementación que habría que probar.
  • Al ser el store un array de objetos, las modificaciones en esos objetos no actualizan la vista. Esto sólo pasa con cambios asíncronos, por ejemplo, si cambia la fecha de un fichero cuando ya ha sido representado en la vista, ese cambio no se muestra. Se puede solucionar de una forma sencilla aunque no sé si muy elegante, forzando una modificación del store cuando sea necesaria. A la vez también es una ventaja, puesto que podemos modificar el modelo real sin que eso implique necesariamente que la vista deba recargarse.
Secuencia de operaciones:

Lo que voy a describir a continuación es un posible método para instanciación de inspectores y vistas. Una parte de esto es lo que pretende ser el ejemplo mvc.py.
  1. Al arrancar TP se registran en una 'factoría abstracta' todos los inspectors y vistas disponibles.
  2. El 'manager' recibe una petición para gestionar un uri.
  3. El 'manager' pide a la factoría un inspector que pueda manejar esa uri (puede haber varios). Se instancia el inspector pasándole una referencia al manager.
  4. El inspector crea un modelo básico, No hace falta calcular todos los datos hasta que sean necesarios (los pida la vista). Es decir, puede ser un modelo creado bajo demanda.
  5. El 'manager' pide a la factoría una vista que pueda representar ese inspector (puede haber varios). Se instancia la vista pasándole una referencia al inspector.
  6. La 'vista' se configura utilizando el metamodelo del inspector que se le pasa.
  7. El 'manager' pide a la vista el 'gui' y lo incrusta en la UI dónde corresponda.
Como ya he dicho, el ejemplo del repo no tiene factoría ni manager (aún) pero creo que sirve para hacerse una idea.

Saludos, y espero comentarios.

13 comments:

Oscar Aceña said...

Mmmm, como se parece esto a un programita que yo me se... :-P

David said...

ya te lo dije..., Pero yo esperaba encontrar comentarios más jugosos.

Unknown said...

En mi opinión, es indispensable la vista arbórea.

Sin embargo, he comprobado en mis propias carnes que la diferencia entre un modelo "lineal" y uno "arbóreo" en cuanto a complejidad es realmente abismal.

Por eso me parece muy bien comenzar por una lista, que tiempo tendremos de complicarnos la vida.

Tengo que releerme todo el artículo con el código y tiempo delante, ya que sólo le he echado un ojo.

David said...

Como era de esperar, lo del metamodelo ya se le había ocurrido a alguien antes... :-(

http://unpythonic.blogspot.com/2006/11/pygtk-lists-made-easy-with-kiwi.html

David said...

Otro enlace interesante que trata sobre GVFS, el substituto de gnome-vfs y que como podéis ver y como era obvio tiene grandes similitudes con la problemática de TP, porque al fin y al cabo nosotros queremos el VFS universal

David said...

Más sobre GVFS:
GVFS Plans

Oscar Aceña said...

La verdad es que Gnome VFS o GVFS son cosas que nos pueden ser útiles, pero no queremos suplantarlas, ¿verdad? Los servicios que provees ayudan a la tarea del TP, pero, básicamente, TP trabaja a un nivel más alto, más relacionado con las capas de presentación/interactuación en HIG.

luego mas...

David said...

No, claro que no queremos suplantar a VFS, pero evidentemente nos da la posibilidad de implementar un montón de inspectores del tirón.

Pero por lo que yo ponía esos links es por las ideas que hay en el diseño del API de VFS y lo que se está discutiendo en GVFS.

Mientras gnome-vfs estaba hecho a imagen y semejanza de las llamadas POSIX, en GVFS están tratando de hacer un API "document-centric" y si te fijas en las primitivas que están barajando, se parecen muchísimo a los que hablamos en la reunión y que Miguel resumió en un post anterior.

Las cuestiones son:
¿Vale la pena aprender de los fallos que los de gnome cometieron al diseñar el API de VFS, según ellos mismos?
¿Un API POSIX como el que estamos pariendo nosotros es lo más adecuado para manejar cosas que NO son ficheros?
¿No vamos a tener los mismos problemas que gnome? Sobre todo teniendo en cuenta que ellos tratan únicamente con ficheros y nosotros somos más ambiciosos.

Oscar Aceña said...

Aprender de los errores de otros (si es posible) vale la pena siempre, el problema que surge se contesta con la segunda pregunta. Cierto, nosotros vamos a usar ficheros, pero sobre todo, otras cosas que no son ficheros (cosas muuy distintas de hecho). Entonces, tendremos los problemas de gnome cuando nos enfrentemos a sistemas de archivos (et al). Pero quizá una api POSIX (completamente) no encaje en nuestra filosofía, por lo anteriormente dicho.

No sé, Miguel, ¿tu que opinas?

Unknown said...

Ahora no tengo tiempo de leerme las cosas con detenimiento, pero por lo que he podido ojear, GVFS llega a la conclusión de que lo bueno es utilizar algo similar a lo que nosotros pretendíamos desde un principio, es decir, desde el punto de vista del usuario (leer/copiar documentos, ...), de una forma abstracta.

Evidentemente, lo bueno es aprender de los demás.

Nuestro curro se basa en cosas que no son ficheros, es decir, en folders, containers o como queramos llamarlos. El tratamiento de las hojas o leaves debería ser, en principio, miserable, reduciéndose a saber qué programa es capaz de trabajar con ellas y proporcionándoles el fichero de la mejor manera posible (incluso bajándoselo a un temporal si no hubiera otro remedio).

Mi opinión es que, después de ser capaces de trabajar con folders, es posible que tengamos un inspector de leaves que nos permita integrar dentro de la ventana una vista de un nodo.

A. Martil said...
This comment has been removed by a blog administrator.
Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...

www.blogger.com is very informative. The article is very professionally written. I enjoy reading www.blogger.com every day.
fast loan
faxless payday loans