• Post Reply Bookmark Topic Watch Topic
  • New Topic

How many exceptions should a method throw at most?  RSS feed

 
Avor Nadal
Ranch Hand
Posts: 156
Java Netbeans IDE Postgres Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello:

There are times that my methods need to report the caller about many kinds of errors, represented as checked exceptions. This makes my methods look like very convoluted. It happens mostly when I work with stateless EJBs and databases. Sometimes I end throwing even 8 different exceptions! Are they too many?

Many of them inherit from common exceptions, so I've been tempted to throw the parent classes. But I've quickly discarded that option because I've read that it's a bad practice, since a method may throw only a subset of the children of that parent class, not all.

Finally, I've studied these possibilities:

1. Throwing the parent class (mentioned above).
2. Throwing a common exception with an error ID or code as message.
3. Throwing a common exception with an enum as member, as if it were an ID or code (safer than the #2).

All them show the same defect that the #1. However it's more a conceptual problem than a technical one, because my callers always use the same mechanism to treat every "specialization" of the same exception, without worrying about if the method really can return it or not.

What do you think about all this? Thank you.
 
Stephan van Hulst
Saloon Keeper
Posts: 7992
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You're approaching the problem from the wrong perspective. Don't declare exceptions because you're using things that may throw exceptions, declare exceptions because they make sense when a user calls your method.

For instance, it would be ridiculous to throw an IOException in a method named calculatePi(int digits), even *if* your method uses I/O operations to retrieve the results.

I rarely write methods that throw more than two or three exceptions. When they work with many different types of exceptions, I usually have them throw either a common super-type, or I catch the exceptions within the method, and wrap them in an exception type that makes more sense for the method.

Maybe you can post your code and we can offer some suggestions.
 
Campbell Ritchie
Marshal
Posts: 56576
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
you should also consider what is right for your method, decide to do it, and /**write it down in the comments*/
You should not worry about how people will handle the Exceptions. You write the methods correctly and let them consider how to handle the Exceptions.
 
Avor Nadal
Ranch Hand
Posts: 156
Java Netbeans IDE Postgres Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:You're approaching the problem from the wrong perspective. Don't declare exceptions because you're using things that may throw exceptions, declare exceptions because they make sense when a user calls your method.

For instance, it would be ridiculous to throw an IOException in a method named calculatePi(int digits), even *if* your method uses I/O operations to retrieve the results.


Yes, I know what you mean. But I'm not throwing exceptions that haven't got any relation with the context of the method. Or I believe so at least, he he he.

For example, let's consider a stateless EJB that contains a method like this:



The method processes exams, which consists in doing some calculations for every student and exam, saving some data in a database, and returning a few statistics. "session" represents a session controlled by the application itself. You need to pass it on every call so it checks if it's valid or not. "studentExams" are the exams to be processed.

The method could be rewritten like this...



...Because NotFoundSessionException, ExpiredSessionException, PermissionException inherit from SessionException and StudentNotFoundException, StudentAgeLimitException, BannedStudentException inherit from StudentException. However, I've read that one shouldn't do this, because it isn't clear for the caller which exception may be thrown: All? Two of them? One only? I did this in the past, but stopped doing it. What do you opine?

Thank you.

Campbell Ritchie wrote:You should also consider what is right for your method, decide to do it, and /**write it down in the comments*/


Some years ago that's what I did. But I read some articles on the Internet that suggested to favour self-documented code (I believe that in this forum too). Indeed some of that articles used the throw of checked exceptions as a good example where you should be very concise with your code instead of throwing the parent class and commenting. What do you think?
 
Campbell Ritchie
Marshal
Posts: 56576
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What did you write in your documentation comments about Exceptions?
 
Avor Nadal
Ranch Hand
Posts: 156
Java Netbeans IDE Postgres Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:What did you write in your documentation comments about Exceptions?


I'm taking the previous example to illustrate it. In the part of the javadoc referred to StudentException I had written something like this:

 
Campbell Ritchie
Marshal
Posts: 56576
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In that case you are condemned to use those exceptions for ever. If you say, “throws StuentException if student is banned, fails to pay the bills or walks across professors' garden,— you have a lot more flexibility.
Look at List#get(). That says in the documentation that it might throw an IndexOutOfBoundsException, so let's look at an implementing class. The same method in ArrayList describes the same Exception, rather than ArrayIndexEtc. If you declared ArrayIndexEtcException, then you are declaring that your implementation uses an array and you are committed to arrays for ever. If you are vague about the Exception you can use it or any of its subtypes and add new conditions meriting Exceptions.
 
Avor Nadal
Ranch Hand
Posts: 156
Java Netbeans IDE Postgres Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:In that case you are condemned to use those exceptions for ever. If you say, “throws StuentException if student is banned, fails to pay the bills or walks across professors' garden,— you have a lot more flexibility.
Look at List#get(). That says in the documentation that it might throw an IndexOutOfBoundsException, so let's look at an implementing class. The same method in ArrayList describes the same Exception, rather than ArrayIndexEtc. If you declared ArrayIndexEtcException, then you are declaring that your implementation uses an array and you are committed to arrays for ever. If you are vague about the Exception you can use it or any of its subtypes and add new conditions meriting Exceptions.


But I believe that an exception called ArrayIndexOutOfBoundsException doesn't add any extra information about the cause with regard to IndexOutOfBoundsException, Right? I consider returning an IndexOutOfBoundsException enough informative in both cases. I believe that a similar case to mine could be FileNotFoundException and IOException. Some methods return the former instead of the later because it gives a more specific information about what caused the exception. Returning the latter, it's not so obvious (you need to check the documentation) and the caller can't take a different action depending on the type of exception that is thrown (or not so easily at least).

However, I see the point of what you're commenting. And although I had applied that strategy in the past, I had never thought about it in that way. It's interesting. It's like when you return an interface or super-class instead of the implementation, Right? I'm considering to use it again...

But I also would like knowing your opinion about the 3rd strategy of my first post. It consists in throwing an exception relative to the current context, not too specific, and attaching an enum to it, to be more specific about the cause. Some people (many really) create an exception for every possible cause. But if one doesn't create a class for every existing number, letter or file access mode, Why don't do the same with specific causes of exceptions? This strategy gives you the best of both "worlds": flexibility and a straight-forward way of knowing the possible cause.

SessionException would attach the enum SessionFailure.NOT_FOUND, SessionFailure.EXPIRED or SessionFailure.PERMISSION, whereas StudentException would attach StudentFailure.NOT_FOUND, StudentFailure.AGE_LIMIT or StudentFailure.BANNED.
 
Campbell Ritchie
Marshal
Posts: 56576
172
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[pedantic mode]Very few methods return an Exception. This is one. Many methods declare that they might throw an Exception.[/pedantic mode]

You are right: in your example and the ArrayList example, IndexOutEtcException provides enough information and there is no need to be more specific. Similarly about IOException and FileNotFoundException, though I suspect many methods declare IOException because it is not clear which Exceptions might occur.
Agree about specific information being added. When one says “cause” about Exceptions one often means a previous Exception which is being chained; many Exceptions can take another Exception as a constructor argument. Examples here: 1 2 3. You can read about Exception Chaining in the Java Tutorials. That is one way to add specific information. So you can add additional information to an Exception by:-
  • 1: Using its message field (good for human readers, bad for computers)
  • 2: Chaining an Exception as cause.
  • 3: Adding a code (int) as you see with SQLException
  • 4: Using an enum to encapsulate your error code.
  • There are doubtless many other ways to do that.
     
    Winston Gutkowski
    Bartender
    Posts: 10575
    66
    Eclipse IDE Hibernate Ubuntu
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Avor Nadal wrote:It consists in throwing an exception relative to the current context, not too specific, and attaching an enum to it, to be more specific about the cause.

    But if you're going to do that, why not simply throw a parent, and include the actual cause? Sounds to me like a solution to a problem that doesn't exist.

    I will say this however: I think it's VERY good that you're thinking about these things, so keep it up. Exceptions are tricky beasts, and it's easy to get them wrong. Java themselves have on several occasions.

    Winston
     
    Steve Fahlbusch
    Bartender
    Posts: 612
    7
    Mac OS X Python
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Well i was going to reply to the OP's original question as 42. :-)

    Anyway, i think that Campbell's response should be part of the FAQ page.
     
    Avor Nadal
    Ranch Hand
    Posts: 156
    Java Netbeans IDE Postgres Database
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:[pedantic mode]Very few methods return an Exception. This is one. Many methods declare that they might throw an Exception.[/pedantic mode]


    Touché XD .

    Campbell Ritchie wrote:Agree about specific information being added. When one says “cause” about Exceptions one often means a previous Exception which is being chained; many Exceptions can take another Exception as a constructor argument. Examples here: 1 2 3. You can read about Exception Chaining in the Java Tutorials.


    I was afraid that using the word "cause" could lead to confusion. I considered the definitions "origin of the error" or even "code of the error", but changed them at the last minute. Usually I've used the true "cause" argument when an exception is originated in another method, don't fit well in the current context, and needs to be chained with one that does. But for tasks like the one described here, where I create and throw the exception, I prefer the enum mechanism.

    It cheers me up to know that I'm not doing anything weird. Indeed my inspiration was the SQLException. But I chose an enum instead of a number to represent the "code" because it's more descriptive when you're writing code. Thank you for your help!

    Winston Gutkowski wrote:But if you're going to do that, why not simply throw a parent, and include the actual cause? Sounds to me like a solution to a problem that doesn't exist.


    I'm so used to utilize the "cause" argument to chain exceptions that have already been thrown by other methods, that I find it weird to chain an exception that has just been instantiated by myself. Maybe I'm doing a very personal use of the exception chaining, but if I've all the control over the exception creation, I prefer to attach a custom class as a property. I find it more natural.

    The fact that the method getCause () returns a java.lang.Throwable and doesn't support generics also influenced in my decision. I preferred something more concise or more specific of the exception thrown.

    The mistake in my message was that I called it "cause". I'm sorry. Really it's not the cause what I wanted to represent, but an identification or description of the exception itself. But not a textual one, because we've the "message" argument for that.
     
    Campbell Ritchie
    Marshal
    Posts: 56576
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Exceptions aren't parameterised anyway, so why does generics make any difference?
    There is a reason for using the word cause.I have no idea whether i & −1 can ever equal 456, but in that method the cause of the Exception is that equality. You are throwing an Exception because something == somethingElse.In this case the cause of the PQRException is the XYZException. You are throwing the new Exception because the old Exception has occurred.
     
    Avor Nadal
    Ranch Hand
    Posts: 156
    Java Netbeans IDE Postgres Database
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:Exceptions aren't parameterised anyway, so why does generics make any difference?


    One of my typical deliriums, he he he. I meant using generics to restrict the class of the exception that behaves as the cause. But after examining the situation, it's a no sense, because I still would need to analyse the class of the return of getCause () if I wanted to know what's the concrete cause. Definitively, I consider the enum the best way to represent the cause in my specific situation. Without abandoning the exception chaining in the rest of cases, of course.

    Campbell Ritchie wrote:There is a reason for using the word cause.


    I know, I know. I simply wanted to clarify that I was using the broadest meaning of the word "cause" in that situation.
     
    Campbell Ritchie
    Marshal
    Posts: 56576
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    You can restrict the type of Exception by something like that: public void foo(XYZException ex)… which confines the Exception to XYZException and its subtypes.

    You can use instanceof but that would make me suspect you are straying out of the confines of the object‑oriented world.
     
    Don't get me started about those stupid light bulbs.
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!