Interfaces and exceptions, best practice question

J

Jama

Greetings,

When I build my libraries, I code to interfaces, which is clearly a
best practice. When programmers then create classes that use my
interfaces, they complain that the exceptions they want to throw are
not defined in my signature. For example:

public interface myInterface {
public void instantiateThisMethod();
}

is no good. People want interfaces like:

public interface myInterface {
public void instantiateThisMethod() throws Exception;
}

This gives the implementing programmer flexibility to throw any
exception they want. So now, all my interfaces have "throws Exception"
tacked on the end of every signature.

Is this a bad idea? What's the proper approach to defining exception
handling with interfaces from a best practices point of view?

Thanks,
J
 
?

=?ISO-8859-15?Q?Tobias_Schr=F6er?=

Hi,
Greetings,

When I build my libraries, I code to interfaces, which is clearly a
best practice. When programmers then create classes that use my
interfaces, they complain that the exceptions they want to throw are
not defined in my signature. For example:

public interface myInterface {
public void instantiateThisMethod();
}

is no good. People want interfaces like:

public interface myInterface {
public void instantiateThisMethod() throws Exception;
}

This gives the implementing programmer flexibility to throw any
exception they want. So now, all my interfaces have "throws Exception"
tacked on the end of every signature.

Is this a bad idea? What's the proper approach to defining exception
handling with interfaces from a best practices point of view?

IMO, throws Exception is not a very good practise. It forces you to
explicitly catch all Exceptions, including RuntimeExceptions, which may
not be wanted.
In your case, I'd say, you define a own Exception class that can be used
by programmers to encapsulate their own Exceptions:

<code>
public class MyException extends Exception {
public MyException (String message) { super(message); }
public MyException (String message, Exception cause) {
super(message, cause); }
}
public interface MyInterface {
public void instantiateThisMethod() throws MyException;
}
</code>

In this way, users of you interface know what they must catch (checked
exception MyException).

However, if you define an interface, you should also define what
exceptions are thrown and in which cases a method will throw a checked
or a runtime exception, and of what type that exception will be.
Programmers will have to follow that contract.

Tobi.
 
C

chris brat

However, if you define an interface, you should also define what
exceptions are thrown and in which cases a method will throw a checked
or a runtime exception, and of what type that exception will be.

Are you saying include the runtime exceptions (those extending
java.lang.RuntimeException) in the throws clause too? Not necessary.
 
S

seb666fr2

Jama said:
Greetings,

When I build my libraries, I code to interfaces, which is clearly a
best practice. When programmers then create classes that use my
interfaces, they complain that the exceptions they want to throw are
not defined in my signature. For example:

public interface myInterface {
public void instantiateThisMethod();
}

is no good. People want interfaces like:

public interface myInterface {
public void instantiateThisMethod() throws Exception;
}

This gives the implementing programmer flexibility to throw any
exception they want.

In this case, the use of RuntimeException (by the implementing
programmer
) is better because you do not have to specify it in the throws clause.

So now, all my interfaces have "throws Exception" tacked on the end of
every signature.

Is this a bad idea?

If there is no reason for an abstract method to throw one or more
specific
exception, the use of RuntimeException by the implementing programmer
seems really better.
What's the proper approach to defining exception handling with interfaces
from a best practices point of view?

http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html


P.S: sorry for my bad english. :)
 
C

Chris Uppal

Jama said:
When I build my libraries, I code to interfaces, which is clearly a
best practice. When programmers then create classes that use my
interfaces, they complain that the exceptions they want to throw are
not defined in my signature.

That's a fundamental problem, which is inherent to the way Java uses interfaces
and checked exceptions. A throws clause is a promise (to the caller of the
method) that it will /NOT/ throw anything except the indicated exceptions (plus
unchecked ones). Not having a throws clause at all is a blanket promise not to
throw (checked) exceptions.

Personally, I have come to doubt the value of this kind of promise (or, more
accurately, come to doubt the value of having the compiler police it so
relentlessly), but that's the way Java works, so that's what we have to live
with.

