UtterAccess HomeUtterAccess Wiki

Welcome Guest ( Log In | Register )

Custom Search
Edit Discussion
> Scope    
Scope

Scope and Lifetime of variables are core concepts in just about any programming language, and a key thing to learn for an aspiring programmer. While the concepts of scope and lifetime can be applied to other programming constructs besides variables, they are most commonly considered with variables and as such this article will focus primarily on their use with variables.

A variable's Scope refers to how much of the application can "see" the variable. When you have a variable defined in a procedure, can code that is not within that procedure make use of the variable? Can code from another module use the variable? What if you declare the variable at module level? Can an entirely different application read your variable? These questions are all scope-related, and this article will provide information on how to control scope as well as best practices and patterns for making use of scope. Scope can be very flexible, but to liberal use of it can also make for some very difficult to maintain code.

Lifetime is a closely related concept, usually discussed in conjunction with scope. While scope concerns itself with how "visible" a variable is, the lifetime of a variable relates to how long the variable value is active for. When does the variable get reset? How long does it retain it's value for? If you set X = 5, how long does it remain 5? If you have a variable defined in a sub or function, does it reset when the procedure is completed? Does it have the same value next time the procedure is called? What if we declare it module-level? How long does it "hold" then?

You'll notice that these questions are very related to those offered for Scope, and likewise, most programming languages give the means to control lifetime to a fine degree. Also likewise, one should fully understand the lifetime and control it as tightly as feasible to make code more maintainable.

Contents

Modules and Module Anatomy

Because so much of the technique in dealing with scope and lifetime relies on a) what type of module the variables are in, and b) where in the module the variables are declared, a solid understanding of module types and the different parts of a module are an essential prerequisite to the study of scope.

Class Module: A class module is a module that is associated with a form/report or one that is created using the triangular shaped module button.
Standard Module: A standard module is a module that is not a class module. Unless you're writing code in a form or report, most code will be in a standard module
Module Level (Declarations): The Declarations portion of a module is the area after "Option Explicit" and before the first procedure starts. Any code here is defined as "module-level" code.
Procedure Level: Any code defined within a procedure (i.e.: sub, function or property) is called procedure-level.

Scope

There are essentially 3 levels of scopes available to us in a VBA project. Those are procedure, module and global level.

Procedure Level

Scope at it's simplest - and most common - is procedure level scope. With no exceptions, a variable defined within a procedure can never be directly accessed from outside the procedure. Variables in a procedure are declared using the Dim statement:

Private Sub MyButton_Click()
  Dim x As Integer
  ...
End Sub

Note how the Dim statements that appears between Function or Sub and its corresponding End

CODE
Public Sub MultiplyNumbers()

Dim a As Long
Dim b As Long

a = 5
b = 3

Debug.Print (a * b)

End Sub

Public Sub DivideNumbers()

Dim a As Long
Dim b As Long

a = 20
b = 4

Debug.Print (a / b)

End Sub

The variables a and b exists only within the procedure MultiplyNumbers or DivideNumbers. But the key concept is that the MultiplyNumbers' a variable is NOT the same variable as DivideNumbers' a variable. As you can see, each procedure has assigned a different number to the a and b variables but the answers returned by each procedure remains consistent because the variables are visible only to exactly one procedure.

Furthermore, note that in both procedures, we had to assign something to both variables. If you modified the procedure to print the variable priror to assignment as shown:

CODE
Public Sub MultiplyNumbers()

Dim a As Long
Dim b As Long

Debug.Print a, b

a = 5
b = 3

Debug.Print (a * b)

End Sub

Running it would return 0, 0, indicating that both variables only have their default values set. They have no memory of any prior values. Running it again would still give you the same result and thus we must always assign some value to the variables. Static variables and different scopes will influence how assignments will effect the variables as the later discussion will make clear.

Module Level

Variables defined at module-level - also called the Declarations portion of a module - are by default visible to all code within the module. This is true for both standard modules and class modules. Module-level variables are declared after the Option Statements and before the first procedure.

CODE
Option Compare Database
Option Explicit

Private mVariable As Integer

Sub Test1()
 mVariable = 5
End Sub

Sub Test2()
 Debug.Print mVariable
End Sub

In the above example, variable mVariable is declared at module level, and thus all code within the module has access to it.

Variables defined at module level are declared using the Private or Public declaration. Variables declared Private are visible only within the module to which they are defined. Variables declared as Public are visible to all modules within the project, and are considered to have Global scope.

Global

Global Variables are declared as Public in the Declarations portion of a module. For standard modules, these variables are always accessible by any other VBA code in the project. For class modules, these variables are accessible to all other code within the project when the class is instantiated.

CODE
Option Compare Database
Option Explicit

Public gGlobalVariable As Integer

Sub Test()
 gGlobalVariable = 5
End Sub

In the above example, variable gGlobalVariable is visible not only to the module in which it's declared, but to all other VBA code within the project as well.

Best Practices

The Golden Rule for Scope is as simple as follows:

Always scope your variables to the smallest reasonable scope. Additional scope equals additional complexity.

Worth noting is the practice of defining global variables. This is a much debated topic, but while some stand by the perspective that global variables should never be defined (e.g., they should always be wrapped with accessors at least) and others stand by the perspective that global variables are fine to use, both parties tend to agree that liberal use of global variables is a bad practice.

By holding to The Golden Rule for Scope, you will find little, if any, global variable requirements anyway.

Lifetime

Lifetime in Procedures

Static Variables

Module-Level Lifetime

Use Cases

Reasons to use various scopes

Reasons to control various lifetimes

Advanced Topics

Scope & Lifetime in Classes

Protecting Variables with Accessors

Self-Healing Variables

Friends

Exposing to External Applications

Edit Discussion
Custom Search


Thank you for your support!
This page has been accessed 13,619 times.  This page was last modified 11:13, 5 June 2014 by Jack Leach. Contributions by BananaRepublic  Disclaimers