Organization of GUIs

Dietmar Schwertberger news at schwertberger.de
Thu Dec 3 13:08:39 EST 2009


Michael Mossey schrieb:
> View can be fine-grained. Often the View consists of a number of GUI
> objects. Some people write this in a democratic arrangement---they all
> talk to each other. This can make analyzing system behavior
> complicated. Hence my proposal for a hierarchy.
Yes, the democratic arrangement is only for very simple applications.

> Also, often different parts of the Model talk to different parts of
> the View. The question, then, is whether both the Model and View
> should be structured hierarchically so that all messages pass through
> a "master" or "root" object before going to the other Model/View, and
> messages within a Model or View should only move along the hierarchy.
> 
> In other words, you can easily make a complete mess of MVC.

I made good experiences with this setup in a very complex application
(inspired by MVC/MVP, but slightly different):
  - Model is completely independent of any GUI; in fact it's written
    to be used not only with a GUI, but also by scripts and an
    application server
  - Controller/Presenter holds the model instance and serves as
    message dispatcher; also it holds view-only data (e.g. cursor
    position, cell selections, file modified?)
  - Views/Controls
    - subscribe to the messages to update themselves
    - either modify data and send update message via the dispatcher
    - or tell Controller to modify the data, which then generates
      the update message

With this architecture, you have the choice whether to plug the
Views/Controls directly to the Controller/Presenter or organize
them hierarchically. I doubt that you'll have many hierarchy levels
between Presenter and Controls. Probably only one...

Examples for the messages:
  - "Changed", model
    (anything may have changed)
  - "AttributeChanged", attname, value
  - "DataChanged", index, new_value
  - "Saved", filename
  - "Modified", modified
  - "IndexChanged", new_index
  - "ViewChanged", view_names
    (I'm using a tabbed interface and some views react to messages
     only when they're active.)
  - "ConfigRead", key, value, persistent
Some messages are automatically issued by the Presenter in response
to other messages. E.g. for a "Saved" message, the Presenter
automatically generates a ("Modified",False) message afterwards.

In my case, the model is hierarchical and so I have "Changed" messages
for many different aspects / levels. The total number of message types
is around 60. I could live with much less, but the finer the messages,
the less performance overhead.

As there are messages related to the model (e.g. Changed) as well as
messages related to the views (e.g. IndexChanged) and to general
functionality (e.g. ConfigRead) it's very easy to couple all
controls and components via the Presenter.

The app is built with wxPython and includes a shell window which exposes
some objects including the app itself and the model.
In this shell you may manipulate the model interactively or by loading
a Python script. For the GUI to catch up you need to issue a "Changed" 
message afterwards.
It would be possible to follow e.g. the original MVP and do all
modifications (GUI and shell) via the Presenter to avoid the requirement
of issuing this message, but that would require wrapping of much
functionality and usage would be less elegant.

As the app, including all menu items, is available from the shell, this
can also be used for automatic testing.
E.g. shell input or script may look like that:
 >>> filename = "c:\\test.dat"
 >>> self.menu.file.open( filename=filename )
 >>> # or self.menu.file.open() to let the user select a file
 >>> # or model = ModelModule.open( filename )
 >>> if model.filename!=filename: raise ValueError, "test failed"
 >>> new_filename = "c:\\output.dat"
 >>> model.filename = new_filename
 >>> presenter.notify("AttributeChanged", "filename", new_filename)
 >>> # or presenter.set_filename( new_filename )
 >>> # or presenter() as shortcut for presenter.notify("Changed", model)
 >>> # or presenter.save( new_filename )

Also, it's possible to automatically test dialogs...


Regards,

Dietmar



More information about the Python-list mailing list