So the question is, what kind of promise is it appropriate to impose on the
people implementing your interfaces ? It's a tricky design question. On the
one hand (as every user of Java's IO classes knows), having too many throwable
exceptions is a serious pain for the user of the interface. On the other hand
the people implementing the interfaces want as much freedom as possible. It's
your job to balance the conflicting interests.

I would tend to favour the users of the classes, myself. Unless the interface
is one that has an inherent (i.e. visible to any /user/ of the interface)
failure mode, then don't permit it to fail with a checked exception. If it
/does/ have such a failure mode (which is rather common, admittedly), then as
Tobias has already suggested, define your own exception class (which can be
subclassed by interface implementers) and declare that. If the developers
still complain then remind them that exceptions can be chained, and otherwise
ignore them ;-)

Also, don't forget the value of unchecked exceptions. There is nothing wrong
with using them -- provided you do it with discretion. They are appropriate
for anything that the user of the interface shouldn't be /forced/ to handle on
every call. That broad class of events includes failure modes which should be
found and eliminated by testing.

Whatever you do, don't declare "throws Exception" !

-- chris
 
?

=?ISO-8859-1?Q?Tobias_Schr=F6er?=

chris said:
Are you saying include the runtime exceptions (those extending
java.lang.RuntimeException) in the throws clause too? Not necessary.
No, that was not what I meant. But you can define what runtime
exceptions should be thrown, e.g. NullPointException, if the arguments
are null or IllegalArgumentException, if the arguments exceed the
allowed value boundaries.
Those things you can define in the javadoc. However, programmers can
throw any other runtime exception they want. But IMO it is a good advice
to follow those definitions (though they could not be forced) and users
know what to expect from a method.

Tobi
 
E

Ed Kirwan

Chris said:
failure mode, then don't permit it to fail with a checked exception. If it
/does/ have such a failure mode (which is rather common, admittedly), then as
Tobias has already suggested, define your own exception class (which can be
subclassed by interface implementers) and declare that. If the developers
still complain then remind them that exceptions can be chained, and otherwise
ignore them ;-)


Ooo, 'eck, I was about to make a bit of a tit of myself there. Might as
well post it for humility's sake.

I was about to take issue with the ancient and noble Chris and say that
it's no good advising to declare an interface with a method which throws
your own exception class, in the hope that interface implementors can
subclass that exception and throw their own, because, as the interface
method declares a specific exception, then this is the only type that
users of the interface implementations will see: they won't see subclasses.

I thought this was like passing a super-class to a method declared as
receiving a subclass: the method only sees the sublcass, and you have to
instanceof to see what super-class was actually passed in.

But I was wrong.

The code snippet below is prints, "I'm doing something really special."

