Reduce Scope Of Variable

"You have a local variable declared in a scope that is larger than where it is used."
"Reduce the scope of the variable so that it is only visible in the scope where it is used."
http://www.refactoring.com/catalog/reduceScopeOfVariable.html


Some people have a bad habit of declaring "global" variables just to avoid the inconvenience of declaring them in each and every subroutine that uses them.

Example: Declare the integer "i" as a global, so that loops throughout the program can use "i" without declaring it.

Problem: Some functions call other functions to get work done. Those functions may also use "i", destroying the data the caller is using.

Solution: When a global variable is not used to pass data between functions, replace it with local variables in each of the functions.

Alternate Solution: A global variable can always be replaced with a global object or global functions. This still lets you share a single instance of data, but provides more controlled access.

(And use objects, parameters and other refactorings to minimize or eliminate the remaining globals too. ;-)

Another problem: "i" is a meaningless variable name. By keeping the scope as small as possible, you can also keep the usage consistent. Keeping the usage consistent allows you to provide a meaningful variable name.


When picking up VisualBasic programs written by other people, I often find a large number of variables declared at the Form level, only a few of which are used for communication between functions on the form.

Example:

  Private strSQL As String
...used to build SQL statements, like SELECT, INSERT, UPDATE or DELETE, for execution. Typical usage:
   strSQL = "select name, address, hire_date "
   strSQL = strSQL & "from Employee "
   strSQL = strSQL & "where ID = " & thisEmployeeID
   Call ExecuteASelectStatement(strSQL, ...)
When every usage of the variable starts by initializing it (and there are no tricky side effects from functions called within each usage), then the variable should be private to each function that needs it.

As for memory usage, having a large number of local variables instead of fewer global variables actually saves memory: Local variables are allocated on the stack, so they only take memory when needed. And local variables are released when the function exits. -- JeffGrigg


Re: Some people have a bad habit of declaring "global" variables just to avoid the inconvenience of declaring them in each and every subroutine that uses them.

In my opinion, declaring large volumes of similar local variables and/or parameters over and over again is a violation of OnceAndOnlyOnce, or at least approaching a CodeSmell. Context can be a good thing. Context is a technique to simplify things. It often removes repetition from code patterns. We use it everyday in spoken language and other endeavors. Of course, it depends on the situation and domain. Some languages have decent alternatives between just local or global. Routines which are module-specific and likely to stay that way are a good candidate for some kind of module-level or nested scope (Pascal-style) to take advantage of context. Something which is intended as a generic or semi-generic function probably is best with more formality and locality with regard to scope. To assume up-front that everything is a strong candidate for re-use is a wasteful violation of YagNi in my opinion. All the wrapping and protective packaging just clutters up the code and makes it longer and harder to read in my experience.

My experience is just the opposite. If a variable is declared close to where it is used, in a restricted scope, then I can understand the code in that scope much more quickly: I don't have to hunt around for the variables definitions to see their types or how they're initialized, and I don't have to worry that changes to those variables have side effects on other code. Even with development environments that help you find variable references, checking these things can waste considerable time when trying to comprehend unfamiliar code. Even the use of member variables solely to communicate state between class-internal methods resembles global variables in these aspects, and should generally be avoided. -- DanMuller


CategoryRefactoring


EditText of this page (last edited January 28, 2009) or FindPage with title or text search