Signs your code sucks
turnleafdesign.com
turnleafdesign.com
Here's the quote from the book:
From time to time, a complex algorithm will lead to a longer routine, and in those circumstances, the routine should be allowed to grow organically up to 100-200 lines. (A line is a noncomment, nonblank line of source code.) Decades of evidence say that routines of such length are no more error prone than shorter routines. Let issues such as depth of nesting, number of variables, and other complexity-related considerations dictate the length of the routine rather than imposing a length restriction per se.
If you want to write routines longer than about 200 lines, be careful. None of the studies that reported decreased cost, decreased error rates, or both with larger routines distinguished among sizes larger than 200 lines, and you’re bound to run into an upper limit of understandability as you pass 200 lines of code.
Splitting the routine into 20 functions, one for each step, doesn't necessarily make it any more understandable: it reminds me of a DailyWTF in which a programmer was told to split a large routine into functions and just did something like this:
doPart1()
doPart2()
doPart3()
...
It's just as effective, if not better, to comment what each section of the large routine does. One advantage of keeping it in one routine is if there are dozens of values which are global to the routine and are not changed throughout it: it would create an ugly mess to pass those all around to each of the subroutines.A better way is to use nested functions. Long-lived state goes in the outer function's variables, so you do not have to repeatedly declare them. Ephemeral variables go in the inner functions. Sub-tasks get encapsulated with zero boilerplate.
If your language does not have nested functions, use a worker class. The algorithm-wide state goes in member variables, initialized from constructor parameters. The sub-tasks are methods. A benefit is that sub-tasks from different jobs can be batched to better use the instruction cache and branch prediction information: a.do_step_1(); b.do_step_1(); a.do_step_2(); b.do_step_2(); ...
Nested functions are good for this kind of code, even when they are only used once and do not abstract --- because you have less variables in the innermost scope. (And when you are going to mutate variables at all, then strongly prefer to do it to variables in the innermost scope.)
No thanks. Has this author ever written any algorithm more complicated than a basic CRUD app? I'd like to see him read some kind of well written complicated graphics algorithm without any comments. The "why" is often really really important, and you can't read that from the instructions.
And sometimes there's just certain technical limits you just can't get around, and you have to comment those.
-- What? --
We aren't writing books, we're writing instructions for a computer and those two things can sometimes be very, very different.
It's also silly if, for example, you need to do "clever" things for performance reasons. Any comment that explains the why behind your code is a good comment.