“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?”
— Brian Kernighan, The Elements of Programming Style
(fortunately the interview itself is not so trite as the headline)
> “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?”
By becoming more clever! That's the very principle of learning: to become more clever.
The act of debugging your own code to become more clever is a well-known learning technique called "Kernighan's ladder", precisely due to this inspiring quote.
>The act of debugging your own code to become more clever is a well-known learning technique called "Kernighan's ladder", precisely due to this inspiring quote.
According to Google, you seem to be the first person to use that phrase.
I am not an English native speaker, but I think when you learn you become wiser, not "more clever*.
There are things that can increase your "cleverness" like deliberate practice (of mental calculations, of memorization), meditation or deleting social media to increase your attention, or using drugs. I would not call that "learning".
Learning is similar to "installing new software on existing hardware". Becoming more clever is similar to "installing new hardware".
> Don't write clever code; the problem you're solving with code is difficult enough already.
No, it isn't. 90% of times it's just tons of dumb boilerplate. The sheer amount of that code creates its own accidental complexity, so if a bit of clever code can cut it down by an order of magnitude, by all means go for it. Other people may need to spend a bit of learning up front, but they'll come out better at the other end, and they won't have to pay the ongoing price of wading through vast amounts of code noise.
I guess I misunderstood it and falsely applied it to make my code clearer and more effective. I failed to become "more clever" in the process and now I'm doomed to write unclever code other people understand better.
Nobody said that you should never write unclever code. Unclever code is alright, but it does not help you to improve. When you want to have a "cleverness boost", you can try to write and debug some clever code thus applying Kernighans's lever. You are not doomed, you can start doing that at any time. I'm sure that the unclever code that you get to write most of the time will even improve after that process.
I remember writing a little bit of clever (at the time) code for simplicity and speed. Ended up doing debugging and sanity checks via napkin math to confer with my partner because it was easier than reading through the function.
Exactly. I've never interpreted that quote other than encouragement to continue writing "clever" code in order to get better at coding, despite the fact it's typically used to suggest the opposite.
As the party guilty of trotting that quote forth, I have to say I couldn't agree more.
Nevertheless, the time lag to improving enough to debug your own very clever code may for some be recalled as a period of floundering dismay, self-doubt, and potentially crippling imposter syndrome.
At these times it is important to be willing to ask for help.
Corollary: at any given time, write code that is only slightly beyond your ability to debug, so that the competence delta is small.
Here's an example: I was writing some code that needed predicates and assertions and at first I did the functional thing and mapped the list of preds into a list of assertions. It worked and was short and DRY, but it had lots of downside, not the least of which is that it ruined stack traces (this was in JS). It turned out to be better to just do the simple thing and statically define a list of assertions that mirrored the preds. It was far longer and more repetitive, but much easier to read and understand.
It’s a real shame languages have such shitty stack traces for functional style code. It’s nothing fundamental about the style, so I’m hoping the situation improves over time.
I'm obviously not the person you responded to, but one thing to note is that the stack is going to be a more useful source of debugging information if the function call stack is encoding the logic of the program, which I would assert is more often the case in imperative style programming.
Imagine for example a state machine implemented two ways. In an imperative style where you have a big if STATE_IS_X /then function_x() /else if STATE_IS_Y ... tree calling a function for each state. Secondly in a functional style where you have a pattern match on a list of tuples of (state, function). In the first case the stack tells you exactly which state you were in and which function got called. In the second case the call stack will look the same in each case because you just match on the first part, unpack the second part into a variable and call the function in the variable.
I guess I see what you're saying, but shouldn't it be evident which function got called based on the next stack frame up? When I look at stack traces I guess I'm usually just trying to figure out the sequence of calls so that I can know where to look for a bug, but if I needed to inspect state I would probably be doing it in a debugger.
— Brian Kernighan, The Elements of Programming Style
(fortunately the interview itself is not so trite as the headline)