jueves, 12 de abril de 2007

MVC. Datos, lógica y vista.

Las vistas no tienen objetos, los objetos tienen forma de ser vistos.

Llevo un rato tratando de programar un manejador de contenido para páginas en la red. No es la primera vez que intento separar las tres famosas capas "datos, lógica y vista". Tradicionalmente, o al menos eso entendí en ingeniería de software, la capa de lógica se monta sobre la de los datos, y la vista sobre ésta. Sin embargo, surge de modo más natural escribir en los objetos cómo se ven estos, en lugar de tener una vista genérica que pueda mostrar a cualquier objeto y creo que la razón es sencilla: la forma en que se ven los objetos depende de sus propiedades. Entonces, una de dos, o no he logrado entender el concepto de las tres capas, o algo está chueco en su concepción. ¿Cómo puedo separar la presentación? Es claro que, el cómo se ve una cosa depende fundamentalmente de qué tipo de atributos tiene; si no conozco sus atributos y más aún, la semántica de esos atributos, es imposible que decida cómo debe verse.

En todo caso, se me ocurre que la idea de que las tres capas son independientes en, realidad, una falasia. A lo más, pensándolo como una pila, le concedo que la capa de datos sea independiente, ésta no requiere ser modificada si hay cambios en la lógica (control), ni en la vista. Pero a la inversa en ningún modo se cumple, por el contrario, si modifico el modelo, debo modificar la lógica que lo controla y la forma en que se ve. En el siguiente nivel: si modifico en control, lo más seguro es que tenga que modificar la vista. Por último, puedo modificar la vista (la puritita presentación gráfica, auditiva, etc.) sin tocar el control, ni el modelo.


Tal vez alguien más familiar con la técnica me diga ¡felicidades! ¡acabas de entender cómo se hace el hilo negro!

Sin embargo toda esta preocupación surge de un caso muy concreto: la intefaz de administración de django. Leyendo entre los correos de usuarios y desarrolladores, hay cierta molestia por el hecho de que el código que define la presentación en la administración está dentro de los modelos, siendo que estas dos capas no debieran trabar contacto.

El problema, como he llegado a verlo, es que los modelos (tablas en una base de datos) no representan más que una manera de hacer persistentes a los objetos, pero las bases de datos no pueden incluir toda la lógica de sus interacciones, ésta en realidad se mantiene en la capa siguiente (gracias al artículo de la Wikipedia). El problema es que ¿quién puede saber de antemano lo que será puesto en la capa lógica? Las implementaciones en las bases de datos limitan claramente qué puede ser almacenado ahí (tipos de datos, relaciones, etc.), pero en la lógica uno puede escribir prácticamente lo que sea. ¿Cómo podría entonces crearse una vista genérica, sin descender a los modelos?

Peor aún, y aquí viene mi muy particular dilema: ¿qué pasa cuando uno requiere hacer persistente cómo se ven los objetos? Es decir, que la forma en que los modelos son vistos en pantalla, también forma parte de los datos. ¿Cómo mantener aquí la consistencia sin que la capa lógica se convierta en una locura?

Por el momento intento que cada nuevo elemento contenga 3 cosas: su propia forma de ser persistido, su lógica y ... opciones para ser visto pero... éstas son las que ya me cuesta más trabajo definir en una manera consistente para todos los elementos (evitando abundar en los códigos especializados a cada caso), esto debe ser lo más general posible.

Me gustaría que los elementos que están contenidos dentro de otros simplemente extendiesen la presentación de sus contenedores, como funcionan los css y evitando persistir la información de la presentación en los mismos modelos (tablas) que el contenido en sí del objeto. De modo que, hasta donde voy ahora... mi modelo parece quedar igual que la administración de django: el objeto tiene la liga a "cómo se ve". ¿pero qué no es eso lo natural? ¿que las cosas tengan una apariencia y no la apariencia a las cosas?

miércoles, 4 de abril de 2007

Juegos II y pygtk

Se me ocurrió actualizar python, pasándome a la versión 2.5. Obvio, tuve que reinstalar todo lo que ya tenía :( django, psycopg, etc., etc. y pygame!

Siguiendo el procedimiento de Juegos I, ahora debí bajar Numeric, ojo, debe ser el viejito (el del 2005), Numpy no satisface los requerimientos.

También hubo que reinstalar OpenGL y pygtk. Este último fue el más problemático: hubo que instalar un nuevo pyobject, en Fedora 5, éste quedó en /usr/local/lib/python2.5/site-packages/gtk-2.0/gobject pero al hacerlo aún detectaba la versión anterior (Requested 'pygobject-2.0 >= 2.12.1' but version of PyGObject is 2.8.4). Tal parece que esto es porque no se instaló como biblioteca del sistema, de hecho, al instalar, aparece el siguiente mensaje:

/usr/bin/install -c -m 644 'pygobject.h' '/usr/local/include/pygtk-2.0/pygobject.h'
...
----------------------------------------------------------------------
Libraries have been installed in:
/usr/local/lib/python2.5/site-packages/gtk-2.0/gobject
...
----------------------------------------------------------------------

configure usa libtool, por lo que debe bastar con indicarle este directorio de alguna manera.

Entonces, antes de invocar .configure, intento exportar las variables:

# export PYGOBJECT_CFLAGS="-I/usr/local/include/pygtk-2.0/"
# export PYGOBJECT_LIBS=/usr/local/lib/python2.5/site-packages/gtk-2.0/gobject

Pero aún falta pycairo (intenté compilar sin él, pero sigue habiendo errores).
Con cairo es la misma historia: compilo e instalo cairo 1.4.2 y queda en:

----------------------------------------------------------------------
Libraries have been installed in:
/usr/local/lib
...
----------------------------------------------------------------------
/usr/bin/install -c -m 644 'cairo.h' '/usr/local/include/cairo/cairo.h'
...

Así que, para pycairo asigno:
# export CAIRO_CFLAGS="-I/usr/local/include/cairo"
# export CAIRO_LIBS="-I/usr/local/lib"

Y sigo las instrucciones de instalación... Dice que sí... ¡pero pygtk sigue sin funcionar! Y ya me cansé... me voy a dormir y ya mañana veo.