Generating Code Is Cheap, Engineering Is Not

Sometime around the middle of this year, I got careless. I have worked in software engineering for almost two decades. I have also worked with LLMs for several years. Still, I thought I could just vibe-code my way into building something great.
I wanted to build a skill that turns a codebase into a predictable draw.io architecture diagram. The agent would read the codebase and show me a quick ASCII diagram preview in the terminal. Once I approved it, the skill would generate the real draw.io file. Deterministic checks should keep the result stable.
I solved many problems along the way. Node placement was perfect, in the ASCII preview as well as in draw.io, in both horizontal and vertical layout. The checks kept the output stable. Both views failed at the same point: routing the edges.
I spent days building my own routing rules before I asked the obvious question: had someone already solved this? They had, years ago. The Eclipse Layout Kernel (ELK) exists for exactly this problem. Mermaid offers it as a layout, and draw.io now offers it as a layout option in its menu. Today my skill hands the routing to the draw.io CLI, and the edges come out right.
The second lesson was smaller but hit harder. I had never used the right domain language. I talked about shapes, connectors, routes, and waypoints. I never used the higher-level terms, nodes and edges. But nodes and edges are the vocabulary every layout engine is written in.
I lost several days. Still, it was a useful reminder. AI can make writing code much easier. But it does not replace the fundamentals of good software engineering. None of this was the agent’s fault. I had skipped the engineering. That is the trap when something new arrives: we get so focused on a new technology that we forget the skills we already have. The technology is new. How we build good software is not.
My failure had nothing to do with the code itself. Around the same idea, a debate was running on X. Mario Zechner shared an article by Senko: “Code was never the hard part” is an insult to all programmers. Senko’s conclusion goes horizontally. Learn more about user experience, customers, product, and business. Understand everything around the code it takes to deliver useful software. I agree with that. Emad Ghorbaninia put the other half more sharply in a reply:
Code was never the hard part: was always true for senior engineers and always false for the industry that hired juniors to write boilerplate for a decade. AI didn’t insult programmers, it just made that gap impossible to hide anymore.
Both are right about the diagnosis: the typing was never the whole job. But I would take the conclusion in a different direction. My own conclusion goes vertically. AI has changed the job. I think we now work one level higher in engineering. From up there, we look straight down at the software. But we also see what happens left and right of it: the users, the product, the business.
As AI takes over more of the implementation work, developers need to move from writing the code to designing and orchestrating the systems it lives in. And we need to define the rules and constraints AI has to work within.
The two directions do not compete. Engineers need to understand more of the world around the software, and at the same time get better at designing and controlling the systems that build it.
The Fundamentals Still Matter
None of this means programming was easy before. Turning requirements into good, working software took a huge amount of time and skill. Architects, tech leads, and senior and principal engineers already designed systems and made technical decisions. They chose patterns and tools and set the direction. AI does not remove that work. If anything, it raises the stakes: a design decision now turns into working code within minutes, wrong or not. What changes is the implementation underneath: much more of it can now be generated.
Developers are moving one level up. We increasingly act as system designers, leads, reviewers, and orchestrators. AI handles more of the implementation. But generating code and knowing how to build software are still not the same thing. People who have spent decades in software engineering did not just spend that time learning how to write code.
They learned how to solve hard problems and understand complex systems. That means choosing the right approach, making technical decisions, managing trade-offs, debugging, and keeping software maintainable over time. AI is now compressing the implementation part, and that makes the difference much more visible.
Concurrency and parallelism are a good example. They are related, but they are not the same thing. As Rob Pike put it, “Concurrency is not parallelism.” And in the age of AI, you may not even be the one who decides to use one of them. An agent might suggest it as part of its plan.
But then you need to understand these concepts yourself. If you see something like this in a plan, you should be able to question it and understand why the agent proposes it. Learn what it means if you do not know it yet, and decide whether it makes sense instead of blindly accepting it.
The same applies to many other concepts. The AI community often creates new jargon for ideas that have existed in software engineering for years. I come back to three examples below.
I like seeing people still learn the fundamentals in the age of AI and try to understand them instead of skipping them.
The Developer Role Is Changing
Our job is becoming more about designing the system. A lot of what AI makes easier today is repetitive work. Many experienced engineers did not enjoy doing it anyway. That is a good thing. More verification will most likely move towards tests, automated checks, and better tooling. Metrics and observability will help us understand what is happening and improve these systems over time.
But understanding still matters. We need to know what these signals tell us. Then we judge them against the rules and expectations we have defined. We do it at a different level, with much less manual checking of the code itself.
The industry Emad describes, the one that hired juniors for boilerplate, now needs to drop the idea that cheap code means easy engineering. More of the repetitive work around writing and verifying code can be automated. We will probably develop new tools and standards around this over time. Eventually, we may mainly define the contracts and structure, while the LLM handles most of the implementation.
Even before AI, I worked this way a lot. In TypeScript, I designed systems and products around types, interfaces, and signatures. Then I programmed against those contracts. I also mostly wrote tests up front, so I knew roughly which direction the code had to go.
Looking back, that was a good approach. It was a mix of contract-first design and test-driven development. The difference today: agents can take over much of the implementation behind those contracts.
Robert C. Martin (@unclebobmartin) on X: Clean code still matters, because the agents can get just as confused as humans do. […] agents can get completely tangled up if the code is tangled up.
Without a mindset of learning, even old software engineering concepts can feel new. The only thing that changed is the context: agents and AI systems.
Many of the newer terms are good examples of this. Graph-Engineering is state machines or workflows. Loop-Engineering is loops, retries, and control flow. And Harness-Engineering is the execution layer around agents with tools, checks, evals, and context. These are not completely new concepts. We use them in a new context and with a different mindset.
Much of this is software engineering we have been doing for years. It is now applied in the context of agents. Maybe you kept learning along the way and stayed curious. Maybe you did not spend your whole career holding on to a single language or framework. Then many of these ideas will already feel familiar.
And again: maybe you have never taken the hard path of learning how software is built, or you are still avoiding it. Then you risk becoming just another developer with a skill set that is increasingly common. Take the hard path, solve the hard problems, and give yourself a reason to stand out.
I think AI is not just an accelerator. It also gives us the chance to build and experiment with things that often did not happen before. They took too much time, cost too much, or people did not want to take the risk. The draw.io skill is one example; I have built several things like it around AI that I would not have started otherwise. And yes, this also means we can produce much more code.
Where Do the Next Senior Engineers Come From?
I also think LLMs can be an excellent learning buddy. You can ask questions, explore concepts, and get feedback almost immediately. But building things from scratch still matters. Struggle with something, break it, and fix it yourself. That is still one of the best ways to understand how it works.
AI has made it much easier for juniors and non-developers to get a prototype running quickly. Even a small, fully working application is within reach. And that is a great thing. We can turn ideas into something real much faster.
The problems usually start when that prototype needs to become a larger product. It has to support more users and use cases and stay maintainable over time. That is where deeper engineering experience becomes much more important. Experienced engineers often need to step in and stabilize the system. They make the architectural decisions and engineer what was built in a hurry.
This also raises a question: if juniors write less boilerplate themselves, where will the next generation of senior engineers come from? I do not think the answer is that juniors stop learning.
The way they learn will probably change. Instead of learning mainly by writing everything from scratch, they can learn by reviewing AI-generated code. They question decisions, change things, debug failures, experiment, and understand why something works or does not. They should still build things themselves and make mistakes. But AI may expose them to more problems and more iterations in a shorter amount of time.
I see the difference every day. Give an experienced developer a solid codebase, a clear understanding of the project and product, well-thought-out skills and rules, and the ability to use AI effectively. The improvement in both quality and productivity can be huge.
Unfortunately, I also see the opposite. Put the same tools on a weak foundation, without enough experience or the right guidance, and they quickly create more problems than they solve. And this does not only affect juniors. Many senior developers are still struggling to adapt their experience and thinking to this new way of working.
Lack of time, room to experiment, training, and the wrong incentives can all play a role. And not everyone needs to become an AI power user either. It depends on the role and what you need AI for. For some, this could end in resignation. They stop trying to adapt at all. If you are interested in that topic, this is worth reading: “AI Adoption Is a Myth”.
Why Pushing the Limits Matters
I learned a lot from my failures. The last lesson came late. I found Archify, an agent skill for architecture diagrams that covers most of what I had wanted in my vibe-coding opening. The agent produces a typed JSON description of the architecture, and Archify compiles it deterministically into HTML and SVG, with schema, layout, and route checks built in.
It takes the opposite path on the one problem that cost me days: it does not route the edges with a layout engine, the agent decides the routes and Archify only verifies them. And it does not produce draw.io files, which was the whole point of my skill.
Finding the right library is harder than it sounds, and checking whether it already exists is part of the engineering. Failures like this build the expert knowledge you will need later. What matters is knowing what you are doing, recognizing when you have gone too far, and stepping back then.
I experiment a lot, and I read a lot about AI and the ecosystem around it. Yes, I mean reading it myself. I do not want AI to summarize for me because that is where part of the fun stops for me. Instead, I often use AI to help me understand the important 20 percent of a large topic, a library, or a scientific paper on arxiv.org.
As engineers we should be careful not to delegate all of our thinking and reasoning to the LLM. If AI does all the exploration, reasoning, reading, and decision-making for us, how do we keep our own skills sharp?
You do not have to do everything manually. Automate what can be automated: with deterministic scripts, agent skills, or a mix of both. That frees up time for the parts that need thinking. For me, AI should help me think and learn faster, not remove the need to think.
Pushing the limits means experimenting a lot and reading everything I can get my hands on. It means building things, breaking things, and finding out what works. Sometimes you go too far or build something that was the wrong approach. That is part of it. The tools change constantly. So you have to keep exploring, learning, and finding better ways to use them.
I believe good and successful products will continue to need experienced engineers. Even the best LLMs can generate and change huge amounts of code. Keeping a codebase healthy and maintainable over the long term still requires experience, judgment, and a deep understanding of the system.
I am curious how others see this transition. How is your role changing, what are you already doing differently, and what do you think we still need to figure out? I would love to hear your experiences and thoughts.
TLDR
- Generating code is becoming cheap. Good engineering is not.
- Programming was never easy, and AI should not make us forget that.
- AI moves more of the work to a higher level: system design, architecture, judgment, verification, and orchestration.
- Fundamentals still matter: concurrency, parallelism, debugging, trade-offs, and maintainability.
- The same tools on a weak foundation can create more problems than they solve.
- Graph-Engineering, Loop-Engineering, Harness-Engineering: familiar software engineering concepts in a new agent context.
- Experiment, push the limits, and learn from failures, but know when to step back.
- The tools will keep changing. What makes the difference is the willingness to learn, adapt, and understand the hard parts.
Thanks to Mario Zechner (@badlogicgames), who originally shared Senko’s article and led me down this rabbit hole. Thanks also to Emad Ghorbaninia (@emadgnia), whose reply got me thinking about the topic from another angle. A special mention goes to Robert C. Martin (Author of Clean Code) (@unclebobmartin). He has spent more than five decades in software engineering. I find it interesting to see how deeply he engages with AI, experiments with it, and thinks about what it means for building software. And a special thanks to Benjamin Matthijs, Sebastian Bonk, Thenmalar Nagarasu, Wycliffe Maina, Andrei Gătej, Santosh Yadav and Armen Vardanyan. They took the time to read early drafts of this article, challenged some of my thoughts, and gave me valuable feedback. It made the article better.
One last note: I used AI to help me write and improve this article. I had written this note before and deleted it again, because I was not sure how people would react. Then I read Ryan Carniato’s My AI Content Journey, and it gave me the courage to say it openly. Today I work the way he started out. I write the whole draft myself. Then I ask AI for feedback, review its suggestions, and brainstorm with it where I get stuck.
I am highly neurodivergent, and my mind tends toward constant cognitive activity. AI helps me channel that into something structured. Four years of working with LLMs have made me noticeably better at expressing my thoughts clearly. I am grateful that this technology exists, because it opens up possibilities for people like me that were not there before.
Some people think writing or improving articles with AI is the easy way. It still requires a huge amount of cognitive effort. I put a lot of thought and care into making sure the final text still feels authentic and sounds like me. At work, we speak English exclusively. Writing at this level is a completely different challenge.