To use or not to use module level variables

This page discusses module level variables, when their use is acceptable and their scope (public or private). Variables contain the data your program relies on. Using module level variables may seem tempting, you only have to set their value once and they will be available to all procedures, no need to pass them on to other procedures as arguments. A potential problem is when other processes in your program can alter those data your current program relies on. To prevent this from happening you need to make sure those variables have limited accessibility from elsewhere.

Procedure versus module level variables

When you write a variable declaration inside a procedure, Dim str1 As String, you are safe: this variable can only be changed inside the procedure. However, if you declare a module level variable other processes may unexpectedly alter its value. As an example, the 'NameUser' procedure sets variable mstrName to 'John'. So on Debug.Print mstrName he may expect 'John' to be written to the Immediate window. Alas, the calling of procedure 'MatchMachine' unexpectedly also altered the same module-level variable, resulting in returning 'Wall-E' instead.


Option Explicit

Private mstrName As String

Sub NameUser()
    mstrName = "John"
    MatchMachine
    Debug.Print mstrName
End Sub

Sub MatchMachine()
    mstrName = "Wall-E"
End Sub

Function GetName() As String
    GetName = mstrName
End Function

The above mishap can easily be avoided by not allowing the use of module level variables, considering this a bad practice - at least in standard modules.

Class modules: Properties, Private and Public variables

In class modules on the other hand Private variables are used to store property values which are primarily accessible using their corresponding Property procedures


Private mstrName As String
Property Get Name() As String
    Name = mstrName
End Property
Property Let Name(rData As String)
    mstrName = rData
End Property

In case of properties whose read and write access is Public, one could use Public variables as an equivalent containing less code. If it is wise to allow this exception to the rule of not allowing module level variables is a matter of opinion.