Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / June 2006

Tip: Looking for answers? Try searching our database.

Interfaces and exceptions, best practice question

Thread view: 
Jama - 02 Jun 2006 07:38 GMT
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
Tobias Schröer - 02 Jun 2006 10:40 GMT
Hi,

Jama schrieb:
> Greetings,
>
[quoted text clipped - 19 lines]
> 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.
chris brat - 02 Jun 2006 11:00 GMT
> 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.
Tobias Schröer - 02 Jun 2006 11:44 GMT
chris brat schrieb:
>>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.

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
seb666fr2@yahoo.fr - 02 Jun 2006 11:09 GMT
> Greetings,
>
[quoted text clipped - 15 lines]
> 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. :-)
Chris Uppal - 02 Jun 2006 11:39 GMT
> 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
Ed Kirwan - 02 Jun 2006 13:34 GMT
> 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 ;-)

>     -- chris

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();
    }
}

Signature

www.EdmundKirwan.com - Home of The Fractal Class Composition.

Download Fractality, free Java code analyzer:
www.EdmundKirwan.com/servlet/fractal/frac-page130.html

Chris Uppal - 03 Jun 2006 12:03 GMT
> the ancient and noble Chris

<grin/>

> 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
Dimitri Maziuk - 02 Jun 2006 17:00 GMT
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
Signature

I'm going to exit now since you don't want me to replace the printcap. If you
change your mind later, run                        -- magicfilter config script

Eric Sosman - 02 Jun 2006 18:10 GMT
Dimitri Maziuk wrote On 06/02/06 12:00,:
> Chris Uppal sez:
> ...  If it
[quoted text clipped - 12 lines]
> 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;
    }

Signature

Eric.Sosman@sun.com

Patricia Shanahan - 02 Jun 2006 22:00 GMT
...
>     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
Eric Sosman - 02 Jun 2006 22:23 GMT
Patricia Shanahan wrote On 06/02/06 17:00,:
> ...
>
[quoted text clipped - 9 lines]
>
> 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.

Signature

Eric.Sosman@sun.com

Patricia Shanahan - 02 Jun 2006 23:03 GMT
> Patricia Shanahan wrote On 06/02/06 17:00,:
>> ...
[quoted text clipped - 30 lines]
> 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
Chris Uppal - 03 Jun 2006 10:58 GMT
>     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
Eric Sosman - 03 Jun 2006 13:50 GMT
>>    Would you mind clarifying what you mean by "the damn
>>thing will barf?"
[quoted text clipped - 8 lines]
> 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.

Signature

Eric Sosman
esosman@acm-dot-org.invalid

Dale King - 04 Jun 2006 03:56 GMT
>>     Would you mind clarifying what you mean by "the damn
>> thing will barf?"
[quoted text clipped - 8 lines]
> 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.
Signature

 Dale King

Dimitri Maziuk - 05 Jun 2006 19:22 GMT
Chris Uppal sez:

>>     Would you mind clarifying what you mean by "the damn
>> thing will barf?"
[quoted text clipped - 8 lines]
> 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
Signature

We're sysadmins. Sanity happens to other people.                  -- Chris King

Dimitri Maziuk - 06 Jun 2006 04:28 GMT
Dimitri Maziuk sez:
> Chris Uppal sez:
>>
[quoted text clipped - 13 lines]
> 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
Signature

I have not been able to think of any way of describing Perl to [person]
"Hello, blind man?  This is color."                                      -- DPM

Patricia Shanahan - 02 Jun 2006 19:14 GMT
> Greetings,
>
[quoted text clipped - 22 lines]
> 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


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.