« Code Rot | Introduction » |
Global variables have a way of becoming a binding element that tightly couples modules. Certain desired behaviors may only occur because of side-effects created when the value of the variable is changed. Conversely, undesired features seem to intermittently appear in ways that cannot reliably be reproduced. As more global variables that are added to the source code base, the system seems to become more unstable. At this point, removing or altering set of global variables in the system becomes a monumental risk, rather than a safe and simple task.
It is not realistic to simply prohibit the use of global variables. There is a reason that global variables still exist in programming languages, they serve a purpose. Just like every other feature that a language provides, it is important to know how and when to use the feature appropriately. Global variables are no exception to this rule. They can be used safely and effectively with a few practices.
Although the majority of the code examples on this site are in C/C++, the concepts and principles can be applied to any language. The most important thing to remember when adding global data, is to control access to the data. This rule applies regardless of whether you intend the data to be private to the current compilation unit, or truly global to the entire program. The most reliable way to accomplish this, is to only give access to the data through a function call. Controlling access with a function provides a control point to manage change in your application. This keeps your application flexible and able to adapt with change rather than break and have to be reassembled.
C++
size_t g_count = 0; | |
size_t GetGlobalCount() | |
{ | |
return g_count; | |
} |
The code above is fine, except access to the global variable is still not protected. There are three ways to protect access to the data at a global level without using classes.
[adsense:]1) The static
qualifier
Adding the static qualifier to a global variable will tell the compiler to only provide access to this variable from the current compilation unit. This method works in both C and C++:
C++
static size_t g_count = 0; |
Be aware that a problem can arise with this method if two different files both declare static variables with the same name. The linker will complain about multiply defined symbols.
2) Use a namespace
This is the recommended method to limit the scope of access to global variables in C++. The unnamed namespace places the global variable in a scope block that is only accessible to the current file. Therefore, even if multiple files declared the same global variable and placed them in unnamed namespaces, the data would be viewed as a multiple variables to the linker:
C++
namespace // unnamed | |
{ | |
size_t g_count = 0; | |
} |
3) Use a static
variable within a function
This method has the advantage that the global variable is not accessible by methods inside the same compilation unit as well as other compilation units. The drawback is that a reference or pointer to the static function variable to be useful or input parameters to the function dictate how the value is manipulated.
C++
|
||||||||||||||||
Or | ||||||||||||||||
C++
|
Conclusion
Global data is considered by many to be evil. Often times it is necessary to have some sort of globally accessible data. Regardless, if access to the global data is properly controlled, global data can continue to be an asset rather than a liability. The key concept, which is the ability to adapt, has been given to the global variables. Access to the data is controlled completely by you. Therefore if a change needs to occur, you still have the flexibility to make your change without this becoming an engineering nightmare.
Recent Comments