[Tutor] Global Variable Gotcha

Alan Gauld alan.gauld@blueyonder.co.uk
Fri Jun 27 15:51:02 2003


* Alan Gauld <alan.gauld@blueyonder.co.uk> [030624 23:24]:
>> All the opther options compromise the solution by building in 
>> undesirable dependencies(coupling).
> 
>  Ah! Here's that word again (coupling) :-) 
>
>  I'm sure it has a pythonic context... Seriously Alan,
>   can you point me to any docs, articles, examples 
>  on this subject (coupling/decoupling) as per python? 

The best description I ever saw was in the book "Using Structured 
Design" by Wayne Stephens (Stephens was one of the 3 guys from IBM
who invented structured design back in 1977).

However a Pythonic example might not be too hard, lets try:

#### Module 1 #####
# creates a global variable used by the function

globvar = 42
def f1()
   if globvar > 25: doSomethingBig()
   else: doSomethingSmall()

#### Module 2 #####
# uses the function in Mod 1

import module1

def f2()
   if module1.globvar == 42:
       doWierdThings()
   else:
       doOrdinaryThings

##### Module 3 #####
# wants to use f2 from mod 2

import module2

module2.f2()

##########################

Now lets consider some problems with the above approach.

1) Module 3 uses module 2 which in turn uses module 1
even though module 3 has no real need of module 1. 
We have required an extra module to be shipped with 
the program that is only needed to provide the 
global variable. Module 3 is "coupled" to module 1 
via module 2.

2) Suppose we actually want all three modules in 
the app, there is still a problem. Because f1() 
and f2() both use globvar to control their behaviour
we cannot safely call f1 and f2 independantly 
without a lot of housekeeping, like this:


oldval = module1.globvar
module1.globvar = theValueIwant

module2.f2()

module1.globvar = oldval

And every time in our module3 that we want to use either 
f1 or f2 we have to keep doing this setting of values and 
resetting to ensure the bahaviour is what we expect, 
just in case some other bit of code changed globvars 
value when we weren't looking.

And it gets worse! Consider that we now write a new function:

def f3()
   # do stuff
   module2.f2()
   # do stuff

NOw we have made f3 depend on module2,module1 and of 
course globvars setting. So now everytime we call any 
of the functions, including our new one we have to go 
through the set/reset protocol above!

Whats the solution? Just pass the test value in as 
an argument to each function. The functions can test 
the parameter and remain completely reusable:

# module1

globvar = 42

def f1(testval):
   if testval > 25:.....

# module 2

def f2(testval):
   if testval == 42: ...

#module3

import module2

module2.f2(theValueIWant)

If I really want to use the module 1 global its no big deal:

import module2,module1

module2.f2(module1.globvar)

But now I am in control, I use a global variable when I 
want and a local when I don't no hideen dependency.
   
Does that make sense?

Alan G
Author of the Learn to Program web tutor
http://www.freenetpages.co.uk/hp/alan.gauld