CleanCode logo
sitemap
SEARCH:
NAVIGATION: first page in sectionprevious pageup one levelnext pagefinal page in section

Guideline VR1: Global variable-less programming

Global variables were first, but certainly not best. On the one hand, global variables should almost never be used. On the other hand, global variables may be used constructively. But, of course, that depends on how you define "global variable". Global variables may be any or all of the following:

  1. Variables accessible without qualification anywhere in a program.
  2. Variables accessible with qualification anywhere in a program.
  3. Variables accessible anywhere within a namespace (package).
  4. Variables accessible anywhere within a file (module).
  5. Variables accessible within an outer block.

Let's consider each of these in turn. In JavaScript, all variables outside of a function are global by definition (1); we'll refer to these as Def. 1 globals. So once the statement shown below is executed:

	var myStuff = "xyz";

you may reference variable myStuff anywhere, be it inside a function, outside a function but contained in a JavaScript file included within an HTML file, or even outside any JavaScript file--in an HTML file directly. This last possibility is just about the only time I would ever even consider using a Def. 1 global, but only if it added to overall program clarity or encapsulation. Def. 1 globals are just too easy to break. Anyone, anywhere, anytime can change the contents of that variable. And sometimes even on purpose. That is to say, it is quite possible that another developer would add a new file or module that also uses a Def. 1 global that happens to have the same name... One or both uses of it are then corrupted.

Perl also let's you use Def. 1 globals--unless you include the use strict pragma in each of your files. Then you'll be required to use only Def. 2, 3, or 4 globals in place of the Def. 1 globals. And Java does not allow you to use Def. 1 global variables at all.

Def. 2 globals do not exist in JavaScript, but they do in both Java and Perl. Within any Java class you may define a variable myStuff as in:

	package com.cleancode.util;
	public class Utilities {
		public static String myStuff = "xyz";
		. . .
	}

The public keyword is an access specifier; its presence here makes this a Def. 2 global. Within the file you may refer to the myStuff without qualification, but outside generally you must qualify the variable with the package and class, that is as com.cleancode.util.Utilities.myStuff. (To be more manageable, you can use import com.cleancode.util; in your program's preamble, then the global may be referenced subsequently as just Utilities.myStyff.) Def. 2 globals are occasionally useful, but generally still frowned upon. The preferred way to have access to a package's variables is via getter and setter methods as shown in the example. This again touches upon data encapsulation; see TBD...

EXAMPLEJava
Instead of:
	package com.cleancode.util;
	public class Utilities {
		public static String myStuff = "xyz";
		. . .
	}
Use:
	package com.cleancode.util;
	public class Utilities {

		private static String myStuff = "xyz";

		public String getMyStuff () {
			return myStuff;
		}
		public String setMyStuff (String newValue) {
			myStuff = newValue;
		}
		. . .
	}

Referring back to the public access specifier on myStuff: if you omit that specifier then you are instead specifying package access, which is the default if you do not explicitly give any other access specifier. Package access makes a variable a Def. 3 global, as we've defined it. With package access, we are teetering on the fence of acceptable global usage. There are still good uses and bad uses, as with most things.

Let's back up briefly to examine Def. 2 globals in Perl. Just like Java, you must fully qualify a Def. 2 global in Perl to access it outside the defining module. With this definition:

	package Util::Entities;
		use strict;
		use vars qw($bar);
		$myStuff = "xyz";
		. . .

you can access the variable by writing $Util::Entitites::myStuff. And, also just like Java, you can use an effective shorthand by including the use vars qw($bar) pragma in your program's preamble. Then you may write just $myStuff to access the variable. But, again, that doesn't mean you should. We still recommend getter and setter methods, as discussed regarding Java. Finally, unlike Java, there are no access modifiers, hence there are no Def. 3 globals in Perl.

Defining globals in a file which may be used unrestricted within that file--Def. 4 globals--is a powerful tool for data encapsulation. A reader of your file will see the definitions, preferably commented, and will see how each is used. Keep in mind that you might intend to use Def. 4 globals, and even believe you are using Def.4 globals, but you might inadvertently be using a lesser type (Def. 1, 2, or 3) depending upon your use and upon the language. A trivial example would be in JavaScript. You create a variable in one file and you use it only in that file... but as indicated above, it is still a Def. 1 global because of language constraints!

The final type of globals is Def. 5 globals. These are available in differing flavors in Java, JavaScript, and Perl, and indeed, in any block-structured language. In the example below, we're declaring printName as a Def. 5 global; that is, it is global to the block defined by the for loop, and may be freely used inside that block. At the same time it is local to the if block in which it is defined. And it is undefined outside that block.

	if (newSpecies) {
		var printName = "[" + bird + "]";
		for (var count=0; count < totalTraits; count++) {
			if (badTrait(count)) {
				alert(printName + ": " + count);
			}
		}
	}

But JavaScript has another trap! The var keyword is optional when declaring variables. So if you do not use it, you're back to creating--or possibly corrupting--a Def. 1 global. Notice the second use of var in the above example, in the for statement; that is a case easily overlooked by careless programmers.

Perl has a similar trap to JavaScript in this respect, but you can fix it by always using the use strict pragma in your file's preamble. It is a voluntary fix, of course, so it is only as good as your consistency.

Java has Def. 5 globals as well, with even greater control. Java has the same notions of block as do Perl and JavaScript, but Java also let's you define nested classes. The class is the fundamental entity within a file; in fact, a file can only contain classes, everything else is defined inside classes. So Def. 4 globals technically only exist in Java if your file contains just one class. But a file may contain multiple classes or nested classes. Each of these can have Def. 5 globals within their scope.

Valid XHTML 1.0!Valid CSS!Get CleanCode at SourceForge.net. Fast, secure and Free Open Source software downloads
Copyright © 2001-2013 Michael Sorens • Contact usPrivacy Policy
Usage governed by Mozilla Public License 1.1 and CleanCode Courtesy License
CleanCode -- The Website for Clean DesignRevised 2013.06.30