In the application I'm developing right now, we found a bug right before going live. A colleague of mine forgot to catch an unchecked Exception in a loop, which led the loop to exit, before iterating over each element. Bugs like this are so subtle and hard to track, that's why I think it was kind of my fault for not using a checked instead of an unchecked Exception.
// must work all jobs
private void workAllJobs() {
for(MyJob job : allJobs) {
job.work(); // throws RuntimeException
}
}
Let me be clear, I don't want to engage into the checked vs. unchecked Exception war. I made
my point clear a couple of times, however I simply think I need to revise
my position.
I
used to think forcing a client of an API to catch an Exception was evil! That's why I usually design custom Exceptions to inherit from
RuntimeException and
declare each and every case carefully in the javadocs of my API methods. I simply followed the
expert's advice:
Always declare checked exceptions individually, and document precisely the condition under which each one is thrown using the Javadoc @throws tag. .... While the language does not require programmers to declare unchecked exceptions that a method is capable of throwing, it is wise to document them as carefully as the checked Exceptions.
Unfortunately, the expert's advice didn't work in my co-worker's case. Should I say in most cases? He is with the sad majority of developers, that don't ready javadocs - not even on public API methods. Maybe I should have listened to
people telling me this:
I kind of disagree with your example; documenting everything in every tiny detail may be a requirement for widely used public APIs (like the JDK), but IMHO a more relaxed approach is useful for the rest of us. Like "configuration by exception" is considered a good idea, there should also be "documentation by exception". That is, don't document every tiny detail but instead follow some higher level conventions. Many people do that intuitively, but unfortunately forget to document those conventions.
Like
Matthias, my co-worker argued, that he thinks conventions should define what happens if e.g. you pass
null to a method or which Exceptions are being thrown from an API method. I do agree, conventions are a great tool to define this kind of behavior. The problem with conventions are: How do you get the whole team to agree on certain conventions and more important - how do you manage those convetions?
Getting a team of strongly opinionated individuals to even agree on minor details, e.g. how to name interfaces, is almost impossible. Believe me, I have been there! After more than a year, we still can't agree on wether to use Eclipse's notation of
IService or my preference - simply
Service. I cannot imagine how hard it will be to agree on really important topics like
passing null to methods and wether to throw
IllegalArgumentException or
NullPointerException in that case.
The second issue with conventions is how to manage them. Who is responsible to maintain those agreements? Do you put those conventions on a wiki page, which nobody updates and nobody reads anyways? I argue, that for us developers code and eventually the IDE is where we live, thus I think that's the place those conventions should live as well. Code is the common single point of truth for us and hence javadocs are in my opinion the best way to document any code related conventions.
I guess you can see where this is going. It's a trade-off, as always in software development. However, it's a trade-off with a catch. I think it's simply not enough to "just have conventions", they need to be documented and managed in the code and my weapon of choice for doing that is javadocs.