Khernighan's lever.
Kernighan's lever



Brian Kernighan
famously wrote:


	
		Everyone knows that debugging is twice as hard as writing a program in
		the first place. So if you're as clever as you can be when you write
		it, how will you ever debug it?
	

	— The Elements of Programming Style, 2nd edition, chapter 2


The following version also circulates on the net:


		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. 
	

This second quote may or may not be by Kernighan — the questionable
use of "by definition" makes me uncertain — but it is useful as a
provocative sound bite conveying the same essential idea.

It is tempting to interpret Kernighan's aphorism as a warning: Stay away from
clever techniques, it seems to say, because if you write clever code, you will
never be able to get it to work. But this interpretation is unfortunate, and
rests on the false assumption that cleverness is static.

While it is possible that Kernighan intended us to interpret the message in a
specific way, he wisely restricted himself to merely presenting an observation,
allowing us to draw our own conclusions from it.

Pay close attention to what is actually being said: Having written code as
cleverly as you can, you will suddenly face a problem that you are not clever
enough to solve. Certainly, "clever" in this context does not refer to some
innate talent, because nobody is born with the ability to write clever code in
the first place. The "cleverness" required to write and understand intricate
code is an acquired mental skill.




If you are a programmer, you will be familiar with a sense of wonder,
gradually transforming into utter stupor, as you stare at some perfectly
reasonable code that couldn't possibly fail, and yet somehow it does. And since
you are confident that you understand how the code works, having written it
yourself, you feel that you must be able to figure out what is going on. Not
only the desire to deliver working software on time, but other powerful forces
such as pride, stubbornness and curiosity contribute to the motivation that
pushes you onwards through the arduous task of tracking down the root cause of
the error.  Suddenly you see it, and you're blinded by a bright light as all
the pieces fall into place. The inexperienced programmer may fall into the trap
of self-degradation: "Oh, look at how stupid I was!" But that same sentiment is
proof that your programming-related cleverness, or skill, has increased: "Oh,
look at how clever I've become!" (Although I wouldn't recommend saying that out
loud.)

Skill is the result of practice, that is, of systematically trying to work
slightly beyond one's ability. Quite understandably, most of us don't spend
that kind of effort unless we have good reason to. Hence, without motivation we
do not practise, but simply cruise along at our current level and never improve
any further.

The mind is very good at rationalising, and will convince us that our
current skills are sufficient, that we are all "good enough"; certainly
better than the average programmer anyway. The human brain will do this trick
regardless of our actual level of skill. So while we all tend to consider
ourselves sufficiently skilled right now, we never regret improving.




You effortlessly wield clever programming techniques today that would've
baffled your younger self. (If not, then I'm afraid you stopped evolving as a
programmer long ago.) But this improvement is the result of practice, and
something must have motivated you to put in all those hours of work.
Kernighan's witty remarks provide a clue: In programming, as soon as you work
at your current level, you will automatically end up in a situation where you
have to work beyond your current level. By means of this very fortunate
mechanism, you will leverage several basic human drives (honour, pride,
stubbornness, curiosity) into providing the motivation necessary for
improvement.

I call this mechanism Kernighan's lever. By putting in a small
amount of motivation towards the short-term goal of implementing some
functionality, you suddenly end up with a much larger amount of motivation
towards a long term investment in your own personal growth as a programmer.

If we deliberately stay away from clever techniques when writing code, in
order to avoid the need for skill when debugging, we dodge the lever and miss
out on the improvement. We would then need other sources of motivation in order
to grow as programmers, and if no such motivation appears, our abilities
stagnate (or even deteriorate).

The psychological concept of flow, somewhat simplified, can be used
to visualise the process. Flow is when you are "fully immersed in a feeling of
energised focus, full involvement, and enjoyment in the process of the
activity" (wikipedia), and it
only occurs when the challenge that you are tackling matches your current level
of skill.


	
		Implement below your ability,
			and you get to debug in the "flow" area.
	
	
		Implement at your ability, and
			the debugging will be frustrating, but you gain skill.
	


