Premature Declaration Redux

Let's revisit the argument about whether to declare variables at the top of a procedure or closest to first use. We'll ask ChatGPT to make the best case for each position.

Premature Declaration Redux

I'm always a bit uncomfortable when I find myself on the other side of an issue with someone I respect as much as longtime Access MVP Karl Donaubauer.

But that's where I found myself in my recent article on declaring variables closest to their first use:

Thomas Jefferson’s Accidental Programming Advice
Premature declaration is nothing to be embarrassed about. It can happen to anyone. You don’t want to make a habit of it, though.

Karl's first comment on the above article began thusly:

I couldn't disagree more. Ok, I could, but I completely agree on Option Explicit.

Karl goes on to make a strong case for his position, especially in the context of his day-to-day work which involves spending a lot of time trying to make sense of other people's code (emphasis mine):

I orientate myself more on the reality of the mass of Access/VBA programming that I experience than on full professionals or wishful thinking. Even then I would disagree, but that is IMO more a matter of taste/style.

What I see IRL are the non-declarers, the partial declarers, the all-at-the-start declarers and the mixed declarers. The all-at-the-start declarers are by far the best to handle. With the mixed or pay-as-you-go declarants, I often experience a mess of multiple declarations (with Option Explicit just with different names) because they have lost track. Then you have "strSQL", "SQL", "sSQL" etc. and worse "Discount", "disc", "dbDisc", etc. This happens much less often when they declare everything or at least a lot at the beginning. Then it is also much easier to tidy up. And we're not talking about a handful of procedures, but usually a few hundreds.

So don't make my work more difficult with your nice-sounding concepts here! ;-)

Straw Men vs. Steel Men

These days, many online arguments boil down to attacks on straw men:

A straw man fallacy (sometimes written as strawman) is the informal fallacy of refuting an argument different from the one actually under discussion, while not recognizing or acknowledging the distinction.[1] One who engages in this fallacy is said to be "attacking a straw man".

By contrast, a steelman argument involves making the best possible case for a proposition:

A steel man argument (or steelmanning) is the opposite of a straw man argument. Steelmanning is the practice of applying the rhetorical principle of charity through addressing the strongest form of the other person's argument, even if it is not the one they explicitly presented. Creating the strongest form of the opponent's argument may involve removing flawed assumptions that could be easily refuted or developing the strongest points which counter one's own position. Developing counters to steel man arguments may produce a stronger argument for one's own position.

Steelmanning with ChatGPT

ChatGPT is a great tool for steelmanning positions with which you disagree.

But first, an important word of warning: ChatGPT has a very strong sycophantic side.  Unless you explicitly tell it not to, it has a tendency to tell you what it thinks you want to hear.

Let's ask ChatGPT to steelman both sides of this argument and let the chips fall where they may.  (NOTE: My prompts are in italics; the responses from ChatGPT-4 Turbo follow.)


[Mike]: In the article I wrote at https://nolongerset.com/premature-declaration/, I make the case that VBA variables should be declared closest to their first use.  In the comments of that article, Karl Donaubauer vehemently disagrees.

Please make the strongest case you can for each position.

Case for Declaring Variables Close to Their First Use

1. Improved Readability: When variables are declared close to where they are first used, it becomes easier for someone reading the code to understand what the variable is for without needing to scroll back to the top of the code. This proximity can also make the code easier to maintain and debug because the purpose and use of the variable are immediately apparent.

2. Less Error-Prone: Declaring variables closer to their first use reduces the risk of using uninitialized variables, which can lead to bugs. This practice ensures that variables are initialized right before they are used, minimizing the lifespan of an uninitialized state.

3. Easier Maintenance and Refactoring: Code is often changed or refactored, and having variables declared near their use means that when a section of code is moved or modified, the related variable declarations can easily move with it. This reduces the chance of leaving behind unused variables and makes the moved code self-contained and easier to understand.

4. Avoids Unused Variables: By declaring variables close to where they're used, it's easier to avoid declaring variables that never get used or are only used far removed from their declaration point. This can also help in identifying and removing obsolete variables during code reviews or refactoring sessions.

5. Principle of Least Astonishment: Developers expect to see related code together. Declaring and initializing variables close to where they are used adheres to this principle, reducing surprises for someone new to the codebase or revisiting old code.

Case for Declaring Variables at the Top of the Procedure

1. Scope and Lifetime Clarity: Declaring all variables at the top of a procedure or function makes it clear what variables will be used throughout the code. This practice provides a single place to look to understand all the data manipulations that might happen in that block of code, offering a clear overview at the beginning.

2. Traditional Structured Programming: Many older programming guidelines and standards advocate for declaring variables at the beginning of a block. This approach is rooted in the structured programming paradigm where the structure and flow of the program should be immediately evident from the first lines of any code block.

3. Easier to Track Variables: When all variables are declared at the top, it's easier to track what variables are in scope and potentially reduces the risk of redeclaring the same variable in different parts of the code, which can be particularly problematic in languages with block scope.

4. Performance Considerations: In some environments, particularly in compiled languages, there might be optimizations that can be better achieved when the compiler knows all the variables in advance. While this is less of a concern in interpreted languages like VBA, habits formed in other programming contexts can influence best practices.

5. Consistency: Especially in larger codebases or teams, having a consistent style guide that includes variable declaration can reduce cognitive load. If the team standard is to declare at the top, this consistency can aid in readability and maintainability across multiple modules or projects.

Conclusion

