Exception Handeling
Hi
Lets have a look at this example.
public interface MyInterface {
public voidinit() throws MyException;
}
public class MyClassImpl implementsMyInterface {
public voidinit(){
//Not throwing MyException
}
}
Is it a good practice that theMyException should not be thrown in the init() of the implemented class(MyClassImpl )?
# 1
No. The interface is a contract, and classes implementing that interface are promising to fulfill that contract. Exceptions are a part of that contract. If the underlying class has no need to throw that exception, it isn't really an implementation of the interface
If people using this API code to the interface - which they should - but the implementation does not throw this exception, they will be writing a bunch of exception handling code for no reason.
# 2
No, I disagree. The Null pattern is a good counter example to your argument (e.g., a valid and useful implementation that does not throw the exceptions defined in the interface). http://www.exciton.cs.rice.edu/JAvaResources/DesignPatterns/NullPattern.htm
# 3
The question is whether it is a bad practice or not. It is a crappy practice, in my opinion, based on what george says above.
There can be examples that exist that do otherwise and they may work fine. However, as a "practice" it should be avoided.
If there is a vaild reason, based on business requirements or technical requirements, that indicates to design in such a fashion. Then an exception is made, and you implement the "crappy practice". Make sure you note in the JavaDoc comments that this is an implementation based on a crappy practice and state the requirements that govern this decision.
# 4
no, again, think about it some more...
The interface is a contract, and classes implementing that interface are promising to fulfill that contract
Sure, that makes sense on the surface.... but does it mean that any implementation that does not implement an interface method completely is "crappy practice"?
That would mean the Adaptor pattern is crappy practice.
-> Adaptors do not throw the exceptions in the interface methods, they do not even implement the methods. So Adaptors are totally crappy practice and should be avoided?
Now consider the converse, how about throwing checked exceptions that are not defined in the interface?
Here is a quote from the javadoc on Throwable:
http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Throwable.html
A second reason that a throwable may have a cause is that the method that throws it must conform to a general-purpose interface that does not permit the method to throw the cause directly. For example, suppose a persistent collection conforms to the Collection interface, and that its persistence is implemented atop java.io. Suppose the internals of the put method can throw an IOException. The implementation can communicate the details of the IOException to its caller while conforming to the Collection interface by wrapping the IOException in an appropriate unchecked exception. (The specification for the persistent collection should indicate that it is capable of throwing such exceptions.)
So there are a bunch of examples of real-world problems where implementations do not throw the exceptions defined in the interface (Null pattern and the Adaptor pattern), and an example where the implementation throws exceptions not defined in the interface (a Collection that throws IOException wrapped in RuntimeException).
I'd like to see how you would tackle these issues without reverting to such "crappy practices".
# 5
The are exceptions to almost every rule. Whether an implementation throws and exception or not is a small implementation detail. If you racked your brain over every detail and tried to follow every rule, you would hardly work efficiently.
That said, to force users of an API to code for exceptions when implementations never throw them is a bad practice in my opinion, and introduces uneccessary code.
The more important point here is that Exceptions should not cross tier boundaries, e.g. your business tier implementation should never return an Exception to the Presentation tier. Only data should be sent upward.
# 6
> That said, to force users of an API to code for
> exceptions when implementations never throw them is a
> bad practice in my opinion, and introduces
> uneccessary code.
It sounds like you're assuming that any and all implementations will not throw this exception. The OP did not define the problem beyond a single implementation, so in the short term, I follow your point. However, I see no problem in declaring an exception that other implementations may throw.
Santosh_Mohanty, by declaring a checked exception, you're forcing the client to deal with a condition that could (and is likely) to occur. If this is not the case, and most or all of your implementations will *not* throw this exception, then the existence of the exception needs to be reconsidered.
> The more important point here is that Exceptions
> should not cross tier boundaries, e.g. your business
> tier implementation should never return an Exception
> to the Presentation tier. Only data should be sent
> upward.
I disagree with this statement. Exceptions are used to indicate a condition that interrupted the normal flow of the application. A lot of these exceptions can be caught and handled by user input. For instance, how about an exception in a browser when the target url refers to a server that is down, or the connection was interrupted. "Would you like to try again?"
# 7
> I disagree with this statement. Exceptions are used
> to indicate a condition that interrupted the normal
> flow of the application. A lot of these exceptions
> can be caught and handled by user input. For
> instance, how about an exception in a browser when
> the target url refers to a server that is down, or
> the connection was interrupted. "Would you like to
> try again?"
"A lot of these". What exceptions are you referring too?
In your example, an "exception in a browser" is a Presentation tier Exception. Would you send the Exception down to the Business tier for processing or would you handle the exception on the Presentation tier?
# 8
> "A lot of these". What exceptions are you referring
> too?
The point I was trying to make was that Exceptions are not evil objects that need to be hidden or thrown away. Many exceptions can be handled with user intervention and it's not bad design to allow exceptions to ascend tiers. Granted you might want to wrap low-level exceptions with ones that make more sense with your higher-level requirements.
> In your example, an "exception in a browser" is a
> Presentation tier Exception.
I'm not sure what you mean by "presentation tier exception". In this hypothetical browser application, I would assume that the connection logic would not reside in the presentation tier. So a connection failed exception would originate from a tier lower than the presentation.
> Would you send the
> Exception down to the Business tier for processing or
> would you handle the exception on the Presentation
> tier?
This is a good design question. One that I believe deserves its own forum topic, as it does not directly relate to the OP. If you do create a new topic, please post the link here.
# 9
> > "A lot of these". What exceptions are you
> referring
> > too?
>
> The point I was trying to make was that Exceptions
> are not evil objects that need to be hidden or thrown
> away.
I agree. The Java Exception mechanism is a great feature of the language and when used appropriately, can help designers create robust, adaptive software designs with high levels of manageability and performance.
> Many exceptions can be handled with user
> intervention and it's not bad design to allow
> exceptions to ascend tiers. Granted you might want
> to wrap low-level exceptions with ones that make more
> sense with your higher-level requirements.
Sending exceptions upwards is poor design, in my opinion. Only data should be send upward. Here is a scenario.
1. If we design the Presentaion tier to deal with incoming Java Exceptions.
2. If we design the Business tier to send Java Exceptions upwards.
3. How would you replace or add a new non-Java presentation format to the application? Would recoding the business logic be required? Would you have to recode and recompile and retest the business classes?
How would you handle the Java Exceptions in this case?
# 10
Only data should be send upward
How do you indicate error conditions to the upper layers?
How would you replace or add a new non-Java presentation format to the application?
I'm not familiar with the problem you're trying to solve. Would you mind elaborating a little on the non-Java presentation format?
# 11
> How do you indicate error conditions to the upper
> layers?
See above.
> I'm not familiar with the problem you're trying to
> solve. Would you mind elaborating a little on the
> non-Java presentation format?
The goal is to maintain low coupling between the tiers, both at a application and technology standpoint. For instance, the main purpose of the DAO pattern is to encapsulate the implementation on the Integration tier and shield its details from the business application on the Business tier. If applied correctly, the code in the business application would never have to be change or modified it the RDBMS was switched from SQL Server to Oracle. Or if a switch was made from Oracle to a fancy new XML/Object database.
A GUI writtern in C++ would be a non-Java presentation format. A GUI written in Ruby would be a non-Java presentation format.
So, say at some point you wanted to integrate the business application and integrate with a partner's existing application, which by the way has a Ruby of Rails GUI. If the business application is sending Java Exceptions upwards, then you could not easily snap on a new presentation without recoding, recompiling and retested the business classes.
Sending Java Exceptions upwards is bad news and increases the coupling levels between the tiers.
# 12
I'm not sure how you would handle the interop with C++. Perhaps you *would* need an adhoc method for handling error conditions. Ruby on Rails, however, is a web framework and would interop quite nicely with Web Services (which support exceptions).
Do you have a layer between the business rules and the C++ / Ruby interop to handle the platform differences? Don't you think that would be a good spot to handle Java's exceptions and convert them to something C++ / Ruby would understand?
I don't see why the business layer would need to be modified in any case. The Business layer happily throws exceptions as error conditions arise and the consumer is responsible for handling them (logging, prompting the user, transforming into Ruby, etc).
# 13
> public void init() throws MyException;
>
> Is it a good practice that the MyException
> should not be thrown in the init() of the implemented
> class(MyClassImpl )?
Two interpretations
1. In terms of interfaces and "initialization" is a good practice to design the interface to deal with the possibility that an exception might occur during initialization.
Yes.
Presuming that it reasonable that not implementations are known when the interface is designed then yes it should allow for this.
By reasonable I don't mean that one should allow for all possible universes but rather have an idea of the current implementations and possible future ones.
--2. Is is a good practice to ignore (not use/implement) exceptions even though they are part of the interface.
No. If the method can create an error condition then it needs to throw an the exception.
On the other hand during implementation it might be the case that 9 out of the 10 implementations do not need to throw the exception. Only the 10th does.
In that case it would be ridicolous to artificially produce a state where the 9 throw the exception. Conversely one must allow for the exception because the 10th class requires it.
And the users must deal with that possibility.
# 14
> I'm not sure how you would handle the interop with
> C++. Perhaps you *would* need an adhoc method for
> handling error conditions. Ruby on Rails, however,
> is a web framework and would interop quite nicely
> with Web Services (which support exceptions).
I never mentioned Web Services anywhere. My example is a POJO business model. I didn't imagine that you would know how to easily swap a Java-based GUI with a C++ GUI.
> Do you have a layer between the business rules and
> the C++ / Ruby interop to handle the platform
> differences?
No. My theoretical example is to illustrate why Java Exceptions should not cross the boundary of the Business tier and Presentation tier.
> Don't you think that would be a good
> spot to handle Java's exceptions and convert them to
> something C++ / Ruby would understand?
>
Nothing to handle because the example was designed not to throw exceptions from the Business tier.
> I don't see why the business layer would need to be
> modified in any case. The Business layer happily
> throws exceptions as error conditions arise and the
> consumer is responsible for handling them (logging,
> prompting the user, transforming into Ruby, etc).
Yes, Java exceptions can happily be thrown within the Business tier. Objects can throw exceptions at each at will. Objects should never throw Exceptions upward.
Basically, you don't understand this design principle. So, there is not much more to say.
For new readers, process commands go downward, data (only) goes upward. This is a fundamental fundamental.
# 15
>
> Basically, you don't understand this design
> principle. So, there is not much more to say.
>
> For new readers, process commands go downward, data
> (only) goes upward. This is a fundamental fundamental.
I can only note that although that might have utility in some cases it is seldom used.
Certainly nothing from the OP would suggest that this would be appropriate.
# 16
> Nothing to handle because the example was designed
> not to throw exceptions from the Business tier.
>
>
> Basically, you don't understand this design
> principle. So, there is not much more to say.
>
> For new readers, process commands go downward, data
> (only) goes upward. This is a fundamental fundamental.
I don't fully understand your point of view. What if your GUI language doesn't support java enums, templates, ints or collections, or whatever else? Surely, interoperability cannot be the reason why you think that exceptions shouldn't be thrown upward?
And if you are saying "never indicate errors upward", how are you supposed to deal with those exceptions that do occur? Log and return? If what you're saying is true, there is no way for the UI-layer to indicate errors. This could become quite humerous; http://forums.worsethanfailure.com/forums/thread/121878.aspx
Is this what you are saying? No error-codes or exceptions or messages upward? How is that good design? I would say that it forces you into a lot of copy-paste coding and/or wierd ad-hoc exception handling.
If some web-layer guys screw up in their javascript validation, it's nice to be able to bounce back some human readable error from the backend. Would you consider this bad practice?
So, what i'm saying is that
public void registerTransaction(Transaction t) throws UnableToProcessException;
is nice to do in order to give info to clients.
Opinions?
# 17
> Sending exceptions upwards is poor design, in my
> opinion. Only data should be send upward. Here is a
> scenario.
Nonsense.
If my Java-based browser can't connect to a website, I want to know about it. Now, I as the user to not want to see the exception per se, but some exception needs to bubble up from new Socket(...) to the presentation layer, which will then couch that in appropriate terms for the user--e.g. a "could not connect, try again?" dialog.
jverda at 2007-7-21 21:36:09 >

