Best practices for exception management in Java or

2019-01-01 04:45发布

I'm stuck deciding how to handle exceptions in my application.

Much if my issues with exceptions comes from 1) accessing data via a remote service or 2) deserializing a JSON object. Unfortunately I can't guarantee success for either of these tasks (cut network connection, malformed JSON object that is out of my control).

As a result, if I do encounter an exception I simply catch it within the function and return FALSE to the caller. My logic is that all the caller really cares about is if the task was successful, not why it is wasn't successful.

Here's some sample code (in JAVA) of a typical method)

public boolean doSomething(Object p_somthingToDoOn)
{
    boolean result = false;

    try{
        // if dirty object then clean
        doactualStuffOnObject(p_jsonObject);

        //assume success (no exception thrown)
        result = true;
    }
    catch(Exception Ex)
    {
        //don't care about exceptions
        Ex.printStackTrace();
    }
    return result;
}

I think this approach is fine, but I'm really curious to know what the best practices are for managing exceptions (should I really bubble an exception all the way up a call stack?).

In summary of key questions:

  1. Is it okay to just catch exceptions but not bubble them up or formally notifying the system (either via a log or a notification to the user)?
  2. What best practices are there for exceptions that don't result in everything requiring a try/catch block?

Follow Up/Edit

Thanks for all the feedback, found some excellent sources on exception management online:

It seems that exception management is one of those things that vary based on context. But most importantly, one should be consistent in how they manage exceptions within a system.

Additionally watch out for code-rot via excessive try/catches or not giving a exception its respect (an exception is warning the system, what else needs to be warned?).

Also, this is a pretty choice comment from m3rLinEz.

I tend to agree with Anders Hejlsberg and you that the most callers only care if operation is successful or not.

From this comment it brings up some questions to think about when dealing with exceptions:

  • What is the point this exception being thrown?
  • How does it make sense to handle it?
  • Does the caller really care about the exception or do they just care if the call was successful?
  • Is forcing a caller to manage a potential exception graceful?
  • Are you being respectful to the idoms of the language?
    • Do you really need to return a success flag like boolean? Returning boolean (or an int) is more of a C mindset than a Java (in Java you would just handle the exception) one.
    • Follow the error management constructs associated with the language :) !

15条回答
笑指拈花
2楼-- · 2019-01-01 04:55

My strategy:

If the original function returned void I change it to return bool. If exception/error occurred return false, if everything was fine return true.

If the function should return something then when exception/error occurred return null, otherwise the returnable item.

Instead of bool a string could be returned containing the description of the error.

In every case before returning anything log the error.

查看更多
路过你的时光
3楼-- · 2019-01-01 04:55

I may be a little late with the answer but error handling is something that we can always change and evolve along time. If you want to read something more about this subject I wrote a post in my new blog about it. http://taoofdevelopment.wordpress.com

Happy coding.

查看更多
泪湿衣
4楼-- · 2019-01-01 04:57

It seems odd to me that you want to catch exceptions and turn them into error codes. Why do you think the caller would prefer error codes over exceptions when the latter is the default in both Java and C#?

As for your questions:

  1. You should only catch exceptions that you can actually handle. Just catching exceptions is not the right thing to do in most cases. There are a few exceptions (e.g. logging and marshalling exceptions between threads) but even for those cases you should generally rethrow the exceptions.
  2. You should definitely not have a lot of try/catch statements in your code. Again, the idea is to only catch exceptions you can handle. You may include a topmost exception handler to turn any unhandled exceptions into something somewhat useful for the end user but otherwise you should not try to catch each and every exception in every possible place.
查看更多
临风纵饮
5楼-- · 2019-01-01 04:57

I would like to recommend another good source on the topic. It's an interview with inventors of C# and Java, Anders Hejlsberg and James Gosling respectively, on the topic of Java's Checked Exception.

Failure and Exceptions

There are also great resources at the bottom of the page.

I tend to agree with Anders Hejlsberg and you that the most callers only care if operation is successful or not.

Bill Venners: You mentioned scalability and versioning concerns with respect to checked exceptions. Could you clarify what you mean by those two issues?

Anders Hejlsberg: Let's start with versioning, because the issues are pretty easy to see there. Let's say I create a method foo that declares it throws exceptions A, B, and C. In version two of foo, I want to add a bunch of features, and now foo might throw exception D. It is a breaking change for me to add D to the throws clause of that method, because existing caller of that method will almost certainly not handle that exception.

Adding a new exception to a throws clause in a new version breaks client code. It's like adding a method to an interface. After you publish an interface, it is for all practical purposes immutable, because any implementation of it might have the methods that you want to add in the next version. So you've got to create a new interface instead. Similarly with exceptions, you would either have to create a whole new method called foo2 that throws more exceptions, or you would have to catch exception D in the new foo, and transform the D into an A, B, or C.

Bill Venners: But aren't you breaking their code in that case anyway, even in a language without checked exceptions? If the new version of foo is going to throw a new exception that clients should think about handling, isn't their code broken just by the fact that they didn't expect that exception when they wrote the code?

Anders Hejlsberg: No, because in a lot of cases, people don't care. They're not going to handle any of these exceptions. There's a bottom level exception handler around their message loop. That handler is just going to bring up a dialog that says what went wrong and continue. The programmers protect their code by writing try finally's everywhere, so they'll back out correctly if an exception occurs, but they're not actually interested in handling the exceptions.

The throws clause, at least the way it's implemented in Java, doesn't necessarily force you to handle the exceptions, but if you don't handle them, it forces you to acknowledge precisely which exceptions might pass through. It requires you to either catch declared exceptions or put them in your own throws clause. To work around this requirement, people do ridiculous things. For example, they decorate every method with, "throws Exception." That just completely defeats the feature, and you just made the programmer write more gobbledy gunk. That doesn't help anybody.

EDIT: Added more details on the converstaion

查看更多
萌妹纸的霸气范
6楼-- · 2019-01-01 04:59

All of the above seems reasonable, and often your workplace may have a policy. At our place we have defined to types of Exception: SystemException (unchecked) and ApplicationException (checked).

We have agreed that SystemExceptions are unlikely to be recoverable and will bve handled once at the top. To provide further context, our SystemExceptions are exteneded to indicate where they occurred, e.g. RepositoryException, ServiceEception, etc.

ApplicationExceptions could have business meaning like InsufficientFundsException and should be handled by client code.

Witohut a concrete example, it's difficult to comment on your implementation, but I would never use return codes, they're a maintenance issue. You might swallow an Exception, but you need to decide why, and always log the event and stacktrace. Lastly, as your method has no other processing it's fairly redundant (except for encapsulation?), so doactualStuffOnObject(p_jsonObject); could return a boolean!

查看更多
看风景的人
7楼-- · 2019-01-01 05:00

try/catch blocks form a second set of logic embedded over the first (main) set, as such they are a great way to pound out unreadable, hard to debug spaghetti code.

Still, used reasonably they work wonders in readability, but you should just follow two simple rules:

  • use them (sparingly) at the low-level to catch library handling issues, and stream them back into the main logical flow. Most of the error handling we want, should be coming from the code itself, as part of the data itself. Why make special conditions, if the returning data isn't special?

  • use one big handler at the higher-level to manage any or all of the weird conditions arising in the code that aren't caught at a low-level. Do something useful with the errors (logs, restarts, recoveries, etc).

Other than these two types of error handling, all of the rest of the code in the middle should be free and clear of try/catch code and error objects. That way, it works simply and as expected no matter where you use it, or what you do with it.

Paul.

查看更多
登录 后发表回答