On Comments
One way or another, all programmers eventually
learn the importance of commenting their code. The importance of clear
documentation increases with the size of the team and the complexity of the
project. Ideally, the code will not only be documented but unit tested as well.
Here's an example of what happens when, for one reason or another, we let
ourselves be less than thorough...
Let's create a hypothetical method,
GetRecord,
that takes an identifier string as an argument and returns an object of type
MyRecord://
Return a record given its
identifier.public MyRecord GetRecord(
string id
){}Admittedly,
the comment is a little obvious here and, for all it says, could be omitted. But
what's missing?While implementation
details generally shouldn't be part of the comment if they're subject to change,
the example clearly omits information that callers need to know. Suppose the
identifier is malformed, or the record for that identifier has been deleted.
What does the method return? Null? A default record of some sort? Does an
exception get thrown? And what happens if our implementation needs to hit a
remote server to complete the request, and a connection can't be
established?Pretend for a moment the
implementation throws an exception when a record isn't found. Code gets built
upon the method with this assumption. Some time in the future, another
programmer makes use of the method and decides it'd be better if it returned
null instead, changing the implementation to suit new code. It's a small change,
really, and development on the product continues. It's obvious where this is
leading.There's now a body of code
that expects an exception to be thrown when the record isn't found, and another
that expects a null return value. The code expecting the exception may not be
prepared to handle a null return value, and null reference exceptions could
result. If, to fix this, a developer goes in and changes
GetRecord
back to its original implementation, the code expecting a null return value will
get exceptions
it
may not be prepared to deal with. Either way, this "innocent" little change has
created the sort of mess you don't want in the final stages of
development.Good documentation can
help, if one takes it seriously. And one should: it is no less important than
the method's signature; it is the human part of the interface contract. That not
only means the comments need to be in place and respected, but it means that
comments must be updated as the method's functionality is extended or modified.
The impacts of even minor changes must be studied, particularly changes made in
lower layers of the code. Like Bradbury's crushed
butterfly, tiny changes in lower layers can have a ripple effect on
the stability of the product.Would
unit testing have saved the day? Only possibly. Certainly, if a unit test had
been written against the possibility of a missing record, the change would've
been caught... but in this case the change was intentional, not accidental, and
the developer who made the change might just have updated the unit test as well.
All of which leaves you with a passing unit test and broken
code.Would comments describing the
behavior of
GetRecord
in the case of missing records really have helped? Only if the developers
involved understand those comments to be part of the method's contract and act
appropriately.So: document both the
expected and unexpected behavior, and foster a culture where the comments are no
less important than the code itself. And if something
isn't
documented but clearly needs to be, don't assume that changing the
implementation is safe.
Posted: Tue - January 16, 2007 at 05:07 PM