# 18
> Hi
>
> Lets have a look at this example.
>
> public interface MyInterface {
> public void init() throws MyException;
> }
>
> public class MyClassImpl implements
> MyInterface {
> public void init(){
> //Not throwing MyException
> }
> }
>
> Is it a good practice that the MyException
> should not be thrown in the init() of the implemented
> class(MyClassImpl )?
I'll assume that it was reasonable to declare that the interface can throw that exception--that it indicates something that could go wrong in a reasonable or normal implementation of that interface.
Now, if a particular implementation can be made to never throw that exception, then it's perfectly fine for the implementation not to declare it. In fact, the compiler won't let you declare a checked exception that's never thrown. (Although if it's an interface implementation or a subclass overriding a superclass' method that throws it, I think it may just be a warning.)
jverda at 2007-7-21 21:36:09 >

# 19
> No. The interface is a contract, and classes
> implementing that interface are promising to fulfill
> that contract. Exceptions are a part of that
> contract. If the underlying class has no need to
> throw that exception, it isn't really an
> implementation of the interface
I disagree.
The throws part of the contract doesn't say "I promise to throw this." Rather, it says, "I promise not to throw any checked exceptions except for this (and its descendants)."
The throws clause says what could go wrong. It doesn't mean that it always will, or that all implementations are susceptible to that problem.
jverda at 2007-7-21 21:36:09 >

