[HN Gopher] Kernighan's Lever
       ___________________________________________________________________
        
       Kernighan's Lever
        
       Author : xk3
       Score  : 97 points
       Date   : 2025-12-19 21:42 UTC (3 days ago)
        
 (HTM) web link (linusakesson.net)
 (TXT) w3m dump (linusakesson.net)
        
       | zahlman wrote:
       | (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 wrote:
         | My younger self effortlessly wielded clever programming
         | techniques that continuously baffle my current self.
        
       | lupire wrote:
       | This article says nothing of substance.
        
       | userbinator wrote:
       | (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 wrote:
       | This 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 wrote:
         | Yes, 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 wrote:
           | Yes, 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 wrote:
         | Looking 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 wrote:
           | Good 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).
        
             | lucketone wrote:
             | In short your stance is to sacrifice readability for
             | performance.
             | 
             | Legit in some cases. But for usual business software, code
             | is for humans (compiler will make machine code intended for
             | the machine)
        
             | zahlman wrote:
             | Recognizing that sort of opportunity is why we have
             | optimizing compilers and intrinsics.
             | 
             | Funny thing: in Python code I've had a few occasions where
             | I needed both quotient and remainder of an integer
             | division, so naturally I used `divmod` which under the hood
             | can exploit the exact sort of overlap you describe. I get
             | the impression that relatively few Python programmers are
             | familiar with `divmod` despite it being a builtin. But also
             | it really doesn't end up mattering anyway once you have to
             | slog through all the object-indirection and bytecode-
             | interpretation overhead. (It seems that it's actually
             | slower given the overhead of looking up and calling a
             | function. But I actually feel like invoking `divmod` is
             | more intention-revealing.)
        
         | JKCalhoun wrote:
         | Personally, I see a kind of arc in programming style over time.
         | It does begin naive, and more-experienced you will look back at
         | your early code realizing you were essentially re-inventing the
         | wheel in one place or you may see now that a look-up table
         | would have been more efficient (as examples).
         | 
         | As you learn more techniques and more data structures the
         | "cleverness" creeps into your code. To the degree that the
         | cleverness might have a complexity cost, sometimes the cost may
         | be worth it--perhaps not always though.
         | 
         | Naive-you would have struggled to understand some of the
         | shortcuts and optimizations you are leveraging.
         | 
         | But then still more-experienced you revisits the more clever
         | code with years now to have both written and attempted to debug
         | such code. You may now begin to eschew the "clever" to the
         | degree its cleverness makes the code harder to understand or
         | debug. You might swear off recursive code for example--breaking
         | it into two functions where the outer one runs a loop of some
         | sort that is easier to set a break-point in and unwind a
         | problem you were seeing. Or you might now lean more on services
         | provided by the platform you are programing for so you don't
         | have to have your own image cache, your own thread manager,
         | etc.
         | 
         | I feel like in that last stage, most-experienced you may well
         | be writing code that naive-you could have understood and
         | learned from.
        
       | GMoromisato wrote:
       | I 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.
        
       | rswail wrote:
       | If debugging is the art of removing faults, then programming is
       | the art of putting them in.
        
         | irishcoffee wrote:
         | IIRC, 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 wrote:
           | Etymonline 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 wrote:
       | If 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 wrote:
         | There is no programming language better than C ;-) Just people
         | not yet experienced enough to have learned this. (Just trolling
         | you back)
        
           | Panzerschrek wrote:
           | 50 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 wrote:
             | Writing 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 wrote:
               | By 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 wrote:
               | For your comments I get that you drank the Kool Aid, but
               | I see no argument.
        
             | lelanthran wrote:
             | > 50 years of widespread C usage has shown that just trying
             | writing without errors using C doesn't work.
             | 
             | Millions upon millions of C code, over decades, controlled
             | (and still control) things around you that would kill you,
             | or similar catastrophic failure. Cars, microwaves,
             | industrial machinery, munitions, aircraft systems ... with
             | so few errors attributable to C that I can only think of
             | one prominent example.
             | 
             | So sure, you can get bugs written in C. In practice, the
             | development process is more important to fault-reduction
             | than the language chosen. And yes, I speak from a place of
             | experience, having spent considerable parts of my career in
             | embedded systems.
        
         | zahlman wrote:
         | It's honestly strange to me that people still believe that
         | things like type systems and effect systems and borrow checkers
         | can actually _do_ that. At least, without spoiling the features
         | that make compile-time detection preferable in the first place.
        
       | mrob wrote:
       | While I agree with the point about improving skills, I think
       | there's a distinction to be made between artistic code and
       | engineering code. Linus Akesson 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 wrote:
         | > Linus Akesson 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 wrote:
       | Why 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 wrote:
         | Because doubling the people doesn't halve the difficulty of a
         | problem.
        
         | randallsquared wrote:
         | I thought you were serious until very last alternative. Well
         | done!
        
         | commandlinefan wrote:
         | Far 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 wrote:
       | > 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 wrote:
         | or you're working in embedded systems, machine learning,
         | cryptography, or any other specialized field where being clever
         | is very important
        
           | amelius wrote:
           | no
        
           | DamonHD wrote:
           | The 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 wrote:
             | Simple 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."
        
               | zahlman wrote:
               | > Often, avoiding abstractions leads to simpler code....
               | But if you do it this way, we think you didn't use enough
               | abstraction so we reject you.
               | 
               | I think you've unwittingly bought into your hiring team's
               | fallacy that classes are somehow essential to
               | "abstraction". They are not. Wikipedia:
               | 
               | > Abstraction is the process of generalizing rules and
               | concepts from specific examples, literal (real or
               | concrete) signifiers, first principles, or other methods.
               | The result of the process, an abstraction, is a concept
               | that acts as a common noun for all subordinate concepts
               | and connects any related concepts as a group, field, or
               | category.[1]
               | 
               | The fundamental abstraction in computer programs is the
               | _function_. A class is principally a means of
               | _combination_ that sometimes incidentally creates a
               | useful (but relatively complex) abstraction, by modeling
               | some domain object. But the most natural expression of a
               | "generalized rule" is of course the thing that takes some
               | inputs and directly computes an output from them.
               | 
               | Of course, we also abstract when we assign semantics to
               | some part of the program state, for example by using an
               | enumeration rather than an integer. But in that case we
               | are doing it in reverse; we have already noticed that the
               | cases can be generalized as integers, and then
               | explicitly... enumerate what it is that we're
               | generalizing.
               | 
               | (The reason that "FFT" etc. classes are so grating is
               | that the process of that computation hardly makes sense
               | to model; the input and output do, but both of these are
               | just semantic interpretations of a sequence of values.
               | You could staple a runtime "time-domain" or "frequency-
               | domain" type to those sequences; but the pipeline is so
               | simple that there is never a real opportunity for
               | confusion, nor reason for runtime introspection. I almost
               | wonder if the hiring team comes from a Java background,
               | where classes are required to hold the code?)
               | 
               | If I were writing the convolution, it would still
               | probably involve quite a few functions, because I like to
               | make my functions as short as feasible, hewing closely to
               | SRP. Perhaps the ring buffer would be a class -- because
               | that would allow a good way to separate the logic of
               | accessing the underlying array slots that make the ring
               | buffer work, from the logic of actually using the ring
               | buffer to do the convolution.
               | 
               | (I'm not sure offhand what you'd need to convolve with to
               | get the same result as "zeroing out the second half" of
               | the FFT. I guess a sinc pulse? But the simple
               | convolutions I'd think of doing to implement "low-pass
               | filter" would certainly have a different frequency
               | characteristic.)
        
               | immibis wrote:
               | Well, I substituted the task for a different but related
               | one, so the substitute task is not fully specified in
               | detail and perfectly mathematically correct - just good
               | enough to show the principle.
               | 
               | We have given extra points to a candidate for having an
               | FFT class even though it should obviously be a function.
               | And the comments clearly indicated that candidate simply
               | thought everything should be a class and was skeptical of
               | things not being classes.
        
           | quietbritishjim wrote:
           | Any good rule of thumb like the one in GP's comment is wrong
           | sometimes, and that's ok. Adding more caveats just dilutes it
           | without ever really making it watertight (if you'll forgive
           | the very mixed metaphor).
           | 
           | But even in complex applications, there's still truth to the
           | idea that your code will get simpler over time. Mostly
           | because you might come up with better abstractions so that at
           | least the complex bit is more isolated from the rest of the
           | logic. That way, each chunk of code is individually easier to
           | understand, as is the relationship between them, even if the
           | overall complexity is actually higher.
        
       | nurettin wrote:
       | I 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 wrote:
       | > 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 ..
        
         | anilakar wrote:
         | The company made a choice, conscious or not, to not keep that
         | talent in-house.
        
           | DamonHD wrote:
           | The company often does/did not get to make the choice, at
           | least in my case.
        
           | misja111 wrote:
           | Talent? Not if it was someone who was adding unnecessary
           | complexity to the codebase.
        
       | gaigalas wrote:
       | This 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 wrote:
       | It 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 wrote:
       | I 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 wrote:
       | It'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.htm...
        
       | foster_nyman wrote:
       | This 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.
        
       ___________________________________________________________________
       (page generated 2025-12-22 23:01 UTC)