2

So, today I was reading a piece of code I found this function:

Public Function FolderExists(sPath As String) As Boolean
    Dim FSO As New FileSystemObject

    On Error GoTo errHandler

    sPath = Trim$(sPath)
    If sPath = vbNullString Then Exit Function
    FolderExists = FSO.FolderExists(sPath)

    Set FSO = Nothing

    Exit Function

    errHandler:
    FolderExists = False
    Set FSO = Nothing

End Function

Aside from the real usefulness of this function, I have a doubt about the error-handling.

Is error handling meant to protect the application from the deficiencies of the dev or is it to protect from some rare, but possible, error of the hardware or lower-level software or whatever?

Because this error handling is something that, for my limited knowledge, doesn't make sense.

For example, does this function require error handling? (let's ignore overflow)

Private Function Add1(arg As Long) As Long
    
    Dim result          As Long
    
    result = arg + 1
    
    Add1 = result
    
End Function
8
  • 1
    Anything taken to an extreme is ludicrous, so no its not because you aren't doing anything other than making a strawman. Its there for both, and more. It is there to protect a developer from themselves, or from garbage feed in. It is there to prevent an issue (man made, or a fried bug) in one place blowing up and taking out other parts of the program/computer. It is there to recover from a network timeout, or a resource suddenly being deleted (called fault tolerance). In your first example its providing fault tolerance.
    – Kain0_0
    Commented Feb 27, 2021 at 4:56
  • I still don't understand.. Can you make an example where the code in the error handler is executed? What has to happen?
    – DT1
    Commented Feb 27, 2021 at 5:33
  • Your FolderExists function already does. If for any reason the external system generates an error presume false. That is a kind of fault tolerance, and is common at integration points, other common handling is to back off wait and try again, only throwing an error after a number of attempts have failed.
    – Kain0_0
    Commented Feb 27, 2021 at 5:42
  • I get the general point you are making, but I'm not sure we are on the same page.. The FolderExists function is supplied by an external object and returns a boolean value. If something can go wrong, the function is responsible for possible errors because the function doesn't have cases in which something different from a boolean is returned. I can understand that the function in some strange cases may return the wrong result, but it always returns a boolean...correct?
    – DT1
    Commented Feb 27, 2021 at 6:06
  • 1
    Why check if the folder exists? Will it attempt to read or write something inside. Let us say yes. How many cores do your machine have? A handful? Ok. How many threads are there running right now? Or, if you prefer, how many can you start in your program? Figure it out. This comment can wait. A couple thousand? More? So threads got to take turns to run in the cores, right? A thread can be preempted at any moment. For example just after it checked a folder exists, it gets preempted, another thread deletes the folder, and now the first thread attempts to use it just get an error. Error handling!
    – Theraot
    Commented Feb 28, 2021 at 9:47

3 Answers 3

5

Sometimes the way to handle an error is to do nothing. Doing that deliberately, obviously, in a readable and understandable way, is handling the error. Doing nothing any other way invites the assumption that you forgot.

In that way, yes, it is always necessary. Because even doing nothing must be handled correctly.


Speaking of nothing, I'm spotting some Nothings that seem to have been written by someone who never read Tomalak's answer to "Is there a need to set Objects to Nothing?".

If you're not doing anything intensive after setting FSO to nothing you're just cluttering the code. It's going out of scope anyway. So the only useful error handling here is the setting of the Boolean.


Is error handling meant to protect the application from the deficiencies of the dev or is it to protect from some rare, but possible, error of the hardware or lower-level software or whatever?

Assertions are meant to protect the application from the deficiencies of the dev.

Error handling is meant to put the system back into a safe well defined state or halt the system before it does something silly like corrupt the database, format the hard drive, or send the president threating emails. Undefined systems behave in undefined ways. They must be defined or stopped.

Handling an error requires:

  • Reevaluating the state of the system in light of the error
  • Deciding if recovery is possible
    • If not, halting the system (making it the operators problem)
    • If so, putting the system into a defined state and adjusting the program to proceed from that state (sometimes this means doing nothing)
  • Informing the operator, if this means their expectations will need to change

When you reduce this to just returning a Boolean you're dumping all of that responsibility onto whoever called this function.

4

You asked

Is error handling meant to protect the application from the deficiencies of the dev or is it to protect from some rare, but possible, error of the hardware or lower-level software or whatever?

which gave me the me initial impulse to answer "none of these two reasons", but that is not correct, either. So let me first say a word about those two cases.

"Deficiencies of the dev"

This is simply a paraphrase for a bug, and bugs in application software or VBA macros like the one where you probably found this code snippet should be fixed. To get them fixed, they must be be made visible to whoever runs this programs. Hence the kind of error handling required for a potential bug is usually one which stops the program with a prominent error message, not one which sweeps the issue under the rug.

Note, for certain kind of errors caused by bugs, VBA stops the program automatically, and if that is what makes most sense in the given context, one can omit implementing explicit error handling. Some kind of explicit error handling can still make sense either, assumed you want to replace a very technical error message by a more explanatory one. It may be still the most sensible action to stop the program after showing that message.

"Errors of the hardware or lower-level software"

For some kind of programs, this can be necessary - for example, when doing low-level C programming for embedded devices. But for the kind of VBA macro from the question, I think this is unlikely. Here I would usually rely on the inbuilt error handling of the VBA interpreter.

"Ok, since we know what it is not good for, when do we really need it?"

Error handling has usually a different primary purpose than formerly discussed reasons. Standard "use cases" for error handling are situations where a program makes interactions with the "outside world", where certain issues can be foreseen, but where they should not stop the program.

In the given example case, FSO.FolderExists(sPath) interacts with the file system. If someone, for example, passes some characters into sPath which are not legal for the underlying file system, without any error handling this would terminate the program. And if that's not the desired behaviour, explicit error handling is mandatory. Note passing such invalid file names is not (necessarily) a sign of a bug. It is also no "error of the hardware or lower-level software" - it is probably a cause of some wrongly entered data from an outside source, like a user who mistyped a folder name.

The details of error handling in your question might be improved, but that is a different matter. Set FSO = Nothing is probably superflous. The function will return False if the folder does not exists, but also just False if the folder name was invalid, so the caller will not be able to differentiate beween these two cases. That might be exactly what's needed in the context of that function, but also restricts the reusability of the function a bit.

Your second code (function Add1) does indeed not contain anything which seems to require explicit error handling. If an overflow occurs, that would probably be a bug, or situation where the program cannot continue sensibly any more, so as I wrote above, handling may not be ncessary, since the VBA interpreter will stop the program automatically with an overflow message.

Conclusion

No, explicit error handling is not always necessary, especially in programming languages like VBA with inbuilt default error handling. It becomes necessary if the code may encounter foreseen issues, and you want the program to deal with these issues in a sane manner.

1

Instead of the word, error, let's use the word, exception. As in "exceptional." As in, "this almost never happens, and whether-or-not it's supposed to ... but, it just did."

Exceptions can be the result of "runtime errors," or they can be something that you deliberately throw. This latter possibility can prove to be an extremely-useful design decision.

"When you find yourself in a situation in which it is now impossible to continue, throw a detailed baseball into the air,' knowing that someone's gonna catch it."

Notice how this achieves a clean separation between the two "concerns." The party which encountered the dead-end situation has just one clear thing to do: write the gory details onto the baseball and throw it up in the air. (Then die.) Meanwhile, the catcher doesn't have to care where the incoming baseballs might be coming from: he just needs to catch 'em and read 'em and from that decide what to do next.

An easy example of this might be the ubiquitous ERR_ABORT: "the end-user just decided, for whatever reason, that he doesn't want to keep doing this anymore." The exception is thrown, and sometimes re-thrown one or more times, as the various layers of software un-wind themselves from what they had been doing. It's "exceptional," all right, yet it's not an "error."

(FYI: BASIC's classic on error goto is a simplification of the actual complete mechanism ...)


"In the bad old days," what you did when something went wrong in your function-call was to "return a non-zero return code." The trouble was that this created two return-paths within each and every piece of software that called your function ... and, "heaven help you if you missed even a single if-statement!" The concept of "exceptions" turned out to be much cleaner. Instead of creating both a "success path" and an "error path" in an unknown number of layers of software, and therefore software that relies upon the correct behavior of every single one of them in what is a probably-never-tested error case, create an escape-hatch that can reliably(!) blast its way out of an unknown number of control-structures, to wind up at a "known-good state" at strategically-placed catch points – which can evaluate data (within the thrown exception-object) that the failing routine reliably sent them. It worked.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.