Interfaces and exceptions, best practice question

Discussion in 'Java' started by Jama, Jun 2, 2006.

  1. Jama

    Jama Guest

    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
     
    Jama, Jun 2, 2006
    #1
    1. Advertising

  2. Hi,

    Jama schrieb:
    > 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.
     
    =?ISO-8859-15?Q?Tobias_Schr=F6er?=, Jun 2, 2006
    #2
    1. Advertising

  3. Jama

    chris brat Guest


    > 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.
     
    chris brat, Jun 2, 2006
    #3
  4. Jama

    Guest

    Jama wrote:
    > 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. :)
     
    , Jun 2, 2006
    #4
  5. Jama

    Chris Uppal Guest

    Jama wrote:

    > 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
     
    Chris Uppal, Jun 2, 2006
    #5
  6. 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
     
    =?ISO-8859-1?Q?Tobias_Schr=F6er?=, Jun 2, 2006
    #6
  7. Jama

    Ed Kirwan Guest

    Chris Uppal wrote:

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


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

    Download Fractality, free Java code analyzer:
    www.EdmundKirwan.com/servlet/fractal/frac-page130.html
     
    Ed Kirwan, Jun 2, 2006
    #7
  8. 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
    --
    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
     
    Dimitri Maziuk, Jun 2, 2006
    #8
  9. Jama

    Eric Sosman Guest

    Dimitri Maziuk wrote On 06/02/06 12:00,:
    > 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.


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

    --
     
    Eric Sosman, Jun 2, 2006
    #9
  10. Jama wrote:
    > 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
     
    Patricia Shanahan, Jun 2, 2006
    #10
  11. 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
     
    Patricia Shanahan, Jun 2, 2006
    #11
  12. Jama

    Eric Sosman Guest

    Patricia Shanahan wrote On 06/02/06 17:00,:
    > 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){}


    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.

    --
     
    Eric Sosman, Jun 2, 2006
    #12
  13. Eric Sosman wrote:
    >
    > Patricia Shanahan wrote On 06/02/06 17:00,:
    >> 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){}

    >
    > 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
     
    Patricia Shanahan, Jun 2, 2006
    #13
  14. Jama

    Chris Uppal Guest

    Eric Sosman wrote:

    > 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
     
    Chris Uppal, Jun 3, 2006
    #14
  15. Jama

    Chris Uppal Guest

    Ed Kirwan wrote:

    > 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
     
    Chris Uppal, Jun 3, 2006
    #15
  16. Jama

    Eric Sosman Guest

    Chris Uppal wrote:
    > Eric Sosman wrote:
    >
    >
    >> 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.


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

    --
    Eric Sosman
    lid
     
    Eric Sosman, Jun 3, 2006
    #16
  17. Jama

    Dale King Guest

    Chris Uppal wrote:
    > Eric Sosman wrote:
    >
    >> 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.


    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.
    --
    Dale King
     
    Dale King, Jun 4, 2006
    #17
  18. Chris Uppal sez:
    > Eric Sosman wrote:
    >
    >> 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.


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

    Dima
    --
    We're sysadmins. Sanity happens to other people. -- Chris King
     
    Dimitri Maziuk, Jun 5, 2006
    #18
  19. Dimitri Maziuk sez:
    > Chris Uppal sez:
    >> Eric Sosman wrote:
    >>
    >>> 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.

    >
    > 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
    --
    I have not been able to think of any way of describing Perl to [person]
    "Hello, blind man? This is color." -- DPM
     
    Dimitri Maziuk, Jun 6, 2006
    #19
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Richard C. Cobbe
    Replies:
    28
    Views:
    807
    Ingo R. Homann
    Aug 1, 2005
  2. Simon
    Replies:
    14
    Views:
    746
    Isofarro
    Jan 2, 2005
  3. Calvin Spealman

    Interfaces and Exceptions

    Calvin Spealman, Jun 8, 2004, in forum: Python
    Replies:
    1
    Views:
    280
    Hung Jung Lu
    Jun 9, 2004
  4. josh
    Replies:
    6
    Views:
    443
    Ed Kirwan
    Dec 19, 2006
  5. =?Utf-8?B?QmlsbHk=?=

    Exceptions Best Practice

    =?Utf-8?B?QmlsbHk=?=, Nov 3, 2007, in forum: ASP .Net
    Replies:
    5
    Views:
    345
    gerry
    Nov 5, 2007
Loading...

Share This Page