Return type vs throwing Exception

As it turns out, a quick search in google reveals that the issue of return type vs. exception is somewhat hotly contested, but I thought I'd check to see what people here thought, based on a particular example that I'm dealing with.

In an interface I've developed, I have the method:

publicboolean canNotify(....)

The problem with that method for me is that there's no way to enforce that an implementor provide a reason for failure. If the method call returnsfalse, it'd be nice to know for the future, either in a log, or programmatically, the exact reason why it failed. So there's two options for this:

(a) Response Object:

public NotifyResponse canNotify(....)

(b) Throw Exception:

publicvoid canNotify(....)throws WontNotifyException

Note that an int status code alone won't work in this particular case, because the reason why something failed should be logged with particular parameters. (for example, "won't notify because user is 12 and must be over 14")

The problem with a) is that you now suddenly have to create a response object every time, even if the method just needs to return "true". So there's a little bit (maybe a lot depending on the success vs failure rate) of object creation/object checking overhead.

The problem with b) is that throw clauses aren't required by implementors, so this isn't strictly enforcible. Implementors are basically left with this strange looking method that returns nothing. While it may bother some that b) uses exceptions to handle applicaiton logic flow, it doesn't bother me much in this particular example, since implementors won't be required to catch the exception -- the exception is handled appropriately by framework code.

Why do you think?

[1994 byte] By [nootcha] at [2007-10-2 22:52:20]
# 1

> The problem with a) is that you now suddenly have to

> create a response object every time, even if the

> method just needs to return "true". So there's a

> little bit (maybe a lot depending on the success vs

> failure rate) of object creation/object checking

> overhead.

>

I don't see this as a problem. In fact, you can have several static final immutable response objects such as OK object. I believe this is what most quality architectures do.

> The problem with b) is that throw clauses aren't

> required by implementors, so this isn't strictly

> enforcible. Implementors are basically left with

> this strange looking method that returns nothing.

> While it may bother some that b) uses exceptions to

> handle applicaiton logic flow, it doesn't bother me

> much in this particular example, since implementors

> won't be required to catch the exception -- the

> exception is handled appropriately by framework

> code.

>

I dont see that is a problem either. An exception should be exceptional. If there is no reason for it to be thrown it should not be. If you are suggesting that implementors merely will ignore throwing the exception and just dont perform the act, nothing you can do about that. Implementors can always violate the contract if they wish. Odd for implementors to want the program to not work though.

I don't think your problem approaches the issue of return type vs. throwing exception. You are defining the architecture and are free to do it either way. Architecturally speaking though, if you are only throwing this exception from one method, it seems bad.

Im currently toying with the idea that an exception should not be thrown unless you can think of some code that would go in the finally clause of the try-er.

_dnoyeBa at 2007-7-14 6:06:33 > top of Java-index,Other Topics,Patterns & OO Design...
# 2

It really depends on your design, I guess. I'd say: when I call a method that is called "canNotify()", I expect some kind of response.

Exceptions are meant to be ... well ... exceptional. They are not supposed as a substitute for signalling, they should only be used to handle rare situations.

So, from what you have written here, imho the most logical solution would be:

public boolean canNotify() throws NotifyNotDefinedException;

For most cases, this will just give you what you expect - either a yes or a no. But sometimes, when things go wrong, this method will give you additonal info with the exception, so that you can try to fix.

Exceptions have the benefit, that you don't have to analyze what exactly caused this error. A complex return object would need thorough analysis what might have gone wrong. With an exception you force the object to make this analysis itself.

Besides this, I totally agree to _dnoyeB: Every contract can easily be broken - no matter which agreements you make. The implementor can easily return just a "true" every time, even though it is not right. You can't force via declaration that only useful code can be written.

Mongera at 2007-7-14 6:06:34 > top of Java-index,Other Topics,Patterns & OO Design...
# 3

Thank you guys for your thoughtful responses.

In regards to implementors breaking a contract, I agree with you both there, but my question partially was more about which is the most "readable" contract. I find that if a contract requires a lot of instruction on how to use it, that perhaps the contract needs to be rethought.

I decided after coding it one way and then another to return a FilterResult object.

public FilterResult canNotify(...);

public class FilterResult {

public static final FilterResult OK = new FilterResult(true);

private boolean passed = false;

private String message;

/**

* Private constructor for single success object.

*

* @param didPass

*/

private FilterResult(boolean didPass) {

super();

passed = didPass;

}

/**

* Public constructor for failure objects.

*

* @param aMessage reason for failure

*/

public FilterResult(String aMessage)

{

message = aMessage;

}

public String getMessage()

{

return message;

}

}

This has the advantage of not needing to create OK objects when it's merely a success message (as _dnoyeB suggested) , but forcing users to provide an explanation (message) if the filter isn't passed.

nootcha at 2007-7-14 6:06:34 > top of Java-index,Other Topics,Patterns & OO Design...
# 4
there is a difference in execution of using try/catch and returning the result of an execution. if there is an exeption, the actual execution does not actually happen, while in the latter, once a result is returned, the actual execution has happened.
nootcha at 2007-7-14 6:06:34 > top of Java-index,Other Topics,Patterns & OO Design...