code structure - suggestions? (classes for gui, data, calculations...)

Hi all,
first, I’d like to apologize for a kind of delayed cross-posting; after sending this post to the general python-list I realized, that this problem probably is rather gui-related; i.e. wxPython in my case.

I’d like to ask for suggestions regarding the appropriate structure of the code of my app. It is a gui program (wxPython; wx.aui) displaying several texts simultaneously. The user interface consists of multiple text widgets and control panels for selecting the text parts and synchronising.
Basically the program reads several text files, analyses them, displays them in the text controls and keeps track of some aditional indexing information (used for synchronising the text with each other etc).

What would be an usual way of structuring the code? I tried to separate distinct tasks to classes, but I am not sure, if this is the right way:
Currently I have a TextDB class containing the functions to parse the source text, then it stores the resulting fulltext and the indexing data; it also contains lookup methods for the text properties and also a display method (expecting a gui widget to write into). There is one instance of this class associated with each text.
Further there is an instance of a gui class (subclassing the wx.Panel - TextCtrl and some basic controls) for each text; besides this there are also panels with specific settings/selections of the individual texts. All this is managed in a frame using wx.aui.AuiManager (the panes can be moved or hidden, but in general, there might be over a dozen of panels used simultaneously on the screen).

Now, what would be a standard approach to let the single instances comunicate with each other? Is it usual, that the “data” instances are created by the gui instances (or the main program class)? Or would it be better to create an extra “dispatcher” class communicating with the others?
(in this app e.g. the user can select some text-property in the control panel, this value is then checked in the respective TextDB instance; finally the matching text part is shown in the text widget.)
Unfortunately, I couldn’t find many relevant code examples or general informations; actualy many tutorial etc. gui programs often have rather few classes, sometimes the only one.

Any suggestions, or references to some examples, concepts … are much appreciated;
thanks in advance;
Vlasta

I posted a similar question before beginning my current project. Someone (forgot who, sorry I didn’t give credit) wisely suggested following the Model/View/Controller pattern, which I did, and I’m pretty pleased with how things worked out.

I created three subdirectories under my main program directory which I called VIEW, MDL, and CTRL. In each of these, I put a init.py file which instantiated a Viewer, Model, and Controller instance, respectively. From there, I put all GUI calls in my VIEW.Viewer object, all event handlers in my CTRL.Controller object, and all my application-specific stuff under MDL.Model. All coding in VIEW and CTRL presume they will run in the main thread only* and all code in MDL must be kept threadsafe. If a callback function has to be passed to a member in MDL, I alway refer to a CTRL.Controller.TS_XXX function which ONLY launches a wx.CallAfter to return to the main thread.

I had a few things that didn’t fit the model precisely. I put some items (such as my wx.App) in the top-level directory since they didn’t seem to go well anywhere else. Also, I had some low-level handlers which were basically self-contained, so I left them in the window class that they belonged to, but put a lot of comments around them to explain why I had deviated from the MVC model.

I will admit that following this model created a few extra levels of calls for me. For instance, when the controller wants to call a method belonging to an object in the viewer, it would instead call a function in the viewer and that function was basically just a call to the specific object’s method. As a hand-optimizer, this reallly grated on me, but it has already saved me a few times, so I grin and bear it.

I don’t know that I followed the pattern well. This was my first MVC attempt, so I may have botched it completely, but it’s working well for me and I’m pleased with how smoothly it’s gone.

Since the details are pretty OT, feel free to e-mail me directly if you have any specific questions for how I did my layout. I will definitely follow this pattern again next time unless someone else has a suggestion of how I should refine this. Is this how you guys do your programs as well? I’d love to get other tips.

Gre7g

···

On 5/16/08, Vlastimil Brom vlastimil.brom@gmail.com wrote:

What would be an usual way of structuring the code? I tried to separate distinct tasks to classes, but I am not sure, if this is the right way:

Hi Gre7g, thanks for your tips and suggestions!
I’ll try to apply them in the further developing; in some aspects I have a similar structure, althought I haven’t separated the code in directories yet, as my program is quite small for now.

Similarly, I also have some parts, which don’t follow this strict separation…
I also noticed slightly more complicated calls and lookups between the classes, but probably it isn’t a big deal.

Thanks again for your help,
Vlasta

···

2008/5/16, Gre7g Luterman gre7g.luterman@gmail.com:

On 5/16/08, Vlastimil Brom vlastimil.brom@gmail.com wrote:

What would be an usual way of structuring the code? I tried to separate distinct tasks to classes, but I am not sure, if this is the right way:

I posted a similar question before beginning my current project. Someone (forgot who, sorry I didn’t give credit) wisely suggested following the Model/View/Controller pattern, which I did, and I’m pretty pleased with how things worked out.

I created three subdirectories under my main program directory which I called VIEW, MDL, and CTRL. In each of these, I put a init.py file which instantiated a Viewer, Model, and Controller instance, respectively. From there, I put all GUI calls in my VIEW.Viewer object, all event handlers in my CTRL.Controller object, and all my application-specific stuff under MDL.Model. All coding in VIEW and CTRL presume they will run in the main thread only* and all code in MDL must be kept threadsafe. If a callback function has to be passed to a member in MDL, I alway refer to a CTRL.Controller.TS_XXX function which ONLY launches a wx.CallAfter to return to the main thread.

I had a few things that didn’t fit the model precisely. I put some items (such as my wx.App) in the top-level directory since they didn’t seem to go well anywhere else. Also, I had some low-level handlers which were basically self-contained, so I left them in the window class that they belonged to, but put a lot of comments around them to explain why I had deviated from the MVC model.

I will admit that following this model created a few extra levels of calls for me. For instance, when the controller wants to call a method belonging to an object in the viewer, it would instead call a function in the viewer and that function was basically just a call to the specific object’s method. As a hand-optimizer, this reallly grated on me, but it has already saved me a few times, so I grin and bear it.

I don’t know that I followed the pattern well. This was my first MVC attempt, so I may have botched it completely, but it’s working well for me and I’m pleased with how smoothly it’s gone.

Since the details are pretty OT, feel free to e-mail me directly if you have any specific questions for how I did my layout. I will definitely follow this pattern again next time unless someone else has a suggestion of how I should refine this. Is this how you guys do your programs as well? I’d love to get other tips.

Gre7g


wxpython-users mailing list
wxpython-users@lists.wxwidgets.org

http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

Hi Kurt,

You don’t need to put that in the brains of the managers but in the brain of the boss.
If the managers don’t manage the project as good as they should than THEY should be changed NOT the programmers.

In my view, managers have 2 specific duties:

  1. directing the manufacturing process
  2. training or “tuning” the “managed” people for better performance.

The first part requires the manager to create and delegate atomic, specific tasks. They should decide what should be built and in what order.
The second part requires non-intrusive monitoring of the people and adjustment of their behavior by specific rewards and specific, objective negative feedback.

Barking at people and requesting “faster” output is not managing.
“Avoiding costs” requires better code NOT faster code.
Better code requires an environment that fosters creativity, requires a properly rested mind that can be output simpler and more efficient solutions.
Requires peace NOT haste.

Unfortunately, not all manager and firm bosses are able to see events evolution and default to a barbaric yoke and whip attitude and then remain shocked when they realize that money (which they use as motivation) is completely incapable of keeping their best programmers on board.

:slight_smile:

Peter

···

On Sat, May 17, 2008 at 12:28 PM, Kurt Mueller mu@problemlos.ch wrote:

Peter,

Am 17.05.2008 um 08:14 schrieb Peter Damoc:

My advice is to isolate the code AS MUCH AS POSSIBLE.

[…]

“Victory attained by violence is tantamount to a defeat, for it is momentary.”

“I object to violence because when it appears to do good, the good is only temporary; the evil it does is permanent.”

both by Skinny G. :wink:

And now remember and say if as a mantra through out your coding:

“Haste is a form of violence.”

First:

I second all of that.

(I am 60 years old and make programs for over 35 years now)

Second: (maybe with a small amount of exaggeration)

How do you put that into the brains of the managers?

A typical manager can only think in terms of (avoiding) costs.

(“Avoiding costs” only besides their own salary of course.)

So they urge the programmers to haste in software projects.

According to the quotes of Skinny G.

→ managers are violent,

→ managers are a source of evil,

isn’t it?

Third:

The lesser the influence of typical managers,

the better the software,

isn’t it?

Grüessli

Kurt Müller, mu@problemlos.ch


wxpython-users mailing list

wxpython-users@lists.wxwidgets.org

http://lists.wxwidgets.org/mailman/listinfo/wxpython-users


There is NO FATE, we are the creators.

Hi, thanks for the recommendations; with the given categorisation of the longer-time programming tasks the advantages of isolation become obvious.
However, how is this being achieved? I can think of functions, classes, modules or packages, which all seem to do roughly this (at various levels); are there maybe some general hints as when to choose which one?