Which now makes me see exception handling in a new light:
polymorphism-unfriendly. It's just another type of instaceof. Every time
a new interface implementation adds a new exception subclass, then all
users may be impacted (not necessarily, but it's possible).

Another nail in the coffin of exception-handling. (Perhaps that's too
strong a phrase. "Another exception for exception-handling?")




class SpecialException extends Exception {
void doSpecial() {
System.out.println("I'm doing something special");
}
}

class ReallySpecialException extends SpecialException {
void doReallySpecial() {
System.out.println("I'm doing something really special");
}

}

interface Munge {
public void hej() throws SpecialException;
}

public class Test implements Munge {
public static void main(String[] args) {
Munge munge = new Test();
try {
munge.hej();
} catch (ReallySpecialException e) {
e.doReallySpecial();
} catch (SpecialException e) {
e.doSpecial();
}
}

public void hej() throws SpecialException {
throw new ReallySpecialException();
}
}
 
D

Dimitri Maziuk

Chris Uppal sez:
.... If it
/does/ have such a failure mode (which is rather common, admittedly), then as
Tobias has already suggested, define your own exception class (which can be
subclassed by interface implementers) and declare that.

Unfortunately the promise is not just to "not throw anything
else", it's also to throw the declared one. That is, if you
declare a method as throwing MyException, the damn thing will
barf on an implementation that doesn't actually throw anything.

E.g. a data store with 3 different implementations: backed by
file (IOException wrapped inside MyException), DB (SQLException,
ditto), and in-memory store. Apart from an OOM (which you won't
catch/wrap anyway), the last one doesn't throw -- bummer.

Dima
 
E

Eric Sosman

Dimitri Maziuk wrote On 06/02/06 12:00,:
Chris Uppal sez:
... If it



Unfortunately the promise is not just to "not throw anything
else", it's also to throw the declared one. That is, if you
declare a method as throwing MyException, the damn thing will
barf on an implementation that doesn't actually throw anything.

E.g. a data store with 3 different implementations: backed by
file (IOException wrapped inside MyException), DB (SQLException,
ditto), and in-memory store. Apart from an OOM (which you won't
catch/wrap anyway), the last one doesn't throw -- bummer.

Would you mind clarifying what you mean by "the damn
thing will barf?" When an interface specifies that a
method might throw MyException, neither javac nor the
JVM complains about a method implementation that doesn't
throw it:

public class NotSo implements DataStore {
public void method() {
System.out.println("in method()");
}

public static void main(String[] unused)
throws MyException
{
DataStore store = new NotSo();
store.method();
}
}

class MyException extends Exception {}

interface DataStore {
public void method() throws MyException;
}
 
P

Patricia Shanahan

Jama said:
Greetings,

When I build my libraries, I code to interfaces, which is clearly a
best practice. When programmers then create classes that use my
interfaces, they complain that the exceptions they want to throw are
not defined in my signature. For example:

public interface myInterface {
public void instantiateThisMethod();
}

is no good. People want interfaces like:

public interface myInterface {
public void instantiateThisMethod() throws Exception;
}

This gives the implementing programmer flexibility to throw any
exception they want. So now, all my interfaces have "throws Exception"
tacked on the end of every signature.

Is this a bad idea? What's the proper approach to defining exception
handling with interfaces from a best practices point of view?

Thanks,
J

I think the process should start by an effort to determine what
exceptions a user of the interface should be expected to know about and
handle specifically. All of those should be documented with throws
clauses and @throws Javadoc comments.

It doesn't matter that some implementations may not throw all of them.
It does matter that the user of the interface needs to be prepared to
deal with any of them, and needs to know what they mean.

If there is a generic "something broke" condition that the
interface-user cannot do much about, there may be a case for the
implementer extending RuntimeException.

Throwing Exception from everything does not tell the user of the
interface anything about what to prepare for, or how to interpret
exceptions.

Patricia
 
P

Patricia Shanahan

Eric Sosman wrote:
....
Would you mind clarifying what you mean by "the damn
thing will barf?" When an interface specifies that a
method might throw MyException, neither javac nor the
JVM complains about a method implementation that doesn't
throw it:

There might be confusion with the rather annoying error message for
catching a non-Runtime exception that is not declared to be thrown in
try block.

try{}catch(IOException e){}

Patricia
 
E

Eric Sosman

Patricia Shanahan wrote On 06/02/06 17:00,:
Eric Sosman wrote:
...



There might be confusion with the rather annoying error message for
catching a non-Runtime exception that is not declared to be thrown in
try block.

try{}catch(IOException e){}

Yeah, I suppose. But then we get to the question
of whether he's calling the method through an interface
reference or through a class reference:

class Tantrum extends Exception {}
interface I { void method() throws Tantrum; }
class C implements I {
void method() {} // doesn't throw Tantrum
}
...
C cref = new C();
cref.method(); // can't catch Tantrum
...
I iref = cref;
iref.method(); // must catch Tantrum

In other words, he's gotta make a choice: use the
class as itself, or use it as an implementation of an
interface. Each route has its own requirements.
 
P

Patricia Shanahan

Eric said:
Patricia Shanahan wrote On 06/02/06 17:00,:

Yeah, I suppose. But then we get to the question
of whether he's calling the method through an interface
reference or through a class reference:

class Tantrum extends Exception {}
interface I { void method() throws Tantrum; }
class C implements I {
void method() {} // doesn't throw Tantrum
}
...
C cref = new C();
cref.method(); // can't catch Tantrum
...
I iref = cref;
iref.method(); // must catch Tantrum

In other words, he's gotta make a choice: use the
class as itself, or use it as an implementation of an
interface. Each route has its own requirements.

It's one of the few situations in which replacing the less specific with
the more specific requires other changes. Usually, you can change a
reference variable from an interface to an implementing class, or from a
class to one of its subclasses, with no other changes in the code.

In general, I think that check was a mistake. For some blocks of code, I
would like to write the catch clauses as a unit. It often can't be done,
because some exception handling is needed as soon as the first call is
coded, but the complete exception handling cannot be written until the
try block contains at least one call that throws each significant exception.

It also makes temporarily commenting out a call during test/debug more
complicated and error prone than it needs to to be, because some catch
clauses may also need to be commented out.

Patricia
 
C

Chris Uppal

Eric said:
Would you mind clarifying what you mean by "the damn
thing will barf?"

Changing the subject very slightly. I could've sworn I remembered Javac
refusing to compile code like:
void aMethod
throws SomeException
{
// code that doesn't throw anything
}
but a quick check shows it quite happy. Is my memory at fault, or has
something been fixed that I didn't notice.

-- chris
 
C

Chris Uppal

Ed said:
the ancient and noble Chris

Which now makes me see exception handling in a new light:
polymorphism-unfriendly. It's just another type of instaceof. Every time
a new interface implementation adds a new exception subclass, then all
users may be impacted (not necessarily, but it's possible).

I think there's a lot of truth in that. The hierarchy of exceptions isn't used
"normally" -- to structure sharing among polymorphically varying
implementations of some protocol(s) -- but to /categorise/ the exceptions.
Catch clauses are indeed "instanceof" in a short skirt and heavy makeup. What
they do is decode the categories at runtime (which is not in itself a bad
thing, IMO, it's just not lined up with the rest of Java's version of OO.)

Another indication that exception objects are not expected to be used as
normally polymorphic objects is that you can't use an interface type in a
throws declaration. (At least, I assume not -- I haven't tried it.) That's
not an issue that had struck me before, though I suspect you must have faced it
with your Factality tool.

-- chris
 
E

Eric Sosman

Chris said:
Eric Sosman wrote:




Changing the subject very slightly. I could've sworn I remembered Javac
refusing to compile code like:
void aMethod
throws SomeException
{
// code that doesn't throw anything
}
but a quick check shows it quite happy. Is my memory at fault, or has
something been fixed that I didn't notice.

I suspect Patricia Shanahan has hit on the explanation.
See her contributions to this thread.
 
D

Dale King

Chris said:
Changing the subject very slightly. I could've sworn I remembered Javac
refusing to compile code like:
void aMethod
throws SomeException
{
// code that doesn't throw anything
}
but a quick check shows it quite happy. Is my memory at fault, or has
something been fixed that I didn't notice.

Eclipse has a setting to generate an error or warning for that case and
a setting to allow it for cases where it overrides or implements a
method that does throw the exception.

Perhaps this is the source of your memory.
 
D

Dimitri Maziuk

Chris Uppal sez:
Changing the subject very slightly. I could've sworn I remembered Javac
refusing to compile code like:
void aMethod
throws SomeException
{
// code that doesn't throw anything
}
but a quick check shows it quite happy. Is my memory at fault, or has
something been fixed that I didn't notice.

Mee too, that's the reason I posted it in the first place. Looks like
something's got fixed indeed.

Dima
 
D

Dimitri Maziuk

Dimitri Maziuk sez:
Chris Uppal sez:

Mee too, that's the reason I posted it in the first place. Looks like
something's got fixed indeed.

Now I remember. With the above declaration, you have to catch
SomeException somewhere:

try { aMethod(); }
catch( SomeException e ) {}

is where it barfs. (Although "catch( Exception e )" is apparently
OK. Go figure.)

Dima
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top