2010-07-17 15 views
6

Im tratando de refactorizar mi solicitud (con más de 1000 líneas de código GUI) a un patrón de estilo MVC. El código lógico ya está separado de la GUI, por lo que no hay problema. Mi preocupación es la separación de la vista desde el controlador. Entiendo el principio básico de la MVC y this tutorial en el wiki wxpython ha sido muy servicial pero el ejemplo de código es un poco simplista y me deja con dudas cuando intento de aplicar el principio de mi propio proyecto, que es un poco más compleja.Re-factoring patrón MVC -Doubts en la separación de vista desde el controlador de

Un fragmento de la estructura ..

I tienen una MainWindow con un número de widgets incluyendo una (sección de pestañas) noteBook, el portátil tiene un número de pestañas una de las pestañas (que me llamo FilterTab) posee dos instancias de una clase (que yo llamo un FilterPanel) que es un panel con un cuadro de lista , tres botones, uno para borrar, uno para eliminar y uno para agregar elementos a/de la lista . Dependiendo de banderas pasaron a la clase en el caso de instancias botones añaden puede crear diferentes tipos de cuadros de diálogo, por ejemplo, un diálogo de entrada de texto o directoryPicker etc ..

Eso es sólo una parte de la interfaz gráfica de usuario que es bastante capas controladores de eventos -con enterrado en la clase FilterPanel.

Si tuviera que convertir esa parte a MVC tendría que vincular los eventos de botón para cada instancia de FilterPanel en mi controlador (en lugar de en la clase filterPanel) -en este caso hay dos (instancias de filterPanel)

por lo que tendría algo como esto para cada botón, (3 botones por filterPanel * número de instancias del panel), además de los manipuladores ..

self.mainWindow.filterTab.dirFilterPnl.Bind(wx.EVT_BUTTON, 
            self.onAdd_dirFilterPnl, 
          self.mainWindow.filterTab.dirFilterPnl.addBtn, 
          self.mainWindow.filterTab.dirFilterPnl.addBtn.GetId() 
            ) 

que añade una gran cantidad de código extra, (el doble de la cantidad de eventos manipuladores si tengo solamente dos casos filterPanel)

Así que me gustaría saber si estoy tomando el enfoque correcto?

Respuesta

9

Si tuviera que convertir esa parte de MVC tendría que obligar a los eventos de botón para cada instancia de la FilterPanel en mi controlador (en lugar de en la clase filterPanel )

¡No necesariamente! La filosofía y la práctica de MVC no implican que las "vistas" sean widgets elementales; su FilterPanel bien podría ser pensado/implementado como un widget "rico/compuesto" que generan sus propias, de mayor nivel "eventos" (dirigidas al controlador) y actualizar apropiadamente. Por lo tanto, ese widget compuesto puede tener controladores para "eventos" de bajo nivel y sintetizar eventos de mayor nivel a partir de ellos, enviándolos al controlador; el controlador no tiene que saber ni preocuparse por cada botón, etc., solo acerca de los eventos de mayor abstracción que recibe, como "el usuario quiere elegir un directorio para el propósito X" o "el usuario quiere ingresar el texto para el propósito Y" - y responda diciéndole a la vista qué hacer.

El punto clave es que la vista no toma decisiones "semánticas" en función de los eventos que maneja ni envía ningún comando al modelo: el controlador es el "intermediario" indispensable para todas esas interacciones.

Para una analogía, considere que la capa más baja de la GUI tiene eventos de muy bajo nivel como "botón izquierdo del mouse hacia abajo" y "botón izquierdo del mouse hacia arriba" - un "widget de botón" reacciona directamente al cambiar el apariencia del botón (una decisión "visual", no "estratégica") y, eventualmente, si y cuando sea apropiado, sintetizar un evento de abstracción más alta como "botón pulsador" (cuando un botón del mouse está seguido por un botón del mouse) sin movimientos intermedios del mouse invalidando la hipótesis de "hacer clic", por ejemplo). Este último se dirige a lo que sea que la capa superior necesite para "responder" a los clics del botón.