# 20
> I don't fully understand your point of view. What if
> your GUI language doesn't support java enums,
> templates, ints or collections, or whatever else?
> Surely, interoperability cannot be the reason why you
> think that exceptions shouldn't be thrown upward?
It is understandable why you don't understand the point of view. You would have to have read the other thread about exceptions and all of this threads posts.
Code from Controller on Presentation tier:
int results = 0;
results= bus.addNewContact(data);
if (results==1){
log.info("There was a problem using saving this contact record.");
return (mapping.findForward("exception"));
}
Code from Business Delegate on Presentation tier:
public int addNewContact(Contact c) {
return CRMMngr.addNewContact(c);
}
Code from Business object on Business tier:
public int addNewContact(Contact c) {
int results = 0;
try {
// Start Hibernate Transaction
hibernateSession.beginTransaction();
hibernateSession.save(c);
hibernateSession.getTransaction().commit();
...
In this example, no Java Exceptions or Object is sent upwards. Only primitive int.
# 21
> In this example, no Java Exceptions or Object is sent
> upwards. Only primitive int.
That's great if this is the layer that's specifically intended to go between your Java code and some non-Java client layer that doesn't understand Java exceptions. Eschewing the exception mechanism in favor of return codes because some non-Java client might want to use this layer is silly.
jverda at 2007-7-21 21:36:09 >

# 22
> > In this example, no Java Exceptions or Object is
> sent
> > upwards. Only primitive int.
>
> That's great if this is the layer that's specifically
> intended to go between your Java code and some
> non-Java client layer that doesn't understand Java
> exceptions. Eschewing the exception mechanism in
> favor of return codes because some non-Java client
> might want to use this layer is silly.
Agreed. My point was that the ad-hoc "integer exception pattern" doesn't really serve any purpose, it's identical to the native exception solution.
# 23
> Agreed. My point was that the ad-hoc "integer> exception pattern" doesn't really serve any purpose,> it's identical to the native exception solution.How is it identical? You're allowed to create code that doesn't even acknowledge the "integer
jverda at 2007-7-21 21:36:09 >

# 24
> How is it identical? You're allowed to create code
> that doesn't even acknowledge the "integer
> exceptions."
What I mean is that the two methods are not conceptually different, just two different implementations of the same idea, where one is less efficient and flawed (the integer one). Ergo, why not just stick with the implementation shipped with the JVM?