When I read really great code, I often think "This is all there is?". It seems like there is too little code to do all the things that it does. Or what is there seems trivial, so simple that it couldn't have required any thought or effort to produce.
Bad code is full of stuff, it twiddles bits here and there, does complicated things in nested loops and works very hard to accomplish very little.
This might make bad code seem more interesting, at first glance it seems like it does more, when in fact it generally does less, just with much more complexity.
"When I read really great code, I often think "This is all there is?". It seems like there is too little code to do all the things that it does. Or what is there seems trivial, so simple that it couldn't have required any thought or effort to produce."
Similarly, in my experience great code solves a problem that would seem very difficult in a way that seems very obvious but usually only in retrospect, or as we're reading the code. A corollary would be code that reveals some truth about the system being coded that isn't obvious except in retrospect.
This comment reminded me of the epiphany I had my sophomore year in college: that code is a literal (and physical in a sense) representation of an idea or system.
I know it seems trite.
But I had been programming for years, and I had grokked recursion and pointers, but up to that point I was always sort of thinking of programming as a means to an end, and somehow distinct from the task it was accomplishing. At this point I take it for granted that I can translate my thoughts into this or that programming language, but when I first realized the direct correlation it was like a bolt of lighting.
This is the key to effective programming. I like to measure what the code ENABLES both the end user, and the programmer in the future (design leverage) - not just what it DOESFOR the user in a literal way.
The code becomes more abstract, more of a model, and the software may become a 'tool'. (You'll find that as you program you will naturally refactor to a more abstract model and things will "click-in" and work the way you want it the first time)
I think the point he's trying to make is that in the general case, boring code is safe (boring in the eyes of someone reviewing your code, that is). That's not to say boring code is better. Remember the fast inverse square root gem (http://en.wikipedia.org/wiki/Fast_inverse_square_root)? Definitely not boring, but optimal in the situation that it was in.
That's definitely not boring, and also awesome. Like I said, sometimes you find a clever hack. But if I saw that code in a code review, it would be a huge red flag for me. I'd want to see a pretty good justification for using it instead of a more standard algorithm. (It happens to be in this case that there IS a good justification).
The key problem with inverse square root is the risk of having that code unmoored from a very well put together comment explaining the rationale for it, and perhaps a TODO in the backlog about re-evaluating when to get rid of it.
Without knowing that it's a fast inverse square root approximation using the Newton-Rhapson method with 1 iteration using some clever bit twiddling hacks and an initial guess chosen by experiment to be optimally efficient in terms of accuracy and especially for speed you can end up with a lot of problems. First, someone could look at it and spend a lot of time trying to figure out what it was doing before realizing what it did. Second, it could cause people to attempt to replace it without realizing the value of it, causing wasted effort. Third, it could cause people to try to improve it, spending time attempting to find a more optimal first guess, or adjusting the bit twiddling nature in some way. Fourth, and worst of all, it could develop a reputation as a bit of "deep magic" which shouldn't be touched because nobody knows exactly how it works, so nobody ever re-evaluates whether it's worth keeping. As it stands now it's obsolete code given that modern GPUs will perform the relevant calculation in hardware much faster.
Granted, in this specific case a lot of these problems are much diminished (since the company was small, the code and its rationale was well-known by the dev lead, and it's reasonably straightforward to reverse engineer the operation and rationale for the code with some investigation), however this might not be the case somewhere else with some other piece of comparatively magical code.
When you write a bit of WTF code that's actually worthwhile imagine that everyone that worked on the code is now dead and researchers are studying it, what information would those researchers want the most? Now put that in a comment.
P.S. Also, god help you if you happen to be lucky enough to have a chunk of poorly documented "deep magic" code that happens to have a defect in it.
Even the article essentially admits that there are many cases where what is normally seen as boring is actually dangerous - just he redefines these cases as "not boring".
Specifically, repetitious code is the most obvious case of boring and that's not at all safe. He just redefines that as "not boring" because it raises red flags for him. But that's pretty strained reasoning to say the least.
Code that is almost repetitious can also be dangerous because spotting where the changes are can be hard and the repeated parts can lull you into comfort.
Of course, code normally shouldn't be too interesting either but that's a different question.
It seems like it boils down to something like a boring code review indicates safe code because everything that's interesting at that point is a problem.
I wonder if "boring" here just means "clear." I had a great case of this yesterday. We were reviewing a piece of code by someone that could have been better with a basic algorithm change. It did most of the right things but in the wrong order, sometimes on the wrong data, and did one major piece probabilistically were specific computation wasn't intractable.
The coder wasn't completely getting our explanation, but the code was so "boring" or "clear" that we opened up an editor, copy-and-pasted some blocks around added a few if statements and expected it to be basically functional. This was a complex algorithm and a complex change, and we offered provisos that we didn't know what that function returned so a "not" might have to go in front, and a variable name would have to be changed and one piece was going to have to operate on a new key in memcache, but it was basically there.
The point is, the code was so well-written that we could read it well enough to do this never having seen it moments before, and our resulting chopping was clearer to the original coder than 20 minutes of histrionics on a whiteboard full of formulae. That's how it should be. :-)
And for any haters in the crowd, it was all in Perl. So much for "write-only" complaints. :-)
In my coding, I'm starting to think it's better to write code that is wrong and clear than "right" and unclear. Because then you can understand it quickly when you come back to correct it later (note: including correcting the "right" code, due to bugs, problem change, etc).
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." – Brian W. Kernighan
It's such a great line, and such a classic one, that you don't even notice that the premise isn't true. It's like the opening line to Anna Karenina in this respect.
Do you mean that debugging is infinitely harder than writing the code in the first place (since you can never verify correctness) or that debugging isn't more difficult? In the former case, while it is factually incorrect, in the general sense it's true.
Debugging is not always harder than writing the code in the first place (let alone "twice as hard" - what does that even mean)?
Debugging doesn't mean proving there are no bugs. If it did, the quote would be even more wrong, since our inability to do that has nothing to do with how cleverly code is written. But that's beside the point, since nobody uses "debugging" to mean this; it means tracking down and fixing bugs you know about. And it's trivial to see that that's not always harder than writing the code in the first place: some bug fixes (e.g. typos) are easy.
I guess I'm taking it for granted that any piece of code is going to have multiple bugs in it, and you're going to spend more time debugging than you did writing. I still don't think you've said anything that shows the maxim to be false in the general sense, only in the sense that it could be worded a little more clearly.
There's definitely a similarity between the two principles. That shouldn't be surprising since code is basically a programmer's user interface to the computer.
Sometimes boring isn't as good as awesome. My first reaction to the Schwartzian Transform was, "Computers can do that!?" Figuring out what this thing did, and how it did it, made me a better programmer.
I completely agree. Interesting and awesome code is how you grow as a programmer. And it's the interesting code that can really make your program shine.
When I see an interesting bit of code it's still a warning sign though. Because for every time the Schwartzian Transform was implemented well, 100 programmers reimplemented it badly in a language where .sort_by(func) already existed.
Given a stack trace pointing to that single line of code with an exception, could you immediately figure out what had gone wrong? Would you know what to fix before you even had the code up in the editor?
That's something you can do with well-written production code. It's not particularly sexy to look at, but it's built for debugability.
Split that little kernal of awesome into 7 distinct lines that your CS101 nephew can explain back to you. Then it's ready to go live.
I agree that good code is usually quite easy to read and shouldn't requires big efforts of the reviewer. When I need to read some functions 2-3 times to understand it.. or when I need to switch from a "calm/boring" attitude to a "crap, I really need to think hard" attitude, it's usually a sign that it wasn't well written. It's not necessarily "bad code" but more of a sign that the programmer didn't reread himself to make sure it was clear.
Anyway, for me, the biggest hint for a bad code is big functions. It's somewhat really counterintuitive and I can't understand why people still continue to write like this. And worst, they sparse comments to separate the different sections of the function.. gasp
For decades the received wisdom among good programmers has been that long functions are inherently non-maintainable. However the actual result of companies that track maintenance information is that if the function is below 200 lines, the length of functions is not significantly correlated with maintenance cost. (However a high density of logic within the function is associated with maintenance cost.)
In general I find myself writing short functions because modern programming languages and libraries are powerful and there is not a lot of busy work. That said, if there is a lot to do and little opportunity for re-use, I have no problem with long functions. The primary criteria for creating functions should be clear interfaces that minimize abstraction leakage.
I don't have that book at hand right now. I wonder if language plays a role here. Judging from my own experience, a 200 line stored procedure is quite manageable, but 200 lines written in a c-like language are a tough nut to crack.
I believe that code bases in C were studied. As long as the number of ifs, loops, etc was small, the length of the function did not hurt maintainability.
However in this does result in language differences. In practice the density of ifs, loops, etc tends to be higher in a C-like language than in a stored procedure. So the complexity of functions tends to go up.
The research cited is, however, quite old and did not include any OO code. Method dispatch can hide an implicit "if", and I don't know whether that tends to affect the maintainability of code in practice.
Incidentally, I got exactly the same thing from "Smart"Filter at work. Like the others, I suspect that having "cam" in the URL makes it look suspicious.
Very related: Know your compiler and what optimisations it will already do for you. I have often seen code which is very hard to read because the programmer has tried hard to optimise it (e.g. reuse same variables etc.).
Bad code is full of stuff, it twiddles bits here and there, does complicated things in nested loops and works very hard to accomplish very little.
This might make bad code seem more interesting, at first glance it seems like it does more, when in fact it generally does less, just with much more complexity.