[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