Ok, this is a doubt I always have when I'm writing any API, a.k.a., code reusable.
What do you do with exceptions? There are different possibilities:
Always throw them to the client. The exceptions are acumulative, so if method A uses the private method B and method B throws an exception and method A throws another exception, the client sees 2 exceptions and only should see the latest because is the method that he is invoking. We can acumulate a lot of exceptions.
Only throw the exceptions produced on the method that the client invokes. What do we do with the internal exceptions? Just print the exception (
printStackTrace()
)? Convert this checked excep开发者_JS百科tions to unckecked exceptions so we only have to throw them?Implement an interface that the client can use to set his prefered Log. I simply refuse do this.
Extend a
RuntimeException
and always throw your customized unchecked exception. All the methods published to the client are well explained and says that the methods can throw the exception if the contract is fulfilled. I like this technique.
Regarding your first point - it's always better to create a domain-specific hierarchy of exceptions for your API (e.g. spring's DataAccessExceptions) and wrap everything that goes out to your clients.
The rule of thumb regarding checked/unchecked exceptions is:
- Throw unchecked exceptions when client cannot do anything about the error
- Throw checked exceptions when client should handle the error
Regarding the second point - never hide internal errors if they affect the client in any way. Also, don't output the error information into a side channel (like e.printStackTrace()
) the client might not be aware of. If you need to provide non-exceptional information to your users, you have two options:
- Provide methods which accept a
Logger
of some kind- Pros: explicit, no additional dependencies
- Cons: clutters the API, cumbersome to use
- Use SLF4J logging facade and do your logging in a normal way
- Pros: keeps the API clean
- Cons: dependency on
slf4j-api
You should throw the exception back to the client on the method they invoke. Exceptions that are generated internally in the API by private methods should either throw the exception back to the client or catch it and do something useful. You should throw back an exception up the method stack if its impossible to continue execution with the exception being generated.
Generally I like to use exceptions by extending Exception
or a subclass of it. Therefore the type of exception being thrown is more meaningful and easier to understand by the client. So I usually catch and then throw the custom one.
Checked exceptions are generally best to use by extending Exception
. They are generally easier to debug. But of course you may want to use unchecked exceptions in some cases.
Whatever you do don't use return values to indicate exceptional circumstances this is bad practice for Java. Just thought i'd mention it as I have seen it before.
Wherever you throw an exception make sure you add a meaningful message to it that the client can understand.
It ultimately comes down to what you would want in an API, but you should always make it as simple to use and easy to debug when exceptions occur.
I'm not sure if this goes under your first item, but what I prefer best is to catch an exception internally and then throw a new specific exception, with the original exception as the root cause:
class A {
void methodA() throws AException { /*...*/ }
}
class B {
void methodB() throws BException {
try {
new A().methodA();
} catch(AException e) {
throw new BException("A problem occured in methodA", e);
}
}
}
This can of course result in a few levels of nested exceptions, but the advantage is better information hidding (as you do not have to expose the internally used methods by the exceptions they throw) and also much less clutters the interface, as you do not end up with 20 exceptions in your throws declarations.
精彩评论