Vb.Net got something right. Its separation of the trusty function and the subroutine makes perfect sense. Unfortunately, that transition has not made its way to any other recent language. Delphi and Pascal also use this idiom, labelling them Procedures and Functions respectively.
All other languages that omit a value from a method call, return a void type. By default, you will create your function and then decide whether to return something.
Let's look at the purpose of a void function or as I like to refer to them, a subroutine and try to comprehend the utter confusion it can bring.
Is there a correct usage of Void?
Isn't the purpose of a function to return something?
9 times out of 10 a function will return something. Otherwise, it will do something. These two acts should be tangibly different, yet we group them together. This leads to horrific methods that are not pure, do multiple things and mutate global state, all under the watchful eye of Master Void.
Programming has come a long way, yet we stick to this archaic practice that confounds me to this day. Now I'm not against the notion of functions doing something; This is what we want; The issue is the misuse of the void mechanism specifically.
When saving or deleting a record, is it better to return nothing, or should we return the object, boolean or an identifier of the record changed? Is explicitly checking for some value better than wrapping all that code in a try-catch block.
One valid use case is Logging; where information is captured about the application. Another is an entry point like the main function or task runner whose only job is to run a set of functions synchronously.
Why are you using Void?
Let's start with global properties. My ultimate bugbear with void functions is changing global state. It happens far too often. Don't do it!
The key design decision should be whether the function returns something? When creating a function ask yourself:
- Does it throw an exception if there is an error?
- Does it alter an object or some properties?
- Should we wrap code in a try-catch block?
- What happens when the function succeeds?
Do we care? Is more information better or worse?
That's down to you, I guess what I'm trying to say is that using void functions can cause confusion. It requires the developer to dig deeper into code because externally the function doesn't disclose any information about its effects.
I believe the only valid use case of a void function is a fire and forget call. So long as it didn't error, you don't care what it did.Me, hater of the misused void.
A void call shouldn't stop the rest of the code running successfully. It's not required for the rest of the function to do its job.
Are you sure it doesn't do something you want to know about?
This is the first question I as myself when looking at a void function.
It should be yours too!
My aim is not to stop people from using void functions. They are an intrinsic part of how software is developed and consumed, I just urge you to use them when necessary. You wouldn't save a number into a string field.
Don't use void without first thinking about the consequences of doing so.
I'd love to hear your views on this, counter arguments are most welcome!