Tue, 15 Aug 2006
Clean Code versus undef
I like to write a clean, readable code. Sometimes even to the point that I am slow to write or fix the code when I think the current code is too ugly, but I have no immediate idea on what would be the best way to fix it cleanly. Recently I've came across an interesting dilemma, which is probably a clash between two measures of a clean code:
- Rule 1:
- The clean code produces no warnings. The
compiler usually knows about dangerous constructs of its language, and can
warn the programmer appropriately. When the programmer really
wants to do something weird, there is often a way to switch the warning off
(such as using two nested pairs of parentheses when an assignment is to be
used as a Boolean value inside the
if (...)
statement). - Rule 2:
- The clean code is readable. And by readable, I also mean short. The longer the code is, the more the reader has to keep in a short-term memory in order to grok the code. Perl programmers usually call this principle DWIM - Do What I Mean. So the symbols should be named appropriately, the meaning of the return values should be obvious, etc.
There is an interesting problem in Perl with an undef
value.
The Perl interpreter usually considers undef
to be something
volatile which should be handled with an extreme care. So it warns of almost
every attempt to use an undef
value. Yet undef
has a very clean mental interpretation: it is nothing. So it is natural
to expect it to behave as a neutral element of the operation in question:
The concatenation undef.$string
should lead to
$string
, length(undef)
should be zero,
lc(undef)
should remain undef
, ++$new_var
should return 1 for a variable with undefined value, etc.
So I am in a situation when I have to put
if (defined $var) { ... }
around various parts of the code, in order to disable warnings
about an unitialized value. But the code is perfectly readable (and thus
clean by Rule 2) even without it. Adding more code makes the readability
by Rule 2 worse.
Moreover, even Perl itself is not consistent with handling undef
:
The above ++$new_var
construct follows the DWIM principle,
and produces no warning. But something like
print STDERR $log_prefix, $message, "\n";
produces a run-time
warning when $log_prefix
is not defined. There are definitely
usages of undef
where Perl should complain loudly (such as
calling a method of undef
, calling undef
as
a function, etc). But I think string concatenation or other string operations
(i.e. everything that can be solved by replacing undef
by an
empty string) should not fall to this category.
So what do you think? Should Rule 1 have precedence here? And what about your language of choice? I know, LISP is unreadable by definition :-), but what about other languages?