On Mar 30, 2011 6:22 AM, "Kevin Wright" <[email protected]> wrote:
[...]
> when working with Java.  I find that it's far easier to reason about code
if I can skip logic between the time a collection was created and the time
it's actually used, knowing that intervening changes simply aren't possible.

I was going to respond to this thread to add that thought myself, but you
beat me to it.

There's a popular book about UI design called "Don't make me think!" -- I
believe we should approach the code itself in the same way: "Don't make me
think about code!"

Things like use of immutable collections, even when not strictly necessary
at the time the code was first written, will make maintenance much simpler
and safer. Other stuff that helps me not think about code:

* null checks on values stored by public methods and constructors -- when a
value is stored but not dereferenced, a null check will produce an NPE with
the culprit in the stack trace, whereas the culprit will be long gone when
the value gets dereferenced in a future method call

* marking every field initialized by the constructor (or a field
initializer) adnprivate and final. (in many cases, objects can become fully
immutable without inconvenience)

* religiously adding doc comments that explain what classes and methods are
supposed to do. It often makes sense to document fields with their
invariants with respect to each other too.

* never handling an exception by ignoring it. When your options are limited
(for example in the nested try/catch/finally(try/catch,try/catch) hell of
closing JDBC resources) at least log the exception you're suppressing. Or
recognize the inherent evil and adopt a lightweight wrapper like Spring JDBC
that masks the broken API.

None of this is ground breaking; in fact, it's all very basic and very old
advice. All I can say is that in my own experience, teams who approach their
work this way can deliver more value to customers in less time than those
who leave their classes and interfaces undocumented, leave their fields
nonfinal, and pass around mutable collections where the present situation
allows it. And, shockingly, teams who follow this  basic advice are few and
far between.

These are all cheap practices that need not be sacrificed at crunch time.
Unit tests and FindBugs are great investments that I make regularly, but I'm
guilty of ignoring them when under pressure. The habits above, and others
like them, are easy to stick to no matter what.

To bring this back on topic, you can't blame checked exceptions when people
fail to follow 4 out of the 5 practices I've outlined above. And in fact, if
you adopt the attitude that proper error handling and "don't make me think
about code" makes you deliver faster and better, maybe checked exceptions do
even help a bit. Especially when your IDE can use the declared exceptions to
create an outline of the necessary error handling catch blocks for you (like
Reiner said a few days ago).

But it's not black and white. I cringe as much as the next guy at the
laundry list of checked exceptions that have to be individually gift wrapped
and rethrown in an "exception appropriate to the abstraction" in code that
does reflection, RMI, and so on. It's a complex issue fraught with
tradeoffs.

-Jonathan

-- 
You received this message because you are subscribed to the Google Groups "The 
Java Posse" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/javaposse?hl=en.

Reply via email to