Convenience Functions (My Secret Weapon to Create Self-Commenting Code)
How much can you really gain by replacing one line of code with a different, functionally equivalent line of code? Quite a bit, as it turns out.
A "convenience" function is a short procedure that wraps a bit of functionality into a more readable form.
When I say short, I mean really short. Many of these procedures contain only a single line of executable code.
I used to feel silly writing these kinds of routines. After all, how much can you really gain by replacing one line of code with a different, functionally-equivalent line of code? Quite a bit, as it turns out.
Wherefore Convenience Functions
Why do I use thee? Let me count the ways.
Don't repeat yourself
Anytime you find yourself copying and pasting code–even if it's only a single line–you should stop and consider whether that code could be extracted into a standalone procedure.
For example, I always open reports in Print Preview mode rather than sending them directly to the printer (which is the default behavior of DoCmd.OpenReport
). This resulted in lots of code that looked like this:
DoCmd.OpenReport RptName, acViewPreview, , WhereCondition
This is very readable code, notwithstanding the omitted FilterName parameter resulting in an extra comma. I was repeating myself, though. I had to remember to include the acViewPreview
flag every time I called this method. But I didn't always remember.
In fact, I forgot the acViewPreview
flag so often, that I finally gave up and set my default printer to a virtual printer driver to save on paper. I realized that was silly, so I created a convenience function to wrap the above command and remove the need for the preview flag:
PreviewReport RptName, WhereCondition
Evolving needs
What begins as a simple wrapper function often expands into something with additional functionality. If you are using a custom procedure to provide some feature, you can improve the feature by modifying the code in a single, central location.
In fact, the PreviewReport function from above is a perfect example of something that started as a convenience function but evolved into something that addressed several frustrations I had with the built-in DoCmd.OpenReport
method.
Self-commenting code
What's better than well-commented code? Well-written code that requires no comments.
Here's a quick example from my article on date-related convenience functions:
'--== Well-commented code ==--
'Calculate the start and end of the current month
StartDate = DateSerial(Year(Date), Month(Date), 1)
EndDate = DateSerial(Year(Date), Month(Date)+1, 0)
'--== Self-commented code ==--
StartDate = MonthStart(Date)
EndDate = MonthEnd(Date)
Why is self-commenting code better than well-commented code? Because sometimes good comments go bad.
Improved readability
How do you force Access to save the current record in a bound form? You set the form's Dirty property to False. I often do this as a first step before previewing a report. This ensures the report has access to data the user may have just entered.
Me.Dirty = False 'Save the current record
PreviewReport RptName
Of course, sometimes Access can't save the record due to some failed validation condition. When the save fails, I usually want to exit the routine to give the user a chance to deal with the issue. One way to do this would be to turn off error-handling, try to set Dirty to False, and then restore error-handling if the save succeeds.
On Error Resume Next
Me.Dirty = False 'Try to save the current record
If Me.Dirty Then Exit Sub 'There are unsaved changes and the save failed
On Error Goto 0
PreviewReport RptName
Again, this is fairly easy to follow. But if I use my SaveFails convenience function, the code is much more readable:
If SaveFails(Me) Then Exit Sub
PreviewReport RptName