Its quite common to require opposite pairs of functionality. Things like show/hide, or hide/unhide, or protect/unprotect, register/unregister, load/unload… you get the idea.
There are 2 basic approaches to this:
- have 1 function that takes a true/false parameter to tell it to do or undo the action
- have 2 clearly named functions whose names are good opposites, as above.
Which do you prefer?
I personally prefer the 2nd (I think) and I would say thats usually the way we interact with COM object models. I notice a lot of C code and Win API stuff uses the first though, so I thought about it a bit more.
I think the second (2 separate methods) is probably easier to understand, but on reflection the first is maybe more powerful. Or at least allows more concise code.
compare:
if msgb = vbyes then
menu.show
else
menu.hide
end if
to the more concise
menu.show(msgb = vbyes)
I guess the hard bit is getting a method name that makes sense with a true false parameter. Maybe a property gives the best of both worlds?
menu.visible = (msgb = vbyes)
What do you prefer? in your own code? in working with others (eg libraries)?
cheers
Simon
Wednesday, 5th March, 2008 at 2:13 am |
Guess you hit on the big question: should your example be a method or property? If method, then two separate methods would be better. If property, then one property taking a boolean argument would be better. So, should displaying or hiding a menu be an action (thus done using methods) or should this be considered a change of state (thus done changing a property)?
Do you drive on the left side of the road or the right?
Wednesday, 5th March, 2008 at 4:24 am |
When ever I write a procedure in a userform to enable/disable buttons based on context, I ask myself this same question. Should I write an enable procedure and a disable procedure so the code is clear and easy to understand? Or should I write one procedure? I always end up with one because I don’t want to repeat code (makes editing harder). I try to name my procedure as verb+none (e.g. EnableButtons). I think EnableButtons False is easy to understand.
Wednesday, 5th March, 2008 at 8:21 am |
What’s missing in that picture is the additional isdirty field for each property.
Wednesday, 5th March, 2008 at 8:27 am |
I prefer to toggle option with a single function, partially to reduce the amount and duplication of code.
However, often there’s circumstances where there are more than one alternative (yes, no, maybe) in which case I usually use an enumerator as a parameter to the method. I’ve seen others pass strings, but I prefer the readability and error control an enum provides (passing anything other than a valid enum value generates an error).
Cheers – Marcus
Wednesday, 5th March, 2008 at 9:48 am |
It depends on the exact circumstance, but I’d say that menu.show(false) is counter-intuitive and should be disregarded: If you’re going to use methods, then you’re going to need a separate one for each purpose i.e. menu.show([params]) and menu.hide([params]).
However, for toggles of state, a property procedure pair is absolutely the way to go, no question in my mind. The only debate, really, is whether show/hide is a simple toggle or something more.
Wednesday, 5th March, 2008 at 9:50 am |
I would generally go for one method that passes a true/false parameter. If I like to be really clear I would then do something like this:
Sub ToggleButtons(ByVal bEnable As Boolean)
‘ The usual crap
End Sub
Sub EnableButtons()
ToggleButtons True
End Sub
Sub DisableButtons()
ToggleButtons False
End Sub
If there are more than true/false I would go for the Enum to get compile time errors and full intellisense in the editor.
But if it’s just one custom object I think a property is better. I think cmdButton.Enabled = true is better than cmdButton.Enable() or cmdButton.Disable().
Wednesday, 5th March, 2008 at 12:08 pm |
Harlan being UK based I have the privilege of driving on both sides of the road, left here and right when I visit our neighbours across the channel.
Wednesday, 5th March, 2008 at 12:52 pm |
I learned to drive in Rhode Island, where it was permissible to drive on both sides of the road. Also in the middle.
About the question: two procedures or one procedure with an argument, the definitive answer is “it depends”. I’ve gotten into the habit of writing functions instead of subs, so
Set TheChart = BuildTheChart(CustomType as enum, rngData as Range)
rather than
BuildTheChart CustomType as enum, rngData as Range
I can query whether TheChart Is Nothing to see if the function worked, and I have the object defined so I can do something further with it.
Johan’s last comment, using dual approaches, is what I do with forms and other classes, where there is a property procedure that accepts an argument, and based on the argument, different sequences of actions are taken.
Wednesday, 5th March, 2008 at 2:35 pm |
“…I have the privilege of driving on both sides of the road…”
I was guessing that that was your natural driving style (regardess of intoxication level).
When in australia, of course, we drive upside down.
Cheers – Marcus
Wednesday, 5th March, 2008 at 6:10 pm |
Like Harlan, if a procedure *does* something, I use a Sub or Function, name it with a verb and have an equivalent verb for the opposite action. If procedure just changes state, I use a Property procedure, named with an adjective describing the thing being changed. And it’s a judgement call which to use. I’ve seen code using any (or all) of the following:
MakeRed
MakeBlue
MakeGreen
RunReport = “Go”
cmdDoIt.Value = True
Where the latter is used the ‘click’ a button on a form!
Thursday, 6th March, 2008 at 10:26 am |
All things beging equal, which they are not of course, I like using 2 functions, so there! ;-)