De manera similar, sus widgets ricos/compuestos pueden tomar tales eventos y sintetizar los de mayor abstracción para que el controlador reaccione. (El mismo evento abstracto se puede generar presionando un botón, una selección de menú, ciertas pulsaciones de teclas ... al controlador no le importan estas consideraciones "visuales" de capa inferior, ese es el trabajo de la vista/widget, y la vista/widget no codifica decisiones y acciones "estratégicas" para tales interacciones del usuario, ese es el trabajo del controlador).

La separación de preocupaciones ayuda con cuestiones tales como las pruebas y la flexibilidad de la aplicación; No es extraño que esas ventajas se compren al precio de tener más código con una alternativa en la que todo está codificado ... pero si elige MVC, significa que vale la pena pagar el precio.

wx puede no ser el marco ideal para implementar esto, pero usted puede subclase wx.Event - o usted podría utilizar un sistema de eventos por separado como pydispatcher para los eventos de mayor abstracción que fluyen entre subsistemas separados, con el fin de desacoplar el controlador de la elección específica del marco GUI. Normalmente uso Qt, cuyo modelo de señales/ranuras, IMNSHO, se extiende/escala mejor que los sistemas de eventos de los marcos de GUI típicos. Pero, esta es una opción diferente y un problema diferente.

+1

Excelente respuesta que ha corregido mi punto de vista que estaba obsesivamente obsesionado con la eliminación de todas las encuadernaciones de eventos de la vista, lo cual no solo es impráctico sino también imposible. He desarrollado widgets compuestos ricos antes, así que no hay problema (usando wx.NewEventType, wx.PyEventBinder, wx.PyCommandEvent para tomar eventos como usted sugirió), por qué no pensé en esto porque este problema fue probablemente debido nuevamente a la fijación mencionada. Gracias de nuevo por la esclarecedora respuesta – volting

+0

Sin embargo, una última duda (con suerte) con respecto al cuadro de lista, al agregar solo elementos únicos, ¿se consideraría una decisión semántica? – volting

+2

@volting, eres bienvenido!Mostrar cada elemento solo una vez en el cuadro de lista, tanto como (por ejemplo) si mostrar los elementos en el orden en que se agregaron o en algún orden ordenado, son cosas que normalmente clasificaría como decisiones visuales: no hay una decisión difícil y rápida. criterio, pero me parece que es esencialmente una decisión sobre "cómo mostrar" cosas al usuario, en lugar de "qué acciones semánticas realizar". –

1

wxPython tiene pubsub incluido, que sigue la metodología Publicar/Suscribir. Es similar a pydispatcher, aunque sus implementaciones son diferentes. El wiki wxPython tiene algunos ejemplos sobre cómo utilizar pubsub en su programa y también hay este sencillo tutorial sobre el tema:

http://www.blog.pythonlibrary.org/2010/06/27/wxpython-and-pubsub-a-simple-tutorial/

MVC en interfaces gráficas de usuario no es exactamente lo mismo que lo es en Django o TurboGears . Me parece que puedo poner la mayor parte de mi lógica en controladores y en mi "vista", simplemente me conecto al controlador. Algo como esto:

view.py

btn.Bind (wx.EVT_BUTTON, self.onButton)

def onButton (auto, evento): controller.someMethod (* args, ** kwargs)

Según el cálculo, puedo ejecutar un hilo desde mi controlador y publicar el resultado más tarde utilizando wx.CallAfter + pubsub.

+0

Ya estoy usando pubsub en mi proyecto, con un número de oyentes en mi GUI para mensajes enviados desde la lógica ... "Encuentro que puedo poner la mayor parte de mi lógica en controladores y en mi opinión" Seguro no estás atado a ningún patrón, tengo 1K líneas de GUI ... pero eso es doble. Me gustaría que mi proyecto sea flexible y fácil de ampliar, y al mismo tiempo aprender algo nuevo. Gracias – volting

Cuestiones relacionadas