3

Let us consider the following C# code as an example:

    public static string GetCurentExecutableDirectory()
    {
        return System.IO.Path.GetFullPath(
            System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
    }

According to documentation, System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase cannot throw any exception, so we can suppose this part reliable. But the part System.IO.Path.GetFullPath can throw a few exceptions according to documentation.

I know that the code code will work fine 99.99% of the time, but if the execution is critical, I am a bit confused. On the one hand, I don't want to crash even if somehow System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase yields something that would force System.IO.Path.GetFullPath to raise an exception. On the other hand, I'm not sure checking things that should be evident makes much sense. (And as this example situation itself is nonsensical, the handling is quite delicate.)

The above is just an example and my question should be considered in the general sense

In a nutshell

In a critical piece of code, should exceptions describing a situation which does not makes sense be handled?

  • Possible duplicate of How should I handle exception that *should* never be thrown? – gnat Jul 14 '16 at 22:32
  • What makes code critical in your mind? And why would you want to handle exceptions differently compared to non-critical code? – Martin Maat Jul 14 '16 at 22:51
  • 1
    You will have to figure out what critical operation needs to continue to stay up and running despite exception. This is a higher-level design issue, and thus is unlikely to be handle-able within the method you're showing. For example, in the case of a web server, an exception during processing of a request should not kill the whole web server; that kind of resilience needs to be designed with your overall or larger software situation in mind. – Erik Eidt Jul 14 '16 at 23:01
  • 2
    In the .NET world, this sort of analysis isn't going to work for you, unless you're willing to wade through every possible code path in the .NET Framework Reference Source to find every possible exception that might be thrown. That's why every sensible program has one try/catch block at the very top that catches Exception (the ancestor of all exception classes), assuming you don't want your program to crash when it throws one. – Robert Harvey Jul 14 '16 at 23:02
  • Irrelevant for the conceptual question, but I think your example is broken. – Martin Ba Jul 15 '16 at 8:02
4

From your applications toplevel point of view, you do want to "crash". If a "nonsense" (your words) exception happens. In a controlled way: Either via an UnhandledExceptionFilter or toplevel catch(Exception).

It's also the easiest option: You don't have to do anything here. Just let the exception propagate.

From comment:

The point is that the code should only crash if the error (whatever nonsense it may describe) compromises the entire code execution.

But it does. From the point of view of that function, if you can't give back a valid directory, the entire calling chain is compromised. It is the job of the caller to decide whether to handle failure of (e.g.) GetCurentExecutableDirectory gracefully.

By example (C#6):

        // Example where the caller decides to handle it: /e.g. a "show exec dir operation"
        try
        {
            string execDir = GetCurentExecutableDirectory();
            Console.WriteLine($"Executable directory is: {execDir}");
        }
        catch(Exception ex) when (AppRules.IsNonCritical(ex))
        {
            Console.WriteLine("Sorry, couldn't determine the executable directory. (You may wish to inspect the logs for further details.)");
            Log(ex);
        }
        // Execution can continue / return normally here

        // ------------------
        // ------------------

        // Example where the caller decides *not* to handle it:
        string execDir = GetCurentExecutableDirectory();
        // Note, we really need this here, 
        // otherwise the rest of the code doesn't make sense ...

You will note that the caller doesn't care what exception caused the failure. The operation it tried to perform failed, and that's it. Log the exception for possible analysis and report back in a user/caller friendly way.

C#6 is nice that way, in that you can just filter out e.g. NullReferenceException in your IsNonCritical filter if you consider that to always be a bug. (CSE are not caught nowadays anyway.)

Side Note: Is catching general exceptions really a bad thing?

  • Exactly right. I would also add that the idea that it's a good thing to try to continue to execute when unexpected things are happening is a really pernicious delusion. This is not a way to make software robust. In fact it's the exact opposite. – JimmyJames Jul 18 '16 at 13:23
2

Define "critical".

If your software powers a pacemaker or Google.com, wrap the code to catch exceptions and log them in detail. And hope that somebody actually reads the logs and you promptly fix the problem.

Otherwise, I prefer to just crash and throw an Exception. Quietly logging an unexpected fatal error is inferior since it will likely get ignored and the user will get frustrated that their command, say Save, appeared to work, hey, there was no error message, right? But it really failed and that important memo they thought they spellchecked and saved is still full of typos the boss will see.

As Robert Harvey notes, wrap the entire app in a try / catch that provides some nice feedback to the user, like "oops, we had a serious error", then log the error and crash. They can call tech support who can read the stack trace, ask what happened, etc.

As Eric Eidt notes, when appropriate, structure the program to only crash for that one user, not everybody. And that is indeeda high level architctural decision.

  • Critical code in my question (and elsewhere I believe) is code where code quality and reliability is paramount. The other questions here and there mention a "fail fast and log" approch, much like you are suggesting. The point is that the code should only crash if the error (whatever nonsense it may describe) compromises the entire code execution. – Marsya Kaustentein Jul 15 '16 at 7:22
  • im not sure pacemakers use software, if they do they probably dont use c# or any exceptions in the first place – jk. Jul 18 '16 at 11:33
2

"Exception Handling". Two little words but which is more important? I would argue, it's the latter.

In a critical piece of code, should exceptions describing a situation which does not makes sense be handled?

Counter-question: If a situation occurs which "does not make sense", what can you[r code] do about it?

  • If the answer is "something useful", then by all means code an Exception Handler, deal with the exception and then allow the calling code to go on as if nothing had happened.
  • If, however, the answer is "not much", then don't catch it; let the caller of your code deal with it. If nothing handles it, then your program crashes and burns, courtesy of the "global" handler embedded within the run-time that launches your program.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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