This page contains an archived post to the Design Forum (formerly called the Flexible Java Forum) made prior to February 25, 2002.
If you wish to participate in discussions, please visit the new
Artima Forums.
Message:
caveat caveat
Posted by Bill Venners on 18 Jun 1998, 10:18 AM
> In general, I agree with the advice to throw meaningful, > specific subclasses of Exception. However, it's important to > consider how to do this in a way that allows the code to > evolve over time without breaking clients. As emphasized in the > article, the throws clause is an important part of the contract > between a class and its clients. If a future version of the > class needs to throw a new type of exception, the clients will > have to be recompiled. > A nice solution is used in package java.io. Many methods of > classes in this package throw IOException, which is actually > the superclass of numerous exception types. Most clients only > need to catch the more general IOException, but can handle > specific exceptions if needed. Future versions of these classes > may throw new subclasses of IOException without requiring client > code recompilation. > This is an excellent point, though I have one caveat of your caveat to offer. Another good guideline concerning exceptions could be: Create families of exception types, not just individual exception classes. Families, like IOException, give you more flexibility because clients can just make a catch clause for the base type and catch the subclass types that exist today, AND their code won't break if I add another subclass exception to my throws clause in the future. There superclass catch clause will catch this new exception. The caveat I have to this is that I think the whole point of having checked vs. unchecked exceptions is that checked exceptions are *supposed* to break the client's code. If a client doesn't either catch the checked exception or declare it in its throws clause, that client code won't compile (i.e. is broken). This forces clients to *think about* what they should do if such an exception were to be thrown. So when I change my code and make it possible for a new exception to be thrown, I would make it a checked exception to once again put it into client programmer's faces. They will have to recompile their classes and figure out how they want to deal with this new possibility. If I felt it wasn't important that they actually considered what their code should do if my code threw this new exception, I'd make it an unchecked exception. On the other hand, people tend get upset when you deliver a new version of a package (whether the package is your company's product or just used in-house by other groups) that breaks existing code that uses the package. In general, one should strive to make updates binary compatible with previous releases. If you want to get rid of something, for example, don't just get rid of it, deprecate it and explain the alternative in a doc comment. But I think checked exceptions might be the exception to this rule of avoiding breaking the client code. The checked exceptions my package throws tells clients what errors I, as designer of the package, felt were important or common enough that client programmers, if they want their code to be robust, would need to consciously decide how to deal with. > Another approach is to use an instance variable in the exception > class to indicate a subtype. This approach is useful for > exceptions thrown by CORBA services, since CORBA IDL does not > support an inheritance hierarchy for exceptions. Yes, this makes sense in the CORBA IDL context. In general, however, I would go with the "Define a different exception type for each different kind of problem your code can encounter," which lets people separate out code in different catch clauses and use inheritance to catch a whole family of exceptions in one clause. bv
Replies:
|