Also, if these code segments are represented by classes, whose instances need to communicate with each other (directly or indirectly), what is an standard approach for doing this? (only creating these instances in the same space or rather something more sofisticated?)

thanks in advance,
Vlasta

···

2008/5/17, Peter Damoc pdamoc@gmail.com:

My advice is to isolate the code AS MUCH AS POSSIBLE.

Think about this: All the coding you will do will falls into 3 major categories:

  1. BUILD (new stuff)

  2. ADAPT (existing stuff that just need some specific functionality)

  3. COMBINE (glue glue glue)

Try to reduce the COMBINE layer to something very very simple. In this layer you will get most of your problems.
[…]
Remember, isolation, isolation, isolation. Isolation fosters simplicity and this is something that is not at all simple. It takes discipline and commitment.

[…]

It depends.
If you make a 100 SLOC software there will be classes and functions,
but for a 100'000 SLOC software there will be more like
multiple programs, different hosts, different types of communication, ...
SLOC="Standard Lines Of Code"

But anyway:
Software is made for "DATA-PROCESSING".
So after you have understood what the software should do
and became familiar with the "unchangeables" (maybe program-language, OS, HW, ...)

1. Think (not code) about DATA:
    what DATA is to be processed/stored
    structure the DATA
    isolate DATA that belongs together.
    think again about the DATA

2. Think (not code) about PROCESSING:
    what algorithms, ...
    can I adapt, reuse or at least learn from existing stuff.
    structure the PROCESSING tasks
    isolate different processing tasks.

3. Think about DATA and PROCESSING interaction:
    Is the DATA-structure suitable for the algorithms.
    How to access/modify/store the DATA (persistent/volatile/fast-access/backup/...)
    Restart @1. until ???

4. Think about the exterior-view of your software.
    CLI (Command-line-interface)
    GUI (Graphical-user-interface)
    Functions/Libraries
    Command-strings on TCP-ports, bus-adress, ...
    Sensors, Actors, Systems, ...
    Restart @1. until ???

5. Define appropriate platform/tools if not in the "unchangeables"

In every step try to isolate components in DATA, PROCESSING and external-view.
Make small and clearly defined, but extensible interfaces between the components.
Think about how you can test each component before and after implementing it.
This is also crucial if you have a group of programmers. Each can make his/her
components without too much communication and dependence to other programmers.
How could a component be made reusable?

Make fine RAVIOLI-code and no SPAGHETTI- or LASAGNA-code:

You may have heard of SPAGHETTI-code.
It is a complicated, difficult-to-understand,
and impossible-to-maintain software.
- SPAGHETTI-code has NO structure and NO isolation.

LASAGNA-code is simple, understandable an has a layered structure.
LASAGNA-code is structured, but monolithic and so not easy to maintain.
An attempt to change one layer, while conceptually simple, is often
difficult in actual practice.
- LASAGNA-code has structure but NO isolation.

In RAVIOLI-code, each of the components is a component
containing some contribution to the program.
Any component can be modified or replaced without
significantly affecting other components.
Components are small and are loosely coupled (Sauce/Glue).
- RAVIOLI-code has structure and has isolation.

Grüessli

···

Am 17.05.2008 um 21:29 schrieb Vlastimil Brom:

However, how is this being achieved? I can think of functions, classes, modules or packages, which all seem to do roughly this (at various levels); are there maybe some general hints as when to choose which one?

--
Kurt Müller, mu@problemlos.ch

To split the code, write the screenplay of the program. Who is doing what with what. And find out the main actors, the main props, etc.

Most of the time you will have a Sender, a Receiver, a Message and maybe some kind of MessageTranslator. Each of these 4 players should be isolated. It is ok for them to start up in one file, but if they grow too big and interact with too many other players, give them their own home. If they can form a “syndicate”… give them their own namespace. i.e. you can delegate the translators in their own namespace.

Look for separation anxiety. If you find separation anxiety in a piece of code, refactor it.
This is easily detected by asking the question: What if this
piece of code would be in another [part of the file | file | package |
folder | whatever]?

If you hear the code screaming “Oh NOOOO!”… you should refactor.
This is the Ravioli way. :slight_smile:

Peter.

···

On Sat, May 17, 2008 at 10:29 PM, Vlastimil Brom vlastimil.brom@gmail.com wrote:

2008/5/17, Peter Damoc pdamoc@gmail.com:

My advice is to isolate the code AS MUCH AS POSSIBLE.

