Refactoring Procedure Signatures: The Do's and Don'ts
As our VBA code evolves, we often need to modify existing procedure signatures.
However, it's crucial to understand the potential risks and follow best practices to maintain backward compatibility.
Understanding the Risks of Modifying Procedure Signatures
Changing procedure signatures can break existing code that calls those procedures.
When modifying a signature, consider the impact on any code that currently calls the procedure. This includes code in the same project, as well as any other projects where it may be reused. Be especially cautious when modifying procedures in a shared code library file, as the impact can be far-reaching.
Careless changes can lead to compile errors, runtime errors, or even subtle logic bugs.
When It's Appropriate to Modify a Procedure Signature
There are times when modifying a procedure signature is necessary or beneficial.
Some valid reasons to modify a signature include:
- Adding new functionality
- Improving code readability
- Making a procedure more generic
For example, if a procedure has a hard-coded value that limits its reusability, you can make the procedure more generic by extracting that value into a new optional parameter. This allows the procedure to support more scenarios without breaking existing code that relies on the original behavior.
Best Practices for Changing Parameter Types
When changing a parameter type, it's generally safer to make the new type more accommodating than the old type.
For example, changing from a specific type like Integer
to a more general type like Variant
is usually safe (though you sacrifice some compile-time safety checks as a result).
Avoid changing parameter types in a way that would require calling code to be modified. For instance, don't change a parameter from a String
to an object type, as that would require updates to any code that passes a string literal.
How to Safely Expand Procedure Visibility and Scope
If you need to make a procedure more widely accessible, it's safe to expand its visibility or scope. For example, you can change a Private
procedure to Public
, or a Friend
procedure to Public
.
However, avoid restricting a procedure's visibility or scope, as that can break existing code that relies on the current accessibility. For instance, don't change a Public
procedure to Private
if it's used by other modules.
Guidelines for Adding Optional Parameters
When adding new parameters to a procedure, it's important to make them optional and place them at the end of the parameter list. This allows existing code to continue calling the procedure without providing the new parameters.
Remember, if the new optional parameter is replacing a hard-coded value from the procedure, be sure to set its default value to match the one that was previously hard-coded.
Considerations When Renaming Parameters
Renaming parameters can improve code readability, but it comes with risks.
Calling code that uses the named parameter syntax (argumentName:=value
) will break if the parameter name changes.
Before renaming a parameter, search your codebase to ensure the named parameter syntax isn't used. If it is, you'll need to carefully update all the affected code. Tools like MZ-Tools can help with this (the Method Callers feature is great for this).
Techniques for Searching and Updating Existing Code
When you do need to make breaking changes to a procedure signature, it's crucial to find and update all the code that calls the procedure.
Use the built-in VBIDE search feature if you must, but I prefer a third-party tool, such as:
- MZ-Tools
- Philipp Stiefel's Find and Replace for MS Access
- TortoiseHg, Notepad++, or your favorite Git IDE along with your preferred Access Version Control add-in
Don't rely solely on compile errors to identify affected code. Some changes, like renamed parameters, can silently introduce logic bugs without causing compile errors. Thoroughly test the calling code after making signature modifications.
Exceptions to the Rules - When Breaking Changes May Be Warranted
While it's generally best to avoid breaking changes, there are situations where they may be justified.
If a procedure is used only within a single project and you can easily update all the calling code, a breaking change may be acceptable.
Breaking changes may also be necessary when fixing critical bugs or security vulnerabilities. In these cases, the benefits of the change outweigh the costs of updating the calling code.
When you do make a breaking change, clearly document it and communicate with any other developers who may be impacted.
By understanding these principles and following best practices, you can safely evolve your VBA procedure signatures while minimizing the risk of breaking existing code. Careful planning and attention to detail are key to maintaining backward compatibility.
Acknowledgements
- Initial draft generated with the help of Claude-3-Opus
- Cover image generated by DALL-E-3
- Cover image created with Microsoft Designer