When I define interfaces to the functions that I implement, I try to be explicit about the variables that the functions will examine and modify. From time to time, a global variable is necessary, and I typically employ intermediary functions for accessing such a variable. Avoiding the direct use of global variables within functions is a sound software implementation principle.
An ideal function under the functional programming paradigm operates only on its parameters and returns a single value. Functions that possess these attributes along with good function names are coherent and cohesive. The function is dependent entirely on its parameters. There are no implicit dependencies. As opposed to a function that operates on a global variable, for example, a function that operates only on its parameters can accept different parameters from its caller.
There are times when a global variable is required, and introducing accessor functions to provide access to these variables is highly recommended. One benefit that accessor functions provide is the possibility of implementing state validation. In general, using accessor functions allows for preprocessing before access to the global variable is provided. Using an accessor function, even if such a function simply returns the global variable, introduces another level of indirection. It effectively provides an interface to the global variable.
Like the good practice of keeping member fields of objects in C++ non-public and preventing dependents of those objects from acting on those objects’ data fields, a level of indirection should be introduced between a global variable and the code that depends on the global variable.