Think about this: All the coding you will do will falls into 3 major categories:

  1. BUILD (new stuff)

  2. ADAPT (existing stuff that just need some specific functionality)

  3. COMBINE (glue glue glue)

Try to reduce the COMBINE layer to something very very simple. In this layer you will get most of your problems.

[…]

Remember, isolation, isolation, isolation. Isolation fosters simplicity and this is something that is not at all simple. It takes discipline and commitment.

[…]

Hi, thanks for the recommendations; with the given categorisation of the longer-time programming tasks the advantages of isolation become obvious.
However, how is this being achieved? I can think of functions, classes, modules or packages, which all seem to do roughly this (at various levels); are there maybe some general hints as when to choose which one?

Also, if these code segments are represented by classes, whose instances need to communicate with each other (directly or indirectly), what is an standard approach for doing this? (only creating these instances in the same space or rather something more sofisticated?)

thanks in advance,
Vlasta


wxpython-users mailing list

wxpython-users@lists.wxwidgets.org

http://lists.wxwidgets.org/mailman/listinfo/wxpython-users


There is NO FATE, we are the creators.

Vlastimil Brom wrote:

Hi all,
first, I'd like to apologize for a kind of delayed cross-posting; after sending this post to the general python-list I realized, that this problem probably is rather gui-related; i.e. wxPython in my case.

I'd like to ask for suggestions regarding the appropriate structure of the code of my app. It is a gui program (wxPython; wx.aui) displaying several texts simultaneously. The user interface consists of multiple text widgets and control panels for selecting the text parts and synchronising.
Basically the program reads several text files, analyses them, displays them in the text controls and keeps track of some aditional indexing information (used for synchronising the text with each other etc).

What would be an usual way of structuring the code? I tried to separate distinct tasks to classes, but I am not sure, if this is the right way:
Currently I have a TextDB class containing the functions to parse the source text, then it stores the resulting fulltext and the indexing data; it also contains lookup methods for the text properties and also a display method (expecting a gui widget to write into). There is one instance of this class associated with each text.
Further there is an instance of a gui class (subclassing the wx.Panel - TextCtrl and some basic controls) for each text; besides this there are also panels with specific settings/selections of the individual texts. All this is managed in a frame using wx.aui.AuiManager (the panes can be moved or hidden, but in general, there might be over a dozen of panels used simultaneously on the screen).

Now, what would be a standard approach to let the single instances comunicate with each other? Is it usual, that the "data" instances are created by the gui instances (or the main program class)? Or would it be better to create an extra "dispatcher" class communicating with the others?
(in this app e.g. the user can select some text-property in the control panel, this value is then checked in the respective TextDB instance; finally the matching text part is shown in the text widget.)
Unfortunately, I couldn't find many relevant code examples or general informations; actualy many tutorial etc. gui programs often have rather few classes, sometimes the only one.

Any suggestions, or references to some examples, concepts ... are much appreciated;
thanks in advance;
      Vlasta

Vlasta,

I try to separate my logic code from the GUI as much as possible. The MVC model is definitely one of the best ways to go, although I doubt I follow it too closely. So far, most of my projects are very small, so I just put logic code into what amounts to a logic module or modules. Then I just import the functions to whichever GUI file needs access to whichever function.

This has helped a lot in connecting to databases and manipulating them as well as for file access and parsing.

The more decoupling between the GUI and the logic, the better off you are. It makes swapping in new algorithms that much easier and debugging also becomes much easier as you can run the logic code independently from the GUI.

Mike

Hi Mike and Igor;
Thanks for further hints and the reference to the Martin Fowler’s blog.
I took me some time to determine the category of the single tasks in my script (and there still remains a few uncertain “grey areas”), but I am starting to see the differences as well as the advantages of the isolation of the single functionality.

best regards,
Vlasta

Peter Damoc wrote:

To split the code, write the screenplay of the program. Who is doing what with what. And find out the main actors, the main props, etc.

Most of the time you will have a Sender, a Receiver, a Message and maybe some kind of MessageTranslator. Each of these 4 players should be isolated. It is ok for them to start up in one file, but if they grow too big and interact with too many other players, give them their own home. If they can form a "syndicate"... give them their own namespace. i.e. you can delegate the translators in their own namespace.

Look for separation anxiety. If you find separation anxiety in a piece of code, refactor it.
This is easily detected by asking the question: What if this piece of code would be in another [part of the file | file | package | folder | whatever]?

If you hear the code screaming "Oh NOOOO!".... you should refactor.
This is the Ravioli way. :slight_smile:

Nice exposition. It's also very similar to Martin Fowler and Kent Beck's approach in the book "Refactoring: Improving the Design of Existing Code", but instead of "screaming code", they talk about "code smells".

One other MVC bit: I like to have "active" buttons on my forms, in the sense that each one is only enabled when it makes sense for the user to push it. (E.g., a Save button should be disabled until the user makes a change worth saving.) Among other things, this avoids the need to write checking code in the button handler to pop up error messages when the button is pressed under the wrong circumstances.

The problem I've run into with this is the need to check all the button states after each "significant" change to the form. The solution I came up with was to incorporate the buttons into the MVC structure. In effect, a button is a view on a Boolean method of a model; when the method returns true, the button is enabled. To do this requires some setup, registering each button as an observer of the model, and arranging for the model to notify its observers when any change to the form occurs. Once set up, though, it becomes easy to manage the states of any number of buttons. If anyone's interested, I'll write up a short description of my implementation of this.

···

--
Don Dwiggins
Advanced Publishing Technology

Christopher Barker wrote:

Don Dwiggins wrote:

One other MVC bit: I like to have "active" buttons on my forms, in the sense that each one is only enabled when it makes sense for the user to push it. (E.g., a Save button should be disabled until the user makes a change worth saving.)

One usability issue here: I now it drives me crazy when a control is grayed out, and I don't know why. It's not uncommon for me to think that I should be able to performance given operation, and I can't. It's usually because of some condition hasn't been met, but if I don't know what it is, all I'm left with is frustration.

If, on the other hand, I click the button, and get a dialog that says" "You can't do X until you've set a value for Y", I know what to do.

A fair criticism; to some extent it's a matter of style, but should be evaluated on a case-by-case basis, being sensitive to the user's experience. More generally, the design of the form (including the button labels) should always make it fairly clear under what circumstances each button should be used. It might even be worth adding a tooltip to the button saying something like "Don't press this until you've set a value for Y".

I've had a request for the little framework I use for this, so here it is: There's a ModelButton class that extends Button, and a mixin to use with the panel or other class that contains the buttons.

Then, in setting up each button, you call <panel>.setModelButton; in the handler for each event that might cause a significant change (one that might cause a button to change state), you call <panel>.notifyButtons(). (You can be pretty liberal in interpreting "significant" -- unless you have dozens of buttons with complex conditions, it won't cost much to process the notifications.)

Here's the code for the class and the mixin:

···

-----------------------------------------------------
"""
This is a subclass of wx.Button, designed to support enabling and
disabling of buttons in a container in an organized fashion, so that
event handlers and other state-changing methods don't have to
explicitly enable and disable buttons.

This class is designed to be an observer of a 'model' object, which
will notify the instance when its state has changed and the button
might need to be enabled or disabled. When appropriate, the model
should call the 'notify' method, which takes no parameters.

As part of hooking up the instance, two handlers are passed:
- An 'enable tester' that takes no parameters and returns
   the desired enable status of the button.
- A typical wx event handler, to be called on EVT_BUTTON.
"""
class ModelButton(wx.Button):
     def __init__(self):
         """ See the module description """
         pre = wx.PreButton()
         self.PostCreate(pre)

     def SetHandlers(self, enableTester, eventHandler):
         """ Set the handlers that we'll use """
         self._enableTester = enableTester
         self._eventHandler = eventHandler
         self.Bind(wx.EVT_BUTTON, eventHandler)

     def notify(self):
         """ It's time to decide our enabled status """
         self.Enable( self._enableTester() )

"""
Mixin for use with ModelButton. Inherit from this in the GUI class
that contains button instances; it allows the GUI class itself to
act as a model for the buttons. Call its "init" anytime during the
GUI class' init (but before using the other methods here).

For each ModelButton: define an enableTester and an eventHandler method,
then call self.setModelButton(button, enableTester, enableHandler) --
this will take care of binding the event handler to EVT_BUTTON as well
as registering the button as an observer.

When a state change occurs that might affect the enabled status of
some button, call self.notifyButtons().
"""
class ModelButtonsMixin(object):
     def __init__(self):
         """ Set up to act as a simple observable """
         self.observers =

     def setModelButton(self, button, enableTester, eventHandler):
         """ Set up the model button for operation with this class """
         button.SetHandlers(enableTester, eventHandler)
         self.observers.append(button)

     def notifyButtons(self):
         """ Send notification to all buttons of a state change """
         for button in self.observers:
             button.notify()