7 ms·
Kernighan's Lever
- zahlman 10mo ago(2012) > 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.) ... Perhaps if we allow that "clever techniques" can yield simpler results than my former self did.
- stodor89 10mo agoMy younger self effortlessly wielded clever programming techniques that continuously baffle my current self.
- lupire 10mo agoThis article says nothing of substance.
- userbinator 10mo ago(2012) This article can be summarised in one word: learning. I've noticed over the years that there seems to be a growing divide amongst programmers, between those who believe in learning, and those who don't (and actively try to avoid it); unfortunately the latter has become a majority position, but I still try to show others this article when they don't understand code that I've written and would rather I stoop to their level. A look around the site at what else he has accomplished, should be enough evidence that he isn't just a charlatan, unlike some others who have made a consulting career out of spouting pompous hot air about methodology.
- yodon 10mo agoThis feels like a lot of rationalization for the purpose of excusing writing exactly the sort of code that Kernighan advised against. Advising against writing complex code is not advising against learning. The person who solves a hard problem correctly using simple code has generally spent more time learning than the person who solves it using complex code.
- GMoromisato 10mo agoYes, I agree this is true in some (many?) cases. But it is also true that sometimes the more complex solution is better, either for performance reasons or because it makes things simpler for users/API callers.
- bruce511 10mo agoYes, there's a valid argument that simple code is not always best performance. Optimizing simple code usually makes it more complex. But I think the main point stands. There's an old saying that doing a 60 minute presentation is easy, doing one in 15 minutes us hard. In other words writing "clever" (complicated) code is easy. Distilling it down to something simple is hard. So the final result of any coding might be "complex", "simplified from complex", or "optimized from simple". The first and third iterations are superficially similar, although likely different in quality.
- userbinator 10mo agoLooking at all he has done, I don't think he means "complex" when he says "clever". He's not advocating for (and most likely against) the architecture-astronautism of overengineering that some people seem to be associating with "clever" here. He means code that appears indecipherable at first glance, but then once you see how it works, you're enlightened. Simple and efficient code can be "clever".
- Mikhail_Edoshin 10mo agoGood code should not be immediately understandable. Machines that do pasta do not look like humans that do pasta. Same for code; good code does things in a machine way and it won't look natural. Example: convert RGB to HSV. If you look around for a formula, you'll likely find one that starts so: cmin = min(r, g, b); cmax = max(r, g, b); Looks very natural to a human. Thing is, as we compute 'cmin', we'll also compute or almost compute 'cmax', so if we rewrite this for a machine, we should merge these two into something that will be way less clear on the first glance. Yet it will be better and make fewer actions (the rest of the conversion is even more interesting, but won't fit into a comment).
- GMoromisato 10mo agoI like this insight, even though I think they are pushing Kernighan's quip a little too far. I take away two ideas: 1. Always be learning. I think everyone believes this, but we often come up with plausible reasons to stick to what we know. This is a good reminder that we should fight that impulse and put in the effort to learn. 2. Always be fearless. This, I think, is the key insight. Fear is easy. We fear the unknown, whether they be APIs or someone else's code. We fear errors, particularly when they have real-world consequences. And we fear complexity, because we think we might not be able to deal with it. But the opposite of fear isn't recklessness, it's confidence. We should be confident that we will figure it out. And even if we don't figure it out, we should be confident that we can revert the code. Face your fears and grow.
- poemxo 10mo agoFear is the mind killer
- rswail 10mo agoIf debugging is the art of removing faults, then programming is the art of putting them in.
- irishcoffee 10mo agoIIRC, the term "debug" came from people literally picking insects out of massive walls of vacuum tubes. Someone can weigh in if I'm mistaken. Also, a "computer" was a human back then, not a machine. I'm not clear on if the term "programming" had been invented at that time or not.
- zahlman 10mo agoEtymonline attests: > program(v.) > 1889, "write program notes" (a sense now obsolete); 1896 as "arrange according to program," from program (n.). > Of computers, "cause to be automatically regulated in a prescribed way" from 1945; this was extended to animals by 1963 in the figurative sense of "to train to behave in a predetermined way;" of humans by 1966. Related: Programmed; programming. and > computer(n.) > 1640s, "one who calculates, a reckoner, one whose occupation is to make arithmetical calculations," agent noun from compute (v.). > Meaning "calculating machine" (of any type) is from 1897; in modern use, "programmable digital electronic device for performing mathematical or logical operations," 1945 under this name (the thing itself was described by 1937 in a theoretical sense as Turing machine). ENIAC (1946) usually is considered the first. The term "debug" also dates to 1945 per Etymonline, but Wikipedia also claims > The term bug, in the sense of defect, dates back at least to 1878 when Thomas Edison wrote "little faults and difficulties" in his inventions as "Bugs". > A popular story from the 1940s is from Admiral Grace Hopper.[1] While she was working on a Mark II computer at Harvard University, her associates discovered a moth stuck in a relay that impeded operation and wrote in a log book "First actual case of a bug being found". Although probably a joke, conflating the two meanings of bug (biological and defect), the story indicates that the term was used in the computer field at that time. So the metaphorical sense previously existed, but was relatively new as applied to computers (since doing anything with computers at all was relatively new). And "computer" did refer to a human, but the modern sense was in the process of being established during the literal-bugs-in-vacuum-tubes era.
- Panzerschrek 10mo agoIf debugging is 2 times harder than writing code we have at least two choices. One suggests to write simpler code. But another one means not debugging code at all, which may be achieved by using a programming language way better than C, which allows fixing (almost) all bugs in compilation time.
- uecker 10mo agoThere is no programming language better than C ;-) Just people not yet experienced enough to have learned this. (Just trolling you back)
- Panzerschrek 10mo ago50 years of widespread C usage has shown that just trying writing without errors using C doesn't work. But surprisingly some people still believe it's possible.
- uecker 10mo agoWriting without errors using other languages also doesn't work. And if you go towards formal verification (which also does not completely avoid errors), C has good tools.
- Panzerschrek 10mo agoBy using a better language you have no errors typical for C which usually require debugging. Logical errors may still happen, but they are easy to identify without even running a debugger.
- uecker 10mo agoFor your comments I get that you drank the Kool Aid, but I see no argument.
- lelanthran 10mo ago
- stodor89 10mo ago[dead]
- mrob 10mo agoWhile I agree with the point about improving skills, I think there's a distinction to be made between artistic code and engineering code. Linus Åkesson writes some exceptionally clever code, but it's artistic code. The cleverness is both essential to the artistic effect and unlikely to break anything important. But I wouldn't want my OS written like that. In engineering code, the only benefit of cleverness is better performance, and the risk is unreliability. My previous computer was a lot slower and it already did everything I need, so I'm willing to sacrifice a lot of performance for reliability. Most software is written so wastefully that it's usually possible to make up for the lost performance without cleverness anyway.
- zahlman 10mo ago> Linus Åkesson writes some exceptionally clever code, but it's artistic code. Thanks. I somehow ignored the URL and the sidebar, and only now made the connection that OP is by the guy who does all that ridiculous C64 tech demo stuff (especially the music).
- teo_zero 10mo agoWhy does everybody confound "twice as hard" with "need to be twice as clever"? Why nobody contemplates twice the time, a team of twice the people, using debugging tools twice as powerful or costing twice?
- vintagedave 10mo agoBecause doubling the people doesn’t halve the difficulty of a problem.
- randallsquared 10mo agoI thought you were serious until very last alternative. Well done!
- commandlinefan 10mo agoFar be it from me to disagree with Kernighan but... when I think of "clever" code, I think of things like Duff's device. That's clever as hell. It's also perfectly debuggable. When I deal with undebuggable code in the wild, it's usually due to people doing things like declaring global (sorry, "public static") variables that connect to live databases and start downloading definition tables into memory before the code can run.
- chimprich 10mo ago> 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.) I think a better assessment of how well you've evolved as a programmer is how simple you can make the code. It takes real intelligence and flair to simplify the problem as much as possible, and then write the code to be boringly simple and easy to follow by a junior developer or AI agent. If you're wielding increasingly clever programming techniques, then you're evolving in the wrong direction.
- cassonmars 10mo agoor you're working in embedded systems, machine learning, cryptography, or any other specialized field where being clever is very important
- amelius 10mo agono
- DamonHD 10mo agoThe best code, eg for embedded systems, is as simple as it can possibly be, to be maintainable and eg to let the compiler optimise it well, possibly across multiple targets. Sometimes very clever is needed, but the scope of that cleverness should always be minimised and weighed against the downsides. Let me tell you about a key method in the root pricing class for the derivs/credit desk of a major international bank that was all very clever ... and wrong ... as was its sole comment ... and not entirely coincidentally that desk has gone and its host brand also...
- immibis 10mo agoSimple code means just doing the thing. It's often misinterpreted to mean code made of lots of small pieces (spaghetti with meatballs code) but this is simply not the case. Often, avoiding abstractions leads to simpler code. At my job we're disqualifying candidates who don't use enough unnecessary classes. I didn't use them, but they proceeded with my interview because I happened to use some other tricks that showed good knowledge of C++. I think the candidate who just wrote the code to solve the task was the best solution, but I'm not in charge of hiring. Without revealing the actual interview task, let's pretend it was to write a program that lowpass filters a .wav file. The answer we're apparently looking for is to read the input into a vector, FFT it, zero out the second half, unFFT it, and write the output file. And you must have a class called FFT, one called File, FrequencyDomainFile, and InverseFFT. Because that's simple logical organization of code, right? Meanwhile, the actual simple way to do it is to open the input and output files, copy the header, and proceed through the file one sample at a time doing a convolution on a ring buffer. This latter way involves less code, less computation, less memory, and is all-around better. If you think the ring buffer is too risky, you can still do a convolution over the whole file loaded into memory, and still come out ahead of the FFT solution. But if you do it this way, we think you didn't use enough abstraction so we reject you. Which is insane. Some time after I got this job, I found out I would have also been rejected if not for a few thoughtful comments, which were apparently some of the very few signals that "this guy knows what he's doing and has chosen not to write classes" rather than "this guy doesn't know how classes work."
- nurettin 10mo agoI am very happy and sad for people who will never debug their own code for days to figure out subtle bugs. Happy because they won't endure the torture, sad because an LLM took away their opportunity to learn and better themselves.
- misja111 10mo ago> Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. It's worse than that. It might not be you who has to debug it, but someone else. Maybe after you left the company already. Maybe at 3AM after a pager alert in production ..
- gaigalas 10mo agoThis whole "clever code" has become a social thing. It's one of the things people say when they don't like some piece of code, but they also can't justify it with a more in-depth explanation on why the cleverness is unecessary/counter-productive/etc. Truth is, we need "clever code". Lots of it. Your OS and browser are full of it, and they would suck even more without that. We also need people willing to work on things that are only possible with "clever code". From this point of view, the idea of the Lever makes sense. The quote also works for criticizing clever code, as long as we follow up with concrete justification (not being abstract about some general god-given rule). In a world where _some clever code is always required_, it makes sense that this quote should work for both scenarios.
- ninkendo 10mo agoIt doesn’t seem to me that it’s required for code that was hard to write, to be hard to debug. What if I spend my cleverness “budget” specifically on making the code easier to debug? Splitting out just the right pieces into generic bits so they can be replaced with debuggable mocks, for instance. You could counter that the word “clever” only applies to hard-to-debug code, but that makes the whole statement rather vacuous, no?
- gregw2 10mo agoI applaud the author for thinking afresh on this topic. I am also comfortable with the closing comments that you can't always dumb down your code or you stagnate and never learn new tricks/techniques. It is a good thing to keep in mind. But I have also seen people waste a lot of their (and others') time trying to be clever in ways which as an outsider from additional context I have I can anticipate won't pan out. And I've let it slide and watched it end "not-well", leading to long unnecessary debugging cycles, missing deadlines, and creating boilerplates of YAGNI abstraction and complexity that didn't "make the easy things easy and the hard things possible" but instead made the easy things complicated. I myself have been accused of that when trying to design optimal "scalable" architectures up front. And I myself have patched over inherited "clever" things with flaws that I handled by adding yet more incremental "cleverness" when, N years later I wish I had just cut the knot of Gordian complexity on day 1. I think Kernighan's Law is perhaps best applied as a cautionary question to ask yourselves or others in the journey: are you getting too clever, and can you (and others around you) really debug the cleverness you are pursuing? Complexity and cleverness may be needed, but have you considered re-approaching the problem from a standpoint that minimizes the need for cleverness? Put another way, there is cleverness that brings "simplicity of code" that does not bring "simplicity of debugging or maintenance" by yourself or others. It's wise to be aware of that. I view cleverness as somewhat like "innovation tokens"... you should "pick a small handful" of them strategically but not overuse them. I don't see that caution in a pure statement of "Kernighan's lever". Also seemingly tacitly ignored in the poster's perspective is any acknowledgement that software is, or can be in a huge chunk of scenarios, a "team sport". It's all fine for you to get more clever by pushing yourself, but if you don't transfer your knowledge/cleverness to the broader development+support group, it isn't good for the organization, and perhaps not even you if you consider your code's value proposition will itself harden and stagnate and get refactored out. (Of course, for some programmers, that's a virtue; write your code in an obscure language/style so that nobody else will take credit or touch it and mess it up. I literally had an acquaintance who, sensing in me a similar competence (or elitism?), boasted to me about his cleverness in doing this at his workplace. I was intrigued, but silently not impressed.)
- dahart 10mo agoIt’s superficially easy to bike-shed on use of clever code and debugging, but there is an interesting and fundamentally difficult question to answer underneath about what to spend your limited time learning, and how to think about it. Yes Kernighan was trying to pass along advice to future programmers about what he thinks is how to reduce unnecessary effort, and yes at the same time spending time debugging difficult code often/ideally increases your skill and avoiding that effort might mean you miss out on developing those skills. Both things are true, so how does one decide which way to go? Of course it depends on your goals, but it’s also worth asking what the opportunity cost is. What if instead of doing battle with complexity and debuggers, you could instead pick up different skills? It is possible that people should deliberately ignore Kernighan’s advice, and use clever code in order to gain the skills and experience needed to see that Kernighan was right. ;) It’s also possible that spending that valuable time learning how to scale to larger systems would pay off. Or, for some people, spending less time coding and more time devoted to other pursuits. The ‘stopped evolving’ comment seems like it might be designed to stir the pot, but the best programmers I’ve ever known tend to work hard at reducing complexity by thinking hard about dependencies and about how to write large systems. They don’t necessarily shy away from high performance tricks or hard problems. It’s possible that what a young programmer means by “clever” and what a very seasoned programmer means by “clever” aren’t the same thing at all. https://www.teamten.com/lawrence/writings/norris-numbers.html https://www.teamten.com/lawrence/writings/norris-numbers.htm...
- foster_nyman 10mo agoThis feels like a learning-theory restatement of the Kernighan quote: the point isn’t “never be clever”, it’s that cleverness is trainable. If you write right at your current ceiling, you reliably create a debugging task that’s a bit above it, and that mismatch becomes the stimulus (and motivation) for skill growth. I think the same lever shows up in writing: drafting is “coding”, editing is “debugging”. If I only write safe/obvious prose, revision stays in the flow zone but I plateau. If I try a structure/argument I can’t quite see the full shape of yet, the rewrite phase hurts, but it’s literally me moving through the next rung. All of which maps pretty cleanly to Vygotsky’s ZPD (the bug report / reader confusion is the scaffold), and it’s also an antidote to Dunning–Kruger: the work keeps falsifying your self-assessment. The “wow, I was wrong” moment is often just evidence your skill bar moved. Caveat: in collaborative/prod contexts you sometimes trade cleverness for maintainability, but if you always do that, you skip the lever.