You will find yourself situated at a particular x-coordinate, corresponding
to your current level of skill. If writing code is a point on this graph, then
(according to Kernighan's assumption) debugging the same code would
be a point a fair bit directly above it.

It is certainly possible to deliberately pick a low starting point just to
avoid ending up in the frustration area. But this will put you squarely in the
boredom area, and boredom is frankly no better than frustration. However,
should you pick a starting point in the enjoyable flow area, Kernighan's lever
will screech into action and push you sideways through the graph, increasing
your skill until it matches the challenge posed by the bugs in your code.

Naturally, the real world is more complex than this, and you will sometimes
have compelling reasons to go for the boring option, and artificially reduce
your cleverness in order to dumb down the debugging phase. But it may harm
your long-term personal development if you go down that road every single time
you write a program.

In conclusion, the answer to Kernighan's rhetorical question — "how
will you ever debug it?" — is straight-forward: By tackling the problem,
thereby gaining valuable experience and becoming more clever in the process.
And the second version of the quote can be adorned with a single word at the
end: Yet.

Posted Tuesday 11-Dec-2012 21:33

Discuss this pageDisclaimer: I am not responsible for what people (other than myself) write in the forums. Please report any abuse, such as insults, slander, spam and illegal material, and I will take appropriate actions. Don't feed the trolls.Jag tar inget ansvar för det som skrivs i forumet, förutom mina egna inlägg. Vänligen rapportera alla inlägg som bryter mot reglerna, så ska jag se vad jag kan göra. Som regelbrott räknas till exempel förolämpningar, förtal, spam och olagligt material. Mata inte trålarna.AnonymousSat 22-Dec-2012 00:10If this is all true, a perfect solution would be to debug the program 10 years after you've wrote it...However, you will be tempted to rewrite it because after those years the code will be rated down into the boring area, so you'll need another 10 years to wait to debug it.
lftLinus ÅkessonSat 22-Dec-2012 14:09If this is all true, a perfect solution would be to debug the program 10 years after you've wrote it...No, that's completely contrary to my point. Was I really that unclear?Work at your current capacity for ten years and your skills will improve only slightly. Spend ten years trying, with great effort, to work beyond your current capacity, and your skills will improve a lot. The tricky part is motivating yourself to spend that effort. This is common knowledge.My article is about how software developers get this motivation for free by writing clever code.
mporshnevMax PorshnevTue 25-Dec-2012 13:34lft wrote:Spend ten years trying, with great effort, to work beyond your current capacity, and your skills will improve a lot. A famous russian singer <a href="http://en.wikipedia.org/wiki/Vladimir_Vysotsky">Владимир Высоцкий</a> had a song about that: "лучше гор могут быть только горы, на которых ещё не бывал". The song is called "Прощание с горами".
AnonymousFri 11-Jan-2013 13:06mporshnev wrote:"лучше гор могут быть только горы, на которых ещё не бывал"Or, loosely translated to English, "Better than a mountain can only be mountains you have not scaled yet".
AnonymousSun 27-Jan-2013 01:33You just put delicate words onto an everyday personnal feeling. And the tricky part about motivation is not an issue IMHO, because there is no biggest reward than feeling improvement of one's skill. This is self-motivating. Having an idea and code it in the boredom area in order to avoid frustration is like treating your own idea with disrespect. I prefer writing code that respects any original idea thus requiring full capability, which will likely lead to bugs and so on, as you said, but also, hopefully, to a point where you honored your idea (and fixed your bugs).
AnonymousSun  5-May-2013 19:46Interesting essay with some valid points, but the context lacks depth: it is one thing to do this because it is a hobby, quite another if one must walk the very delicate line of writing code easy to debug in consideration of others, because one is an entrepreneur, racing against the clock. "When are we going to ship?"You are probably privy to the Zen of "software is done when it is done!", which means that writing quality code must necessarily avoid cleverness in favor of maintainability: if one is an entrepreneur, one must eventually ship, or the startup will bust.Rule of clarity: clarity is better than cleverness"Because maintenance is so important and so expensive, write programs as if the most important communication they do is not to the computer that executes them but to the human beings who will read and maintain the source code in the future (including yourself)."http://www.catb.org/esr/writings/taoup/html/ch01s06.html#id2877610Rule of representation: fold knowledge into data, so program logic can be stupid and robust"Even the simplest procedural logic is hard for humans to verify, but quite complex data structures are fairly easy to model and reason about. To see this, compare the expressiveness and explanatory power of a diagram of (say) a fifty-node pointer tree with a flowchart of a fifty-line program. Or, compare an array initializer expressing a conversion table with an equivalent switch statement. The difference in transparency and clarity is dramatic."http://www.catb.org/esr/writings/taoup/html/ch01s06.html#id2878263
AnonymousSun  5-May-2013 19:53I would also like to leave you to think about the following:anyone can write clever code; anyone can write complex code; anyone can over-complicate......but if you are really, really smart, make a complex thing simple! Can you go the other way, can you effectively simplify complex things? That is true smarts, because it is incredibly hard to do, and requires one to be extremely smart, knowledgeable, and experienced. Not very many people can do it, even among the smart.
AnonymousSat  8-Jun-2013 04:27"Everything should be made as simple as possible, but not simpler." - Einstein
AnonymousSun 25-Aug-2013 23:07I do not think it is necessary to deliberately stay away from clever techniques. It depends what you do. Also, debugging isn't exactly twice as difficult; it depends on the program and on other things.
AnonymousMon 28-Jul-2014 06:51It true that debugging do improve the understanding of the myth underlying the technologies, especially when debugging others's code in programming.
AnonymousMon 28-Jul-2014 07:01Very nice. Good of you to not attempt to debunk Kernighan but leverage his quote!
AnonymousFri  8-Aug-2014 03:36While practice is generally useful, some practice is more useful than other practice. We are not trying to maximize practice, we are trying to maximize skill-building per time, subject to the motivational constraints. I believe debugging is often less skill-building than writing code - for instance, an hour-long hunt for an omitted character often causes little or no skill enhancement. Sadly, the laws of physics do not say "you will gain skill in accordance with how much you work".Also, I find dubious your statement that coding skill is not innate because "because nobody is born with the ability to write clever code in the first place". "Practice improves programmer skill" does not imply "*only* practice improves programmer skill". Try telling a 3-foot-tall man that the ability to play basketball isn't innate, because "nobody is born knowing how to play basketball".
AnonymousFri  1-Apr-2016 09:41[KC] I love this Kernighan quote. As the author of the best language and best programming book ever, he's one of the computing greats who will be remembered forever.Nice article too Linus. I think it sure takes twice the effort to debug, for the initial effort in analysis and then implementation has to be revisited, before the problem can be seen in context of the original solution. "That can't possibly be happening, the code just cannot do that!". I love problems that seem so impossible. The more people tell me that, the more obvious I know the solution will be when we find it.Subtle problems are much more difficult to find :)From my own (30yrs+) experience in commercial software, Kernighan is right.
AnonymousTue  7-Jun-2016 22:263 aphorisms (aphorisi?), all related, that i've collected over the long, arduous years of prof s/w, all a testament to BK's thesis:1. if builders built buildings the way programmers build programs, the first woodpecker that came along would destroy civilization.2. nelson's law: the better the four-wheel drive vehicle, the farther away from civilization you'll be when it breaks down.and 3, the corollary: the probability that a bug exists is directly proportional to the programmer's insistence that it does not.thank you for a great article (and the accompanying apropos pic of archimedes)
6502Andrea "6502" GriffiniTue 10-Apr-2018 08:31Something that programmers should try to do in my opinion is1) write code at your limits, trying to push them farther2) but don't do that in *production* code :-)Code in production should be "trivial"... even if of course what is trivial and what is not depends on the reader.Moreover the problem of writing the simplest code that can do the job can be interesting too (keeping boredom away), even if of course at a different level than writing the smartest, the fastest or the smallest.However I don't think there is such an easy answer to the question of code complexity... the only definitive answer I think there is in programming is "it depends", and the simplest code may be too simple to be future proof and not able to accept easily the next feature that will be required, forcing a rewriting.Nothing bad in rewriting itself of course (au contraire), but may be the economic downside won't make that an acceptable philosophy.
AnonymousThu  1-Oct-2020 23:55Wow this page is used in our university programming course.
AnonymousThu 18-Aug-2022 19:41If this is all true, a perfect solution would be to debug the program 10 years after you've wrote it...However, you will be tempted to rewrite it because after those years the code will be rated down into the boring area, so you'll need another 10 years to wait to debug it.Okay
AnonymousWed 21-Dec-2022 20:41Mark FitzsimmonsEngineer, woodworker, philosopher, fanMy response is, both of the original statements are false, because the skills required for programming and debugging are subtly different, and not inherently easier or harder. The debugging task has methods that can be systematic and stepwise (making the task "easier"), and sometimes requiring additional code writing to interrogate what were, in your original inspired creation phase, leaps of intuition or complex design you imagined were simpler than you thought (making the task "harder"). Debugging is in part a process of learning how complex your design intent really is, when translated into a language of a complex machine. They are not really separate things, programming and debugging.
AnonymousTue 15-Aug-2023 07:17This matches with my experience as well. Thanks for sharing.Talmid
AnonymousSun 11-Feb-2024 22:21My interpretation of "clever" as Kernighan uses it is based on writings by him and Thompson in the Unix heyday. Thompson wrote the kernel using simple mechanisms that could be optimzied later if required, and only optimized after profiling. So "clever" could be interpreted as overdesigned. Of course the points you make about improvement are valid, and if we interpret "clever" as meaning as good an algorithm and data structure as possible, then yes, by all means, so long as the pattern can be discerned by others later. Like good writing, one must write elegantly and clearly.
AnonymousTue  8-Oct-2024 20:21Two authors, Brian Kernighan and Bill Plauger, wrote "The Elements of Programming Style" while working at Bell Labs in the 70's. Bill also authored several books. Bill probably wrote the first commercial C compiler and a UNIX clone called Idris. Brian and Bill were brilliant programmers who were convinced to write the elements of programming style because of the dreadful Fortran code published in numerical analysis texts. They collaborated on two further books focused on software tools, one in Ratfor and the other in Pascal.

