Cleaning Up the Globe (als)

Let’s get one thing straight up front:  global variables are a bad idea.  Yes, there are some exceptions, but for the most part, they’re a bad idea.

There are lots of reasons why they’re a bad idea.  Here are just a few:

  • They promote side effects.  Globals can be changed anywhere in a program, so a change in one piece of code may have unintentional consequences to other code elsewhere in the application.   And it gets worse fast if you’re working with multithreaded applications.
  • They promote code coupling.  Globals can be referenced from multiple places in code, and code in one place can depend on actions taken against the variable in another place.  This effectively couples those pieces of code.
  •  They prevent testing.  Because they can’t be isolated, globals make it difficult to properly test code.
  • They reduce clarity.  Variables should typically be declared close to the point where they are used.  This makes them easier to see, read, and understand.  Globals can be declared in a different part of the module, or in a different module entirely.  This reduces clarity, making the application harder to follow and harder to maintain.

Of course you need variables to be able to do anything useful. And in some cases, you need a lot of them. And sometimes you need to have access to all those variables in more than one routine, or even more than one module. So what do you do?

You encapsulate!

Suppose you wanted to send a package to your friend to brighten her day. You decide that she needs a cheerful card, a jar of scented oil, a book, a candle, and two boxes of cookies. That’s a lot of things. Do you send each one of them to her separately? Well, you could, but it would make a lot more sense to put them all into a box and send them all at once. That’s all encapsulation is — stuffing all your variables into a box.

Suppose you need to deal with addresses. For the sake of argument, let’s say each address has a first and last name, two address lines, a city, state, zip or postal code, a phone number, and a country. That’s 9 variables. If you have to pass that to a dozen different routines, you might be tempted to just create 9 globals and stuff them full of data and let the parts of the program pick at them whenever they want. But that’s a really bad design decision.

Instead, how about encapsulating the data into a user-defined type?

VB6

Public Type Address
    firstName As String
    lastName As String
    address1 As String
    address2 As String
    city As String
    state As String
    zipcode As String
    phone As String
    country As String
End Type

C#

public struct Address
{
    String firstName;
    String lastName;
    String address1;
    String address2;
    String city;
    String state;
    String zipcode;
    String phone;
    String country;
}

PHP

class Address 
{
    var $firstName;
    var $lastName;
    var $address1;
    var $address2;
    var $city;
    var $state;
    var $zipcode;
    var $phone;
    var $country;
}

Python

class Address:
    def __init__(self):
        self.firstName = ""
        self.lastName = ""
        self.address1 = ""
        self.address2 = ""
        self.city = ""
        self.state = ""
        self.zipcode = ""
        self.phone = ""
        self.country = ""

This defines a new type of variable that you can use to pass all that information around. So instead of 9 variables, now you have one. It’s easy to access, easy to pass around to whatever functions may need it, easy to test, and easy to understand. For example:

VB6


Dim myaddress as Address

myaddress.firstName = "Fred"
myaddress.lastName = "Stoneflint"
' fill other fields and pass the whole address to a function, etc.
Call PrintMyAddress(myaddress)

C#

Address myaddress = new Address();

myaddress.firstName = "Fred"
myaddress.lastName = "Stoneflint"

// fill other fields and pass the whole address to a function, etc.
PrintMyAddress(myaddress);

PHP

$myaddress = new Address();

$myaddress->firstName = "Fred"
$myaddress->lastName = "Stoneflint"

// fill other fields and pass the whole address to a function, etc.
PrintMyAddress($myaddress);

Python

myaddress = Address();

my address.firstName = "Fred"
myaddress.lastName = "Stoneflint"

# fill other fields and pass the whole address to a function, etc.
PrintMyAddress(myaddress)

This makes it easy to pass your address data around in just a single variable. And because of that, you won’t need to have a global variable at all. That will improve the quality of your entire application.

But wait, you say — there are dozens of different functions that all need to operate on that address. Wouldn’t it be a lot easier to just have a global variable that all the functions can access?

No. It would not. You would save a few seconds typing the name of your address variable on a function call, but you would lose far more than that in lost maintainability and understandability in your application. If you really have that many functions that need access to your address data, maybe your application could benefit from some object orientation.

But that’s for another post.

This entry was posted in Fundamentals, Programming. Bookmark the permalink.

One Response to "Cleaning Up the Globe (als)"

Leave a Reply

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


*