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]. [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 exit {} {exit 0} action define cut {} {} action define copy {} {} ... .menubar.editMenu add command cut [list action invoke cut] .popup add command cut [list action invoke cut] bind . <> [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. ----