Both approaches have their merits, and the choice might depend on the specific context of the project, team preferences, language used, and the complexity of the code. In languages like VBA, where the scope is generally procedure-wide regardless of declaration location, the choice largely hinges on readability and maintainability preferences.

[Mike]: If it were up to you, what would you recommend and why?  Would your recommendation depend on the context?  If so, what conditions would you use to decide which approach to go with?  Don't spare my feelings.  Be as objective as possible.

Given the considerations discussed, if I were to make a recommendation, I would generally advocate for declaring variables close to their point of first use. This approach aligns well with modern best practices in programming that prioritize code readability, maintainability, and reducing the risk of errors. Here’s why and when this recommendation might change based on context:

Preferred Recommendation: Declare Variables Close to First Use

1. Readability and Maintainability: Code that is easier to read and maintain is less likely to harbor bugs and is easier to modify or extend. Declaring variables near their use helps keep the context clear and reduces the cognitive load on the developer, making the code easier to understand at a glance.

2. Minimizing Errors: This strategy reduces the scope of variables and the likelihood of using them uninitialized. It also makes it easier to manage variable lifecycles and understand their usage patterns without needing to refer back to distant parts of the code.

3. Adherence to Modern Practices: Most modern programming languages and style guides recommend this approach. Adapting to these practices can make transitioning between different programming languages and environments smoother.

Context-Dependent Adjustments

However, adherence to this recommendation can and should be flexible based on several factors:

1. Language and Environment: Some programming environments or languages might have specific requirements or idioms that favor declaring variables at the beginning of a block. For instance, older versions of languages like C required variables to be declared at the start of a block. Understanding and respecting the norms and limitations of the programming environment is crucial.

2. Legacy Code and Team Practices: In environments where there is existing legacy code, or specific team practices are in place that dictate declaring variables at the start, it may be more practical and less disruptive to follow existing conventions.

3. Performance Considerations: In some compiled languages, there can be performance optimizations related to how variables are declared and managed. In such cases, profiling and performance testing might dictate a specific approach to variable declaration.

4. Project and Codebase Scale: In very large projects or codebases, where hundreds or thousands of developers are involved, consistency might trump other considerations. A unified style guide that includes variable declaration practices can improve overall code quality and teamwork.

5. Educational or Training Contexts: In teaching or when working with junior developers, it might sometimes be beneficial to start with variable declarations at the top to help them understand what data the code will manipulate before delving into how it's manipulated.

Conclusion

In conclusion, while the preference leans towards declaring variables close to their first use due to its numerous benefits in terms of readability and error reduction, it's essential to remain flexible and consider the specific context of the project or team. Adapting to the needs of the environment, respecting legacy practices when necessary, and prioritizing consistency in large teams are all valid reasons to deviate from this general recommendation.

[Mike]: I am only concerned about VBA programming in the context of Microsoft Access.  Does that affect your recommendation one way or another?  If so, how?

Given the specific context of VBA programming within Microsoft Access, the recommendation to declare variables close to their first use remains generally valid, but there are some nuances to consider that are specific to VBA and Access that might influence the decision:

Reasons to Maintain the Recommendation:

  1. Error Handling and Debugging: VBA in Access does not have robust modern debugging tools compared to newer programming environments. Declaring variables close to where they are used can simplify debugging by making it easier to track the variable's value changes and understand its scope and relevance in the context of its use.

  2. Modularity and Readability: VBA code, especially in Access applications, often involves a lot of interaction with database objects like tables, queries, and forms. Keeping variable declarations close to where they are used can help make the code more readable and modular, particularly when dealing with database interactions and UI elements.

  3. Maintainability: Access databases often evolve over time, with changes to forms, reports, and underlying data structures. Code that clearly associates variable declarations with their use can be easier to update and maintain, especially for developers who might not be familiar with the original design of the database application.

Considerations Specific to Microsoft Access:

  1. Legacy Code and Conventions: Many existing Access applications have been built over long periods and might use older coding conventions, including declaring all variables at the top of procedures. When working in such environments, it might be necessary to maintain consistency with the existing codebase to avoid confusion.

  2. Macro and Event-Driven Logic: VBA in Access often interacts closely with form and report events. In such cases, declaring variables at the top of an event procedure (like Form_Load, Form_Open, etc.) can sometimes make it clearer what data will be manipulated throughout the event's logic, particularly if the event handling code is lengthy.

  3. Team Preferences and Skills: If you are working in a team environment, especially where team members may have varying levels of programming expertise, following a consistent and possibly simpler convention (like declaring variables at the top) might help less experienced developers understand the overall structure of the code more easily.

Final Recommendation:

For new projects or when refactoring significant parts of an application, I generally recommend declaring variables close to where they are used in VBA within Access. This approach tends to make the code more readable and maintainable, and better suited to adapt to changes. However, respect for existing code conventions and maintaining consistency within a team or across a large codebase should guide whether to adopt this recommendation wholesale or adapt it to fit the specific circumstances of your project.

In summary, while the recommendation is slightly tilted towards declaring variables close to their use even within Microsoft Access, adjustments should be made based on the specific project, team dynamics, and existing code practices. This ensures that the benefits of any coding standard are balanced against practical considerations of implementation and maintenance.

A Final Word

In the end, it's an issue upon which reasonable people may disagree.  

With that in mind, I'll channel my inner Shawn Spencer and concede that, indeed, "I've Heard It Both Ways":

Cover image generated by DALL-E-3.

All original code samples by Mike Wolfe are licensed under CC BY 4.0