There was no writing in Eden
I saw the title of this article on YouTube by Andrei Alexandrescu, who is a way smarter software engineer than me (and probably you). I'm not a religious person, but this expression caught my eye, because in his video he talks about the same ideas and conclusions that I reached to a couple of years ago.
So what does it mean "there was no writing in Eden"? It describes the ideal world, the ideal paradise where people don't age, have perfect cognition and they don't forget anything, hence they do not need to write down anything.
But for us, mere mortals, we do have intellectual limits, and we do need to write things down to remember them in the future, because writing is a form of abstraction and abstractions are the crutch of the human mind, or as how Nietzsche puts it: "Every concept originates through equating the unequal."
The human mind cannot individually remember and categorize everything it experiences. Abstraction solves that problem by grouping particular things into general concepts. We need abstractions, because our mind is weak and consciously seeking out abstractions is what makes us human.
The complexity of computer hardware passed the point of what our minds were able to deal with in the early 80s. There is no single human, no matter how smart or genius they are, to be able to comprehend every bits and pieces of computer hardware. That's why we invented abstractions to still be able to reason with this technology, abstractions such as programming languages and software concepts in general.
Fast forward to the late 90s and early 2000s, complexity of software started to creep up, yet again, on our "weak" minds, and again, we invented more abstractions and more concepts in the quest to understand this complexity, concepts like software patterns, Extreme Programming (XP), unit tests, source code version control, and so on.
LLMs are nothing, but yet another step in the journey to harness complexity.
The hallmark of a good software engineer, besides Googling more efficiently than the rest of us, is defining better abstractions than their collegues to work with complexity in a more optimal way.
LLMs are the amalgamation of all this knowledge compressed down into comprehensible abstractions, that we, mortals, can reason about.
Whoever says that software engineering is dead, is assuming that we are in Eden, that we don't need to write down things anymore, because the AI's knowledge is infinite and can solve infinitely complex problems. But, data shows, that the LLMs context window and reasoning capacity is limited, just like the human mind, albeit it's much larger.
AI, just like us, need good abstractions, because abstractions are the "grouping of loosely similar things", it's the compression layer of the "context window". This is why a lot of developers are having a bad time getting good results from LLMs because they don't do enough upfront planning and define good abstractions that these models can use.
You can't have an infinitely precise specification because then why would you need AI at all? And you can't really "one-shot prompt" or vibe code your way into good software either because it's like having no specifications at all.
The middle of the chart above is where good software engineers shine.
How to do that?
It might seem simple, but it's not. This is where that "art" part, in programming, comes in.
In a nutshell, high and ultra-high reasoning "expensive" models should be used with clear upfront abstractions to plan and review the specifications and the codebase.
The optimized specification should have a "common language" grounded in the abstraction, it should be also simple for the developers to review.
Then, a low- to medium-reasoning "cheaper" model as the "executor" of the task. Forget about skills and ADRs and "LLM-optimized" comments. The context window is still (as of today) matters and it's still around 200k tokens, so don't overflow it. How? Write better abstractions and smaller specs.
The "executor" implements the spec, and more importantly, the loop goes back to the "expensive" model for review, until the spec is considered implemented.
Finally, the human reviews the results. The human should always be the last stop in the flow. Rince and repeat.
If, the spec isn't clear, it should go back for further refinement. If the abstraction cannot be reasoned about, it should be either broken down into smaller specs or be implemented manually by the developer.
That's about it, there is no magic. It's just a tool, and don't fall into the "Eden Fallacy".