Version 13 of GUI separate from the backend code

Updated 2003-08-21 17:24:12

This issue is often a lot more complex than it sounds. Tips welcome and appreciated.

RS 2003-08-21: I often make it a rule to design an app in terms of a Tcl API that does not require Tk. All functionality is available over proc calls. In a second step I design a GUI and add visualisation of app objects and triggers - buttons or menu items that call one of the API commands; labels with textvariables that further control the APIs action. Examples: Chess in Tcl, TclMusic, tclchat.

DKF: This is an instance of the sort of Separation of Responsibilities stuff that you see a lot in (good) professional software.


Bryan Oakley: This topic interests me greatly. The way I solve this problem is to use what I call actions (and some day, I swear, I'll write up a paper on the subject). actions are, in effect, the public API of a program. I try to stick to the following rule of thumb: anything a user can do from the UI must be done via an action. Thus, my code tends to look like this:

    action define cut {} {<perform 'cut' functionality>}
    action define copy {} {<perform 'copy' functionality>}
    action define paste {} {<perform 'paste' functionality>}
    ...
    .menubar.editMenu add command cut [list action invoke cut]
    .popup add command cut [list action invoke cut]
    bind . <<Cut>> [list action invoke cut]
    button .toolbar.cutButton -command [list action invoke cut]
    ...

For the record, "action" is a command I wrote which is mostly just a glorified proc command, but has some extremely useful additional features.

The benefit is that, for one, it lets you implement several ways for the user to access a function without having to duplicate code. You can have a "cut" toolbar button, a "cut" item on the edit menu, a "cut" item on a popup menu, a "cut" keyboard accelerator, a "cut" function key, etc., all running the same code. Adding a new way to access the functionality becomes trivial. For example, when developing code I usually just start with a menubar and maybe a toolbar. After things are running I'll add accelerators, popup menus and the like, and that is all very simple.

Another benefit is that it becomes easy to drive the interface via a script (for testing, for example), or to rewrite all or part of the UI without having to rewrite any of the actual inner workings of the code. It's also possible to have a macro capability where you can string several actions together in a script, and also makes remote control of the app fairly trivial.


ulis, 2003-08-21: I do the things the other way of RS. I design the user interface and then add the actions needed (in the Bryan Oakley sense). Sometimes I need to slightly modify the UI during the second step.


Charlie What about the other way around? "actions" are defined as being 'things' that originate somewhere in the GUI (view) (a button is pressed), but sometimes 'things' originate from somewhere in the core (model,controller MVC). How is this supposed to be implemented in an efficient/consistent/clear way in Tcl. Or stated otherwise:

        View -> Model/Controller    is no problem (as described above), 
        Model/Controller -> View    ?

RS: see Model / View / Controller - easiest done with textvariables, or variable traces.

Charlie But this requires strong bindings (hard coded) between the Gui (view) and the Core (Model/Controller). How can one avoid this so that true reuse of gui code / core code can be the result?

RS: This is where the above-mentioned API comes in - provide "methods" for setting values or taking actions, and "callbacks" to fire when the model changed.


category concept