In a recent thread I had initially given a rather terse reply, which I
subsequently elaborated on when the OP asked how it worked. Later in the thread
the OP asked how to change the code a little and I bullied him into figuring out
the answer for himself, with a little hint along the way. The OP duly figured
out how to solve the problem, but asked "is it correct way to do it ?". My
answer of 'Indeed. Although the real answer is: "Did it work?".' didn't seem to
satisfy the OP who again asked "wat's the right way or answer to do it,
My reply to "What is the right answer" led to the following list:
- Does it work correctly?
- Do you understand it?
- Would anyone else understand it?
- Will you understand it in a month's time?
- Does it strike a good balance between terseness and verbosity?
- Could you make changes to it without it being likely to break in unforeseen ways?
- Is it fast enough?
which perhaps needs a little elaboration:
Does it work correctly?
Seems pretty obvious doesn't it? However there is a lot under the
surface here. A recent question asked how to efficiently replace the
first and last n with ^ in runs of n in a large file. Sounds pretty straight
forward. But there are a few clarification questions that needed to be
asked (and they were):
- What happens to n or nn?
- Can there be new lines in the n runs?
- How large is "a large file"
The specific answers don't matter here, but the nature of the
questions is important. To know if a solution works correctly you have
to know what it is that you are trying to solve. You have to carefully
consider the edge cases. Sometimes figuring that out is much more than
half the battle.
Often this is the driver for generating and maintaining a test suite.
The major focus of the test suite is on the edge cases.
A correct solution has to work correctly for all the cases it may
have to cope with.
Do you understand it?
If you don't understand the code how can you possibly be sure it does
the right thing in all the situations you expect to use it? If you don't
understand it today the chance of you being able to fix it in the future
is almost 0. Even the chance that it works correctly is pretty low if
you don't know how it works - how can you be sure about the edge cases?
The right answer has to be something you understand.
Would anyone else understand it?
If you are the only person who will ever have to work on the code
then you may think that someone else being able to understand the code
is unimportant. However in most cases good code remains in use for a
long time and there is a pretty good chance that maintenance in some
form by someone else, or by a future self, will need to be performed on
A correct solution should be understandable by someone who hasn't
seen the code before and who has only a modest understanding of the
Will you understand it in a month's time?
There is a stranger who is rather likely to take a look at the code
some time in the future who will probably have no idea how it works
before looking - a future you!
Although code doesn't really decay over time, your understanding of
A correct solution provides its own refresher course.
Does it strike a good balance between terseness and verbosity?
There is a real tension between golfed code at one extreme and "can't
see the code for the comments" at the other extreme. A similar tension
exists between one letter identifiers and identifiers that try to tell a
The balance point tends to shift as code changes from development
mode to maintenance mode. In the end it tends to be a matter of what the
developer is comfortable with, although that comfort level will very
likely change over time
A correct solution is terse enough that understanding is not impeded
by clutter and verbose enough to be understood.
Could you make changes to it without it being likely to break in
This implies elements of robustness and transparency. Robust so that
maintenance changes are unlikely to break the code, or at least will
result in early and noisy breakage rather than late and subtle breakage.
It is generally much better that the code die in a noisy fashion early
on than quietly produce wrong answers or set traps in data structures
that are sprung later on remote realms of the code.
Transparency means that the code usage should be clear and that the
effect of changing the code or the context of the code should be readily
A correct solution is easy to maintain and resistant to the
introduction of nasty surprises.
Is it fast enough?
For most code speed just doesn't matter. The amount of work done by
typical code is small in the context of modern computers and the tasks
they are most often called on to perform.
For some code however speed is of overwhelming importance. Either
because lots of things have to be done with small latency (web servers
for example), or because there is simply a large amount of work to be
done (gene data manipulation for example). In most cases finding the
right algorithm is the key to the solution.
A correct solution uses an appropriate algorithm.
Update: added links to other referenced nodes
Perl is environmentally friendly - it saves trees