NASA has this short document describing 10 rules for developing safety critical code [1]. It's from 2006 [2] but because it's about programming in C it is as relevant as C language itself.
I'm the most unqualified person to argue with their rules, but rule number 4 ... I just can't leave it like that. I heard about such rule over and over from many people and saw it in many places. This time I want write down my counterarguments.
The 4th rule:
No function should be longer than what can be printed on a single sheet of paper in a standard reference format with one line per statement and one line per declaration. Typically, this means no more than about 60 lines of code per function.
Rationale: Each function should be a logical unit in the code that is understandable and verifiable as a unit. It is much harder to understand a logical unit that spans multiple screens on a computer display or multiple pages when printed. Excessively long functions are often a sign of poorly structured code.
I heard the same rule about length of file, commits and other things measured in lines of code. Usually length is undefined and it is just advised to keep things "short". NASA made it a bit better by giving exact number of lines. But this does not change a thing. It's still stupid and here is why:
- Complexity of each line is different.
- Function with single line might be impossible to understand.
- Function with many lines might be super easy to understand.
- Each function call reduce program speed.
- Attempt to comply with such rule leads to cleaver programming.
- Dividing code do not reduce complexity, only spreads it.
- Divided code is harder to read from start to finish.
- The "short function" advice only leads to arguments in code review.
- ... more to come
Example of very long function that is easy to understand:
char *foo(int code) {
switch (code) {
case 0: return "success";
case 1: return "error01";
case 2: return "error02";
case 3: return "error03";
// ... many lines
}
return "unknown";
}
Example of short function difficult to understand [3]:
float Q_rsqrt( float number )
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y; // evil floating point bit level hacking
i = 0x5f3759df - ( i >> 1 ); // what the fuck?
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
// y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
return y;
}
I don't know what else to say. This is just silly. Stop it, get some help.
EOF