Unless you are writing a really simple application that will not be extended in the future, write an exception of you own. A method that throws java.lang.Exception is pretty bad design; it does not provide any clues to the user about what might go wrong in the method call, also it forces the user of you API to catch all Exceptions.
> Unless you are writing a really simple application
> that will not be extended in the future, write an
> exception of you own. A method that throws
> java.lang.Exception is pretty bad design; it does not
> provide any clues to the user about what might go
> wrong in the method call,
You are applying a general case to specific instance without knowing any of the details.
The only time you should create a custom exception is when you believe it will be possible for someone to do something intelligent with it.
If I am creating an application that automatically moves data via a socket and that must move the data, then I don't care why the socket failed to connect. I am simply going to keep retrying until it does connect. In this case an Exception is perfectly acceptable.
On the other hand the same application might want to resolve the DNS name first and simply give up if it can't resolve it. But still continue if the connection timed out. In this case at least one custom Exception is needed to differentiate between the two failure paths.
Never create a custom exception unless you preceive a need to explicitly catch that exception.
> also it forces the user of
> you API to catch all Exceptions.
That is obviously non-sensical. Regardless of the checked exception being used, you still have to catch it.
> You are applying a general case to specific instance
> without knowing any of the details.
Indeed I am. However, generally speaking, a method that throws Exception is less-than-optimal design in an API. I will try to illustrate my point.
Throwing an Exception does not provide any clues to the user of your API about what might go wrong in the method call, while throwing an UnsupportedElementException certainly does. An UnsupportedElementException is much more informative to the user, while a plain Exception is not. A custom exception in this case is implicitly clear, even without consulting the Javadocs.
> The only time you should create a custom exception is
> when you believe it will be possible for someone to do
> something intelligent with it.
Are you always able to tell in advance whether the user of you API can do something intelligent with an exception? Can you make the supposition that the user can never do anything meaningful with the exceptions you throw? I am not convinced that you can, at least not in most of the cases.
> If I am creating an application that automatically
> moves data via a socket and that must move the data,
> then I don't care why the socket failed to connect. I
> am simply going to keep retrying until it does
> connect. In this case an Exception is perfectly
> acceptable.
>
> On the other hand the same application might want to
> resolve the DNS name first and simply give up if it
> can't resolve it. But still continue if the
> connection timed out. In this case at least one
> custom Exception is needed to differentiate between
> the two failure paths.
Agreed. And to make the API nice and neat, write two meaningful custom exceptions to differentiate the failures. :)
> Never create a custom exception unless you preceive a
> need to explicitly catch that exception.
Why not? (I am assuming that the Java API does not already have an exception that you can use.) The way I see it, there are three things you can do to handle and exception:
1) handle the exception and do not throw anything (this is the optimal solution, but often not feasible)
2) do nothing, just throw it (OK sometimes, can clutter up you methods if you need to throw several exceptions, also this can expose the implementation of you API to the outside world in some cases)
3) wrap the exception(s) in a custom exception (OK if you are not worried about exposing your implementation or if you have more than one fatal exceptions that the user can really do nothing about)
> > also it forces the user of
> > you API to catch all Exceptions.
>
> That is obviously non-sensical. Regardless of the
> checked exception being used, you still have to catch
> it.
I did not mean that you force the user of your API to write a try-catch -block, I meant that you force the user of your API to catch each and every exception that inherits from java.lang.Exception. Even RuntimeExceptions; and that can be a problem.
OK, I am getting carried away here. I would still suggest valjok to use a custom exception (UnsupportedElementException or whatever), because that way your method signature becomes pretty much self-explanatory.
Writing a custom exception takes like thirty seconds, it is worth the
effort.
> > You are applying a general case to specific
> instance
> > without knowing any of the details.
>
> Indeed I am. However, generally speaking, a method
> that throws Exception is less-than-optimal design in
> an API. I will try to illustrate my point.
>
> Throwing an Exception does not provide any clues to
> the user of your API about what might go wrong in the
> method call, while throwing an
> UnsupportedElementException certainly does. An
> UnsupportedElementException is much more informative
> to the user, while a plain Exception is not. A custom
> exception in this case is implicitly clear, even
> without consulting the Javadocs.
Which is all true if I am writing a library. But most people do not write libraries, they write applications. In applications either exceptions are part of the process flow (explicitly caught) or they are not. The vast majority are not part of the process flow.
>
> > The only time you should create a custom exception
> is
> > when you believe it will be possible for someone to
> do
> > something intelligent with it.
>
> Are you always able to tell in advance whether the
> user of you API can do something intelligent with an
> exception? Can you make the supposition that the user
> can never do anything meaningful with the exceptions
> you throw? I am not convinced that you can, at least
> not in most of the cases.
One should never ever design or code solely based on the "hope" that sometime in the future someone "might" need it. Doing that leads to code bloat, code that is hard to understand and worst of all code that is never tested.
So unless there is a known need a special exception should not be created.
>
> > If I am creating an application that automatically
> > moves data via a socket and that must move the
> data,
> > then I don't care why the socket failed to connect.
> I
> > am simply going to keep retrying until it does
> > connect. In this case an Exception is perfectly
> > acceptable.
> >
> > On the other hand the same application might want
> to
> > resolve the DNS name first and simply give up if it
> > can't resolve it. But still continue if the
> > connection timed out. In this case at least one
> > custom Exception is needed to differentiate between
> > the two failure paths.
>
> Agreed. And to make the API nice and neat, write two
> meaningful custom exceptions to differentiate the
> failures. :)
Nope. Again that is fine for a library. It is not needed for an application. An application has a purpose which is defined by the requirements. Adding stuff when there is neither a current requirement or when there is no expected future requirement is a bad idea.
I have yet to meet a developer who can accurately predict the future. I have however met many who thought there code could be generalized for many possible imaginary cases that they conceived in their mind.
And all that extra code is never tested by QA (because there are no requirements) and causes maintenance problems down the road because it is not part of the documented infrastructure.
> > > also it forces the user of
> > > you API to catch all Exceptions.
> >
> > That is obviously non-sensical. Regardless of the
> > checked exception being used, you still have to
> catch
> > it.
>
> I did not mean that you force the user of your API to
> write a try-catch -block, I meant that you force the
> user of your API to catch each and every exception
> that inherits from java.lang.Exception. Even
> RuntimeExceptions; and that can be a problem.
>
I have no idea what you are trying to express there.
A checked exception must be caught regardless of what type of checked exception it is. The user might break it out but only if the user expects to do something with a specific type of exception.
>> I did not mean that you force the user of your API to
>> write a try-catch -block, I meant that you force the
>> user of your API to catch each and every exception
>> that inherits from java.lang.Exception. Even
>> RuntimeExceptions; and that can be a problem.
>>
>
>I have no idea what you are trying to express there.
>
>A checked exception must be caught regardless of what type of checked
>exception it is. The user might break it out but only if the user expects
>to do something with a specific type of exception.
Correct, but catch(Exception e) {}
will catch all Exceptions that are a subclass of Exception. And this includes the usually unchecked RuntimeExceptions.
Therefor, by throwing an Exception, you are forced to either catch RuntineExceptions (like NullPointerExceptions, etc) or to not catch the Exception at all.
That's why IMO you should never declare a method that trows Exception.
However, I agree with you that custom Exceptions can be a pain too. But there are the subclasses of Exception that can be used.
e.g. as this Problem has to do with Input, a java.io.IOException may be suffisant. Or use java.text.ParseException which is even more specific.
Generally I agree with you that custom Exceptions should only be used when you write a library, or when your application is so big, that one part uses the other like a library (and is developped by another team).
Else, use the standard java Exception that most fit your needs.
But never throw Exception itself, to avoid forcing the catch of RuntimeExceptions.
Ok, I understand what you were referring to there.
Let me provide this example...
In a client server application (J2EE) the client, the GUI, talks to the back end.
The back end can throw the following exceptions:
1. Communication failure with the backend
2. Communication failure with the database.
3. SQL error (something wrong with SQL in the database.)
4. Null pointer exception (the back end code failed.)
Now the GUI should never exit for any of the above errors.
For exception 1, the GUI should attempt to reconnect to the back end automatically and then give the user the option to keep retrying.
For all of the other exceptions the GUI should tell the user that there is a problem and then let the user decide what to do.
Now for problem 2 above the user might just try again. That is up to the user. Note that this is not the same problem as failure to commnicate with the back end. It requires action that is outside the bounds of the application (maybe the user needs to call the DBA.) But the use might opt to just try again (maybe after calling the DBA.)
For 3 and 4 nothing the user does is going to fix the problem. Even so the application should never exit. It should tell the user the problem in the hope that the user might report it to someone to fix it.
So the exception will be caught. And all of the exceptions will be caught. And except for the first one there is absolutely no reason to use a custom exception. The reason for using a custom exception for the first one is because the system is going to specifically take action on that exception. That is the only reason it exists. If it wasn't going to automatically retry then it would not need to exist.
And there is never any case in which 3 and 4 will ever require any other action. There is simply no way for the system to correct the problem. And for case 2 is is extremely unlikely because the backend should have already retried the connect (or based on requirements decided that was pointless.) There is no need to retry.
On the other hand you might be building a northend interface of which the GUI is only one possible northend client. As such then a retry on a database failure "might" be needed due to future requirements. But if you are building a system like that then you already know that automated systems might be connecting and would need to retry. Again 3 and 4 will never need special action. They are always failure cases. As such a special exception is never needed and never will be needed.
Thanks phohmeyer, that is exactly what I was going after when I said throwing java.lang.Exception is bad.
I would like to offer another point of view into "writing an application" versus "writing a library (an API)": I do not really see that much of a difference between the two.
The signature of a method is the API for that method. Several methods comprise the API for a class, and several classes... You get the picture. Most pieces of (object-oriented) Java-software comprise several classes that interact with each other. Between each interaction there is, essentially, an API.
Now, I agree with phohmeyer that custom exceptions should only be used when your application is so big that one part uses the other like a library. However, I would consider an application of 10 classes (maybe 10-500 lines of code to a class) to be an application sufficiently big to warrant "API-like design" (I would rather just call it "design".)
Of course if you are writing a library to be used by a customer/3rd party, you have to take extra special care in designing the API.
> > Throwing an Exception does not provide any clues to
> > the user of your API about what might go wrong in the
> > method call, while throwing an
> > UnsupportedElementException certainly does. An
> > UnsupportedElementException is much more informative
> > to the user, while a plain Exception is not. A custom
> > exception in this case is implicitly clear, even
> > without consulting the Javadocs.
>
> Which is all true if I am writing a library. But most
> people do not write libraries, they write
> applications.
You may have a point.
I would say that 99% of all Java code I have ever written was a library to be used either by myself later on or by another person. Perhaps this is because I am getting paid for writing almost exclusively server-side Java? I have written few desktop applications, actually.
> > > The only time you should create a custom exception is
> > > when you believe it will be possible for someone to do
> > > something intelligent with it.
> >
> > Are you always able to tell in advance whether the
> > user of you API can do something intelligent with an
> > exception? Can you make the supposition that the user
> > can never do anything meaningful with the exceptions
> > you throw? I am not convinced that you can, at least
> > not in most of the cases.
>
> One should never ever design or code solely based on
> the "hope" that sometime in the future someone "might"
> need it. Doing that leads to code bloat, code that is
> hard to understand and worst of all code that is never
> tested.
I am with you on this 100%. Actually, that is the other side of the coin of my point; you cannot foresee the future, therefore:
1) do not code anything based on hope that sometime in the future someone might need it (You Ain't Gonna Need It, Keep It Simple, Stupid)
2)
> > Agreed. And to make the API nice and neat, write two
> > meaningful custom exceptions to differentiate the
> > failures. :)
>
> Nope. Again that is fine for a library. It is not
> needed for an application. An application has a
> purpose which is defined by the requirements. Adding
> stuff when there is neither a current requirement or
> when there is no expected future requirement is a
> bad idea.
Sheesh. I we both got a little sidetracked here, or something. In any case, I am getting confused. What I meant with "making the API nice and neat" is this:
This is better:
public void moveData(Data someData) throws SocketException, DNSException {
...
}
Than this:
public void moveData(Data someData) throws Exception, DNSException {
...
}
It was not my intention to imply anything else.
> I have yet to meet a developer who can accurately
> predict the future. I have however met many who
> thought there code could be generalized for many
> possible imaginary cases that they conceived in their
> mind.
Me too. However generalization is not what I am going after for, maintainability, readability and robustness are (insert buzzword-laden zealot-speech here). I did not mean that you should implement or design extra **** into your code/architecture/whatever.
> And all that extra code is never tested by QA (because
> there are no requirements) and causes maintenance
> problems down the road because it is not part of the
> documented infrastructure.
Er... yes. With "extra code" I still am thinking about the difference between "throws Exception" and "throws UnsupportedElementException".
Dang, I actually managed to click "Post!" instead of "Preview". Here's the part that is missing from the middle of my post:
I am with you on this 100%. Actually, that is the other side of the coin of my point; you cannot foresee the future, therefore:
1) do not code anything based on hope that sometime in the future someone might need it (You Ain't Gonna Need It, Keep It Simple, Stupid)
2) if possible, and if its not a clear-cut case, try not to make a decision about what to do with exception in your class if, you can delegate the decision making to the user of your class
>
> I would say that 99% of all Java code I have ever
> written was a library to be used either by myself
> later on or by another person. Perhaps this is because
> I am getting paid for writing almost exclusively
> server-side Java? I have written few desktop
> applications, actually.
>
As do I. I don't even know how to do java GUIs. However all of the code that I write is used in applications. The library itself is not the end product. Nor is it a general purpose library that will be used in many applications for a company.
A library is code set that is either a product itself or is used in many products in a company. But for the last to work (in general) the company must have a very strong reuse process. That last part is important because there are many companies which promote reuse, but without a reuse process the followup is meaningless - developers end up coding to what "might" happen.
> > I would say that 99% of all Java code I have ever
> > written was a library to be used either by myself
> > later on or by another person. Perhaps this is because
> > I am getting paid for writing almost exclusively
> > server-side Java? I have written few desktop
> > applications, actually.
>
> As do I. I don't even know how to do java GUIs.
> However all of the code that I write is used in
> applications. The library itself is not the end
> product. Nor is it a general purpose library that
> will be used in many applications for a company.
Precisely.
> A library is code set that is either a product itself
> or is used in many products in a company. But for the
> last to work (in general) the company must have a very
> strong reuse process. That last part is important
> because there are many companies which promote reuse,
> but without a reuse process the followup is
> meaningless - developers end up coding to what "might"
> happen.
Indeed. And everything results from the simple mistake of promoting OO as "reusable". OO may enable reusability, bit sure as hell does not guarantee it automatically!
*grumbling* *whining* Now where did I put that flaming sword of mine?
I believe that my point boils down to this:
Every class and every method inside a major application should be designed with care ("as an API", not "as a quick hack/fix/the first thing that works").
Of course the design should not be taken to the extent of designing a public API. Analysis paralysis is bad. So is object-oriented overkill. And over-engineering.
>
> I believe that my point boils down to this:
> Every class and every method inside a major
> application should be designed with care ("as an API",
> not "as a quick hack/fix/the first thing that
> works").
>
> Of course the design should not be taken to the extent
> of designing a public API. Analysis paralysis is bad.
> So is object-oriented overkill. And over-engineering.
Exactly. Which is why my backends typically end up with just one or two new exceptions. One exception is for denotes back end connectivity. It allows the caller to imply retry logic if connectivity failed. And I only do this when I know a caller will need to do this. This is the case where I know that the front end needs to deal with something is a special way. (Actually this is only needed when I know that there are at least two front ends and each needs to deal with retries in a different way.)
The other exception exists solely to prevent backend exceptions from being propogated to the front end(s.) It wraps everything else. In particular I strip "custom" exceptions because the front end shouldn't have to drag in eight third party libraries just so it can resolve a nested exception tree. The exceptions come from different places but that does not matter to the front end(s.) All that matters to them is that something went wrong.