[Tutor] Getting rid of global variables, reprise

Scot Stevenson scot@possum.in-berlin.de
Sun, 12 May 2002 02:52:25 +0200


Hi there, 

A while ago I had posted a question here about a Tkinter version of a 
program that I was attempting to write that lets you take mail out of a 
mailbox, modify it in various ways, and save it to a file. I had already 
written a text-only version with lots of global variables, and the idea 
was to get rid of those while getting more Tkinter time unter my belt.

Last mail, I was having some problems with the concept of how to proceed, 
which led to a rather vague question, that some of you still valiantly 
tried to answer - thank you! Having figured out what my problem was, maybe 
the solution can be helpful to other people learning to program:

Basically, I was still too stuck in a non-object mode of looking at 
programs. More specifically, I was having trouble with the concept of the 
constructor (or whatever you formally call the def __init__(self): part) 
creating a full fledged object that contains the code. I was thinking in 
terms of code /here/ and data /here/, instead of realizing that when you 
create an object, it contains not only the data but also the program logic 
to play around with that data. The moment when I realized how much fun 
this object stuff came when I wrote "return self" for the first time =8).

More specifically, I ended up with three classes. One is the GUI object 
that builds the Tkinter interface in the constructor, has an instance 
created with the usual "if __name__ == "__main__": trick, and lets you 
load a mailbox file. When you read one mail out of this file, it creates 
an instance of the second class, a single message. The methods in the GUI 
object do little more than forward the method to the equivalent method in 
the mailbox file; the idea here is to keep the logic and the GUI separate 
so that I can do a Qt version in a year or two...

The third class is a container for the mailbox which receives the file 
name that the user picked, and makes sure that there is a "next" method 
that returns a single mail. The idea here is to hide different kinds of 
mailboxes behind one interface, even tho at the moment the program can 
only handle Unix type mailboxes (but I'm getting so fed up with sendmail I 
I swear I'm going to look into qmail). 

The solution to the global variables, of course, was to use instance 
variables like "self.msg" and to pass everything else with the method 
call. I still have to think twice about when to use "self.msg" and when 
just "msg", especially with Tkinter stuff. However: I can proudly say that 
I didn't use /one/ global variable this time, just like I set out to do - 
Ha! Python satisfies another ego!

What I also learned (apart from lots of Tkinter) was what Paul Sidorsky 
had predicted:

> The big problem with manager classes is that to use them you end up
> jumping through many hoops in order to do a very simple task.  It can
> lead to a kind of "OO-spaghetti code" that makes your program really
> hard to understand.

The program is rather longer than I had expected - 700-some lines, 
counting comments and blanks - and following the logic from the GUI class 
to the mailbox class to a single message and back took some getting use 
to. 

If anybody is interested in the code, I can gladly mail or post it (after 
cleaning it up a bit more). Thanks again to everybody who tried to answer 
my question, even though in retrospect I didn't understand enough of what 
my problems was to even formulate it correctly. You helped me get on the 
right track. 

Y, Scot