Globals

The problem with globals, and why you should use subroutines

When you’re writing something like a binary converter it isn’t too bad, but the code can start to get messy, with whole chunks of the program being in loops and things like that making tweaks and debugging more tricky.

When you start writing a program the size of connect 4 then code can easily become a complete mess, nested off the screen and complicated chunks of code sandwiched in the middle of nowhere and other things that make it very difficult to hold in your head and manage…….that is unless you’re using subroutines, preferably efficiently.

A program the size of connect 4 is a lot easier with subroutines. Have some code that prints the board nicely? Move it out into a subroutine and hide the subroutine out the way, suddenly print board isn’t complicated, it’s one line which you can put anywhere. Have some code to check if there’s a win on diagonals? Move it out into a subroutine and suddenly you have a command called hasWonOnDiagonals() – makes a connect 4 a lot easier if you have that sort of command at your disposal, and that’s what subroutines allow you to do.

So. Point 1. Use subroutines. They’re useful.

Next point is globals. Firstly, what are they?

When you run a subroutine it’s like….it’s like delegating a task to someone. Imagine you’ve got a big task to do. Or perhaps you’re part of the computer and you’ve got other parts of the computer that you can manage? Lets take the example of a big task, and you’ve got the entire class to help you if you need. If you plod through trying to do everything yourself, that’s how your early programs are – without procedures. Now think about having specialists. Example. You are running Santas grotto 😀 You need buy a present for sweet little Jimmy, wrap it and put it in the correct sack for sleigh delivery. Think about how many steps are actually involved in each of those steps. When using a subroutine, you use the procedure called SamWrapPresent to get Sam to wrap a present. It’s nice and easy to just say SamWrapPresent and then it gets done. Awesome.

Once you’ve told Sam how to wrap a present once, you only need to say SamWrapPresent and he’ll do it.

The important part is, you don’t care what Sam does provided the present is wrapped. How a subroutine does something doesn’t matter to the rest of the program.

Now, where is Sam going to be doing this wrapping?

With a subroutine you want to GIVE Sam a present and some wrapping paper, he goes off into his own area and RETURNS a wrapped present.

This is where globals can come in.

If instead of letting Sam work in his own area you’re getting him to use things in other peoples work areas, it could work, but you’re asking for trouble. If instead of giving him the wrapping paper you tell him where you store the wrapping paper then you run potential issues of someone putting a half eaten sandwich where the wrapping paper usually is, and Sam is now trying to wrap a present with a half eaten sandwich. Or Sam puts back his off-cuts into the wrapper paper store and other people try to use it and it makes a mess. That is what global variables are like. A potential to make a mess. It’s also less efficient to have people working on top of each other.

Lets take this back to programming.

If you have a variable called X in your program and you’re also using it in a subroutine, then if something alters it which you haven’t previously allowed for, terrible things could happen. Also, it’s bad memory management. Each subroutine should have its own variables and memory storage that doesn’t interfere with any other variables and will get wiped when it’s done.

If you think about a big computer game then the risks are magnified as are the memory benefits. You don’t have to store everything all the time.

So how do you get data into the program if its not allowed to access data from elsewhere in the program?

Arguments.

….no, that’s the answer, not just what I create. When you call a subroutine you give it arguments. For example, hasWonOnDiagonals(board, “R”). This will check the board “board” to see if “R” has won. You’re GIVING the subroutine two bits of information, board and “R”, then it can do whatever processing is required and RETURN an answer (yes or no in this case).

That is how you avoid using globals.

I’m not expecting you all to understand all of this e-mail. Some may get it all, some may get none of it, but keep it and revisit it after we’ve done procedures and spaghetti code and it should make some more sense.

The code to do this is:
def hasWonOnDiagonals(board, turn):
    # Here you can use the variables board and turn as if they contain what you want.
    # The return statement lets you get a result out of the program. It will end the subroutine and give the result.
    return True
# This is then calling that subroutine later in the program, lets say board is a variable we have, but we want turn to be R.
result = hasWonOnDiagonals(board, “R”)
# Result will now hold whatever the function has returned. Hopefully its done something sensible with them.


Working example:
def add(a, b):
    c = a + b
    return c

c = “hello”
x = add(4, 5)
print(x)
print(add(3,4))
y = 8
z = 6
w = add(y, z)
print(w)
print(c)

Question. What will the last line print?! Notice that c is in the subroutine as well as in the main program.
Various ways of calling a subroutine, each is GIVING an ARGUMENT and RETURNING a value. Not how we have only used the + in one place and used it everywhere else. Imagine that was a lot more complicated so didn’t want to copy it out 3 times. Look at the variable c. What happens if you’re using a variable c in your main program? You shouldn’t care what variables add is using – that would be using globals.

Adding two numbers is a fairly trivial example which is why I’ve used hasWonOnDiagonal, because that’s going to be a tricky bit of code containing loops and all sorts that you don’t want in the middle of a complicated program.

Leave a Reply

Your email address will not be published. Required fields are marked *