Chapter 3: A philosophically practical assessment of generative AI
In this chapter, I want to talk about AI in action: how it works and why it works that way. Since my expertise is programming, I'm gonna talk about that, but as I said, I do try to explain things as much as possible so you can translate them to your own field of work, whatever it is. This chapter covers a large portion of the concepts I aimed to discuss. The other chapters are complementary, foundational, or just different aspects that are worth viewing.
Introduction
Sometimes when people are talking about the downsides of using gen AI in programming, they mention things that are not issues with the nature of AI, but rather with its "current state." People used to say AI couldn't even make a simple script when GPT 3.5 came out, and they were right. I have used AI in programming since the release of ChatGPT. I remember that even a single script for a simple task could be so buggy and bad that it wasn't worth using. It was mostly useful for quick questions or summaries. Even nine months ago, when I wanted to use simple voice-to-text in a non-English language, the available tools were either nonexistent or expensive.
Now there are free models that run easily on your own machine, and they're pretty decent too. There are AI tools that can create a whole website, even a game, if you will. The issue was that we didn't understand the nature of AI. The weakness that we saw was just the state of LLMs at that point, which has improved ever since. This is why I'm telling you that we need philosophy, and this is why I talked about the existence of the soul: it changes how you predict the future.
"bad" doesn't mean the same thing to an LLM
When it comes to programming, most of the time—if not all the time—your choices and preferences are all about "maintenance". Think of your programming language. Why does it exist? It exists because you don't want to write machine code. We made Assembly to avoid writing 0s and 1s, then we made C to avoid writing Assembly, then we made Python to avoid writing a lot of low-level stuff in C, such as an HTTP server, to save a ton of time (I'm explaining things in simple terms). Think of your libraries, your tools, and your best practices.
A lot of the things that you do and use revolve around the single premise of "maintenance": doing things faster, more reliably, and so on. It's not like Python does something that you can't do with C at all; it's just more maintainable for certain tasks. When you're refactoring, it's not like you're doing something unnecessary. You're aligned with whatever you've been doing the whole time you were coding.
That's why "bad" doesn't mean the same thing to AI as it does to us. When we say code is badly written, what we mean is that it's not readable enough for humans. I, as a human, can't read that code. In the same way, when we say code is buggy, we mean it's buggy to humans; to the computer, it works, just differently. When we say this language is bad for this job, or that codebase is unmaintainable or even unscalable, we're saying those things in relation to humans.
Now, it is true that some of these issues might translate to AI as well, but you gotta know that AI has capabilities that no human has. For example, it can currently write hundreds of times faster than a human. It can digest and read a lot more than humans. It can start working on a very large codebase right away, while it takes a human a significant amount of time to get to know the codebase and start working.
Let's say you wrote a text that is really hard to read. You may have seen those contests where people write the most unreadable code. You can write surprisingly small pieces of code that take you days, even weeks, to understand. But to AI, that's a piece of cake: it reads the code, connects all the dots, and gives you a thorough explanation of what each part does. It's a machine, in the end; in the same way you can't compete with a bot in reading websites, you can't say that bad means the same to both of you.
The reason why we say the AI model produced bad code is that we humans can't read, maintain, or scale it. Sometimes the AI can't do that as efficiently either (which is something that can absolutely improve), but a question remains: Do you even need to do any of those anymore?
Software engineering degree
The thing is, software engineering isn't really a university field. I mean, technically it is, but what I mean is that it's not one of those fields like medicine or architecture where academic education is necessary for you to enter the industry as a freelancer. In fact, most of the time, it isn't necessary at all. People judge you based on your résumé and put you through a series of theoretical and practical interviews to see for themselves how knowledgeable and experienced you are.
There are two reasons for this, and neither of them is that "software engineering is an easy or unimportant job." It's true that someone's life can be at risk if you practice medicine without the proper qualifications. But don't forget that for thousands of years, humans were essentially doing medicine and architecture through what we'd now call "freelancing." These were the same people who built the Pyramids of Giza. In fact, even Andrej Karpathy himself was talking about this in one of his videos. He said that, in his opinion, software engineering could actually be a more important problem than autonomous driving because it has a much larger surface area. Driving only makes up a small part of your life.
The first reason is that the immediate risk is lower. In some professions, a single mistake can ruin someone's life. But even that isn't enough of a reason when you look at the previous point. You don't necessarily have to see the consequences of your work immediately or directly in order to connect the two. This is especially true when you consider that medicine has existed since before civilization itself, while software engineering hasn't even existed for a hundred years. Still, this is a reason that has made those professions seem more important as candidates for becoming formal academic disciplines, and I'm not arguing against that.
The main reason is that we simply didn't want to formalize the field. The lack of immediate risk made software engineering seem unimportant enough that we could lower the cost of entry. And that directly caused something: we have very few precise, standardized rules for the field.
As an architect or a doctor, you have a very specific and documented way of doing things, often built up over hundreds of years and gradually refined. Every edge case, every unusual situation, and every path you're supposed to take is documented. If something hasn't been documented somewhere, people publish another paper about it, reach some kind of consensus, and eventually incorporate it into the standard way of doing things.
Programming could have been exactly the same. The reason it isn't is that we simply didn't care enough to make it that way. We don't have a handful of extremely prestigious and authoritative institutions or professional bodies that collectively decide, "This is how this part of the industry should work," and then put the entire profession under their microscope. If we had wanted to, we could have done it.
Another reason could be that programming is a fairly new topic. Computers were invented less than 100 years ago, while medicine has been practiced and studied since the dawn of Homo sapiens. We simply have too little information and too little time to know what we're actually doing.
Now, if you think about this for a moment, you start to notice a contradiction. So far, we've established that fields like medicine are highly reproducible. The whole reason you study them academically is that humanity has arrived at a set of blueprints, and everyone keeps repeating those blueprints until someone proves that they're wrong.
Programming is almost the opposite. Everyone is doing things in their own way. Even at the AAA level, you don't necessarily see the same workflow from one team to another. There isn't one universally accepted blueprint for how software should be designed, developed, tested, maintained, and shipped, even within one specific type of project.
So why is it that fields like medicine and architecture haven't been "replaced" by AI before programming?
SWE and mechanical programming
The basic phases of software development are:
- Preparation: requirements, specifications, design and milestones
- Implementation: programming, testing, refactoring, repeat
- Publishing: packaging, deploying
- Maintenance: bug fixes, refactoring, new features
In The Pragmatic Programmer, the sixth chapter ("While You Are Coding") begins with these two paragraphs:
Conventional wisdom says that once a project is in the coding phase, the work is mostly mechanical, transcribing the design into executable statements. We think that this attitude is the single biggest reason that many programs are ugly, inefficient, poorly structured, unmaintainable, and just plain wrong.
Coding is not mechanical. If it were, all the CASE tools that people pinned their hopes on in the early 1980s would have replaced programmers long ago. There are decisions to be made every minute—decisions that require careful thought and judgment if the resulting program is to enjoy a long, accurate, and productive life.
If I could quote this whole chapter, I would have. Awesome book.
Let's first explain what "mechanical" means here:
"without thinking about what you are doing, especially because you do something often" - Cambridge Dictionary
Mechanical programming is programming without thinking. Occasionally, you need to do things that don't need constant thinking and designing. The typing itself can be considered programming. Once you have memorized where each key is, you don't think about it anymore. In the same way, once you learn a programming language's syntax (or even a human language's grammar), you don't keep thinking about them; you just do them. Once you learn to drive and get used to it, you don't actively keep thinking about it; you do it mechanically. This is mechanical work. You're on autopilot.
It's not always mundane work, though. Sometimes you've done a specific project so many times that you've simply memorized everything about it. It's similar to a souls-like player who has memorized every pattern and is defeating bosses with ease.
Programming in general is not mechanical, and this is one reason I wrote Software engineering degree. This job has too many aspects to it for us to be able to even name them. You can test this: go find a senior dev, commission them to create a medium-sized project, then ask them to give you a comprehensive handbook on all the specifications of the project, what they're gonna implement, which files they would create, and so on. Ask them to write down absolutely everything they're gonna do. You'll face one of these results:
- They try to do it, write a literal book, and spend a huge amount of time doing so, but still fail to make it perfect.
- They tell you it's impossible to do it perfectly.
The reason senior developers tell you they can't do it is that people misunderstand the preparation phase: they think you can specify everything. You just have to think really hard and list all the specs. This misunderstanding comes from two perspectives:
- The business perspective
- The AI development perspective
The business mindset requires you to be as concrete as possible. When money comes into play, you'd want to minimize risk as much as possible without hurting your product, brand, or future. Money is hard to earn and easy to spend. This makes business people, managers, CEOs, investors, and everyone else think that you must specify everything beforehand and give concrete milestones. This assures them economic security. In Software engineering degree I explained how much more mechanical jobs like electrical engineering are, yet they haven't been replaced. This is because the managers can visibly see what happens when you ignore the nature of a job. But they don't see that in software; even worse, they blame the developers. I'll talk about this later.
When working with AI agents, it's best to know every little thing beforehand. The more clearly you specify the project beforehand, the better the results are. That's why there are popular skills like "grill me," which asks you questions about the design before planning and implementation, helping you agree on clear requirements and reduce errors and mismatches. People like to think that you can specify everything before you start coding because they want to claim that the rest is mechanical work and therefore AI can do this repetitive job better than a human.
Limitations to mechanical programming
To understand how AI works in programming, we first have to understand what programming was like before AI: the nature of each role, how problems were fixed, how systems were designed, and so on. This is a big topic, and I don't claim to know everything about it, let alone be able to mention it all in a book like this. But I try my best (as I did) to solidify the concepts needed.
There are a couple of issues that prevent us from going on autopilot and programming mechanically, and I will try to name all the important ones. But beware: they're not independent; each one can affect the other one, so take them as a whole.
1. Human cognitive limitations
There are a couple of limitations that come from the human brain itself.
1.1. Incapability to keep track of everything
A major limitation is that the human brain simply isn't capable of keeping track of all the information involved in a non-trivial project. There are too many variables and constraints: requirements, resource limitations, programming-language constraints, deployment conditions, use cases, target audience, architecture, existing code, dependencies, performance, security concerns, and so on.
And these aren't independent. Changing one decision can affect several others, which means the developer has to constantly reason about interactions between them. Documentation can preserve information, but it doesn't eliminate the need for someone to understand it.
1.2. You don't know, you can't explain
A human interaction can be simplified like this ("->" means "goes through"):
Person A's brain -> Person A's (understanding of) language -> Person B's (understanding of) language -> Person B's brain
A lot of the concepts, feelings, and desires get changed when they go from one mind to another. You might think that both of you are speaking the same language, but there is a sea of minor differences—usually caused by different life experiences and belief systems—that change how the person in front of you understands you. Words themselves are much more limited than thoughts. And thoughts don't always represent understandings because you usually think in words. This is essentially why we often don't understand each other, why we talk to each other and argue, why we fight, why we explain, and so on. In each step, the initial concepts that were in Person A's brain have been reduced. In the end, only a portion of the original thought is transmitted.
When someone wants you to develop software, that person's understanding of what software even is is limited. This limited understanding goes through the filter of language and gets even more limited. Then it goes through your understanding of language and translates into concepts and understandings. The end result is much different software. And this is yet again limited by your understanding of how that software is going to be expressed in the language of the machine.
All of this means that both you and the contractor don't know beforehand what you want. You form your understanding of the software along the way. The biggest reason why a senior dev is appreciated is the intuition they have. This, combined with their knowledge, helps them do things the way a junior might never do from the beginning.
2. Ambiguous requirements
A very important and big job of software engineers is translating human words and concepts into code language. Employers don't know how a computer works. Their skewed understanding of a computer leads them to have false expectations. This is true for most freelance jobs. There's nothing wrong with the employers; it's just how the world works.
The contractor might come to you with this beloved idea of theirs. They have already invested some emotions in the idea. You have to be careful and research thoroughly to warn them beforehand about what can and can't be implemented. It's not only about what they can implement, though, but also about what benefits them. Sometimes you have to disagree for their own sake and only proceed if they insist on their perspective despite your explanations. And even then, you might want to find a way to make it safer and better while not disrespecting their direct request.
To understand what they want and discuss it with them, you need a deep understanding of both worlds: both the soft skills and the hard skills. I mean, if AI were as good as a human at soft skills, it would be considered a fully sentient being, wouldn't it? This leads to that whole talk about the AI apocalypse and how one does not prepare for it. Anyway, human interaction is not something you can go on autopilot for.
3. Ever-changing set of requirements
Remember I was talking about how specifications can't be completed perfectly beforehand? This is one of the biggest reasons why. Even if you make the most complete set of specs—a handbook of everything to be implemented—you'll get a set of changes once you develop the product and show it to the contractor or manager. The limitation is not just how clearly they can explain what they want, but also what they want in general. They might not really know what they want in terms of the product. They might be chasing a feeling.
Part of your job is guessing what they need. It's not really an explainable skill, let alone making it mechanical. You have to gain experience from talking to different people and contractors to develop this intuition for what they really need beneath their words. You may not implement those findings, but knowing them helps you choose an architecture that would allow you to switch easily when they suddenly change their minds. If you take what they say for granted, you will not be as safe as you could have been, and they will reject you. You would blame them for not being direct, while another senior would read their minds and become their idea of a good programmer.
Another part of your job is dealing with unexpected changes: they may suddenly demand something you should have known about when you started, and now you aren't prepared. This is mostly a human problem you have to fix, not just a technical problem you can solve mechanically. I mean, if you could make all human interactions mechanical too, wouldn't that mean you're calling yourself a literal robot?
4. No universally correct answer
There is no universally correct answer to many issues and trade-offs. There might be one if we treated software development as an academic discipline, but for now, the answer depends heavily on the developer's opinion. This leads me to a new topic:
Humans are opinionated
One key distinction between humans and AI, in my opinion, is that humans are simply opinionated, and this is true for all fields. Humans are opinionated in the sense that they form their own understanding of the world, the meaning and concept of their jobs, how they should implement and do stuff, and so on.
This may convey that the developer doesn't create an objectively good product. But it's not necessarily the case. The reason is that, as I said multiple times, we don't know the ins and outs of development. There isn't a bible for all the scenarios and how you should approach them. There might not even be a single source of truth, which is the most plausible case (for example, for each operating system, we have multiple programming languages to develop apps with). So it comes down to the expertise and preferences of the developer.
Being opinionated means that we can hire an expert who might actively refuse to do what we tell them because they don't want us to ruin our lives with our choices when we're unfamiliar with their expertise. You can argue that we can simply ask AI to disagree with us when it feels like we're wrong, but I think this shows a lack of understanding of—or ignorance toward—how AI works.
AI is this almighty being that's supposed to answer everyone. The same ChatGPT you use to rant about someone is being used by that person to rant about you. Think of all chatbot instances as one person: this person is supposed to answer everyone. For this person to be of use to everyone (hence the term AGI), he must be as unopinionated as possible. That means being the most neutral and average person you can meet. If you ask AI not to be so obedient, it will not work as perfectly as the phrase implies. The AI model wouldn't suddenly gain an opinion about your web dev project. It would try to adopt the most plausible stereotype and answer based on that, because otherwise, how could it know what opinion it should have when it's designed not to take sides? If we made LLMs opinionated, it would directly affect their quality. A biased LLM is not useful to everyone. It wouldn't be "general."
This is also the reason we have these agent skills such as Ponytail (which essentially makes the agent act like a tired senior developer that just wants to get the job done as fast as possible). We try to mimic being opinionated, while a human brain can do it way better.
Humans become responsible
This is one of my strongest opinion against replacing experts with AI. In the previous section, I explained how humans being opinionated helps you have a cleaner product than just slop that verifies your own delusions. But here I want to dwell on an important topic that I feel people forget when talking about AI in action.
There's no doubt that AI has significantly impacted the industry. This means it has challenged things we took for granted for decades, if not thousands of years. Fundamental worldviews are being refactored, and you have to be aware of this process; otherwise, you'll be biased.
One thing we've forgotten is that we used to make products with people.
Let's go back to when gen AI wasn't a thing. You want to develop a product, an application, and you have no technical abilities. You probably have only management skills, an idea, and a bucket of money. Of course, your only option is to hire people. Now, depending on the scale of your project and how familiar you are with the dev cycle, you might hire just one developer or a couple of developers, or you might build a whole technology department and assign tech leads, product managers and a CTO.
In the first scenario, where you hire a single developer to design a web app or something, what makes you trust them not to waste your money? Well, there are a couple of factors:
- the contract. You clearly mention what you want from them. If they don't develop it, you can sue. The fear of justice will make them do things. But what if you weren't articulate enough? You'd definitely miss a ton of things in the beginning (remember, I told you that you can't 100% specify the whole project beforehand?). So how do you trust them not to do just the bare minimum and leave? This brings me to the second factor:
- you trust their reputation. This is pretty self-explanatory. You have been told that this developer is a nice person who does everything you want and even more than they're paid to do, and won't scam you. But what if you don't have this source of trust? I mean, you definitely have it to some extent, but it might not be enough. They might simply be acting like they know something. This brings me to the last source of trust:
- you trust the person as a whole. You talk to that person, get to know how nice and respectful they are, look up their résumé, maybe even check their social media, and get a good feeling that they're the right person. You might also rely on word of mouth. Your brother suggested him to you? Then he's definitely safe. The fact that the law applies to them as a human being helps too. You know that, even if you are betrayed, you can do something about it.
The same mindset applies to other scenarios as well. You hire a tech lead, a senior, or a group of seniors because they're reputable and you can trust them to handle the project better. By hiring a group of them, you minimize the risk of one of them betraying you before you know it.
This is what I think is missing. We forgot that we trusted our process because we simply trusted the people. That's the benefit of modernity, of societies.
Now we have AI, a tool we take for granted and trust with our whole lives. What happens if AI suddenly ruins your whole company? You can't do anything about it. And it's not just about the rare occasions when something unfortunate happens; it's also that you can replace the humans you hire. If you contract someone and they ruin your project, you can terminate the contract and find someone better. What do you do when Claude makes mistakes? You can't just replace it with another model and call it a day. Your options are limited because you're trusting a non-human, a machine that cannot be sued, even if it harmed you to the tune of tens of millions of dollars. AI is not your tool; it's essentially your new employee that didn't sign a contract. Is that something you'd call safe as an investor?
code is a liability, not an asset. - Software Engineering at Google by Titus Winters, Tom Manshreck, Hyrum Wright
AI is your new employee
A frustrating thing I have noticed is an underlying contradiction in people's claims and tweets. I don't mind if you think AI has made SWE obsolete, but be responsible for your thoughts. Some people tell you they have replaced a million senior devs with five mid-level devs and AI, but they never say that AI is their new employee. Instead, they claim it's just an awesome tool and blame you for not using it. Understand the difference between a tool and a new employee; otherwise, it looks like you're running away from questions such as "If it's your employee, has it signed a contract?"
Deterministic vs indeterministic
Deterministic means the outcome is completely fixed by prior conditions—given those conditions, no other outcome was possible. For example, if you let go of an apple 1 meter above the ground—with no other factors, such as a strong wind—it falls. It was determined to fall because of gravity. Free will, for example, is the opposite of determinism: you can't choose your actions because they were predetermined for you.
Programming was deterministic before the rise of gen AI. Let's say you wrote a simple script, and when you run it, it gives you an error. Can you say the language caused it to fail? Can you say the computer caused it to fail? No, the computer was doing exactly what it was made for. You're the one who wrote a buggy script. You're the one responsible. The programming language and the compiler are deterministic. That's why, when you face bugs, you're almost certain that you've done something bad, not that the output is randomly generated and it will differ if you run it again. You'll get the same error forever, no matter how many times you run it (there are some special conditions too, but you get the idea).
The reason the programming language you use is deterministic is that it was designed intentionally. When you print a simple "hello world," everything from the syntax of your language to the codebase of the compiler and the machine code itself was designed intentionally over the years. The output is deterministic because it goes through a series of logical processes that explain exactly why it does what it does.
AI is practically indeterministic. Yes, of course, the people who develop these models are very educated and they know what they're doing, but that doesn't mean they're fully aware of every little aspect of the end state. The model itself works based on probabilities. There isn't a logical process that transforms the input into the output. Unlike deterministic tools, the output isn't "the result of the input." When you type 2+2 and hit enter on a calculator, the result is always 4 unless something about the device is broken. In AI, 2+2 could result in anything because the LLM looks at "2+2" the same way it looks at "how do I cure back pain": it only knows tokens and generates the next most plausible tokens. It IS dependent on the input, but it isn't deterministic about its output. In the same way, the human brain is not deterministic either.
The outcome bias
I want to talk about determinism in programming, but first I have to explain something called the resulting fallacy, or the outcome bias: judging the quality of a decision based on the result it generated. The issue with this mindset is that we are ignorant of the actual cause of the outcome. We assume that the outcome is caused by that decision, but we haven't yet proved it. This can cause severe misjudgments. The whole philosophy of racism and sexism is based on this exact fallacy:
"Statistically, Black people are a minority of the population and are responsible for the majority of crimes; therefore, Black people are criminal by nature." The reason why it's wrong isn't that we have the wrong statistics (though it could be the case depending on the time period you're living in). The data clearly shows this gap. But that's just it: a dataset. To connect that data to the nature of Black people, you need a whole set of judgments. To explain this, let me get a little deeper into the philosophy of reasoning and argument.
You might have studied in school that each argument has three components:
- The premises: a set of facts or accepted truths
- The conclusion: the result of those premises
- The inference: a logical connection between the premises and the conclusion
Example:
- All humans are mortal.
- Plato is a human.
- Therefore, Plato is mortal.
The inference is not something subjective; it's a purely mathematical and mechanical connection, and it's where the fallacies shine. If all humans are mortal and Plato is human, then there's no way Plato is not mortal. If Plato could be immortal, then not all humans are mortal.
The premises are either scientific facts or previously agreed-upon facts. For example, the sentence "Plato is mortal" itself can be taken as a premise for another argument.
Also, there must be more than one premise. Even if you seemingly conclude something from one premise, you're still using another premise that is hidden and common sense, in order to draw a conclusion. This is because the first premise is a statement itself. It's a fact. We have to add something to it to generate a new fact. For example, you might say, "When I drop water on this pot, it gets vaporized; therefore, it's hot," and it has a single premise (the pot vaporized the water), but there's also a hidden common sense behind it that says something like "Any pot on a turned-on oven that vaporizes water is hot."
The conclusion can't be wrong if both the premises and the inference are correct. If it turned out that the conclusion is wrong, we have to start questioning either of those. So as I said, if we find out that Plato is immortal, then the most plausible culprit is that we took "all humans are mortal" for granted while it wasn't true.
Now going back to racism, what's the argument?
Premises:
- Most of the crimes are committed by Black people
- ?
Conclusion:
- Black people are criminal by nature
There are a ton of assumptions being made in between. The so-called "nature of Black people" here means having different skin pigments (or it could go deeper than that. Trust me, racists themselves don't even know what they really mean). The person making this argument connected a physical trait (skin color) to a mental one (committing a crime) because they wanted to reach that conclusion. The second premise would practically be: "Any overrepresentation in crime statistics reflects an innate, biological tendency of that race."
It's very obvious how wrong this argument is once you unravel this premise, but the person making it kept that premise intentionally hidden, leaving you with pure mathematical statistics that you cannot disprove.
Programming was deterministic
Some engineers are struggling to adapt to using agents because they are not used to being outcome oriented. - Sam Lambert, 2026
The thing that makes a senior programmer is understanding of—and respect for—the way that programs become complex very quickly and programming in such a way as to minimize that problem. - Jonathan Blow, ?
If you don't know why something works, you wouldn't know why it stopped working. - The Pragmatic Programmer by David Thomas & Andy Hunt, 1999
Computers themselves are, of course, mechanical. They're deterministic, they work in a very specific and logical way. Even random number generation has some algorithms to it (which causes a whole lot of security issues). Everything about a computer is designed at some point by some people. That's why a computer is predictable.
People who got into programming often liked this predictability. They have relied on this mentality their whole lives. The thing is, even though computers are designed predictably, they're still fascinating to programmers. It kind of feels like magic to make a piece of rock play your sophisticated video game. As programmers, we're used to that, but we still thrive on the idea of creating something that benefits people through a 10-by-20-centimeter screen, from a distance. I said this not to talk about AI ruining the joy of programming (that's another topic I'll talk about later), but to show that if you take away this part of programming, you'll leave us with a black box we don't understand anymore. The reason we understood this complex machine and could make absolutely mind-blowing products was that we, as programmers, always relied on its rules and how it works.
A big part of being a senior is the instinct you develop. You gain experience over the years as you learn, do projects, and face various problems, honing this instinct. That's why I mentioned that Jonathan Blow quote. Before that sentence, he was talking about how a mere "problem solver" does not necessarily mean you're a senior programmer because you can solve relatively small problems as a junior, too. As a senior programmer, you solve issues way before they happen. You gain this powerful eye on the future, seeing what could go wrong if you do this or that. You feel it in your body when you're doing something risky, hacky, wrong. That's why senior devs are tasked with designing architecture and reviewing code. They do this not just to write cleaner code, but also to look for bad architecture and unmaintainable spots in the product.
Most of these experiences are not learned through lectures, for three reasons:
- Finding a reliable source of knowledge that you can understand is not easy. Referring to Software engineering degree.
- It might not even be explainable. As a senior, your biggest weapon is your intuition, and intuition is not always easily explainable.
- You need first-hand experience to actually learn. If you've done any sort of self-teaching, you know you won't learn until you "practice." If you doomscroll through drawing videos, that doesn't make you a better artist (speaking from experience too). It might be possible to learn everything through theory and not forget it easily, but it's really damn hard. For most people, if you stop practicing, you forget. You can already find a lot of videos about programmers forgetting how to write code in the programming language they have used for years, just because they installed GitHub Copilot.
AI development, on the other hand, is completely outcome-based. There isn't documentation that tells you what each input generates. The people who claim to know how it works are describing their own experiences. To understand this, I can give an obvious comparison:
Let's say you wrote a script completely by hand. Can you tell me what each word you put in the script does? What exact role does each word in your script have, and how does it contribute to the result of the program (the result of running it)? If you're a pragmatic programmer, you definitely can. Even if the script becomes so big that you forget some of it, you still know why you wrote each part when you wrote it. You can't just change "class" to "category" because the words are synonyms in literature.
But if you aren't a pragmatic programmer, you don't. You're doing what The Pragmatic Programmer refers to as "programming by coincidence," I love that term.
When prompting, you lose this luxury. As much as AI diehards love to claim they have authority over their creation, they really don't have it as much as programmers do. As an AI engineer (someone who works with AI agents to create products), can you really say how each word of your prompt correlates with the AI output? Can you really show me what happens if you change "help" to "aid"? Can you really prove what happens if you remove a dot? Because it does matter. In programming, a single dot can cause an error or a bug. Most of the time, if you give the exact same prompt to the same model and harness, you get almost identical results, but if you change the prompt, the result can visibly change. So each word does matter. Why wouldn't it? Remember, the computer itself that is running the model is deterministic. The mathematical operations and weights defined for an LLM are deterministic (whether constant or dynamic). So the output should technically be deterministic. When random number generation is deterministic, then AI output is deterministic too. But the only thing that's not keeping up is your own understanding of what happens under the hood. You only partially get it back by wasting thousands of hours experimenting with a specific model. AI is deterministic in theory but indeterministic in practice.
To show how different it is, consider this situation: let's say you don't know anything about programming, and you want to learn the Python language. You put a bunch of constraints on yourself as a challenge:
- No searching
- No looking up documentation
- Only pure experimentation
The only way you're allowed to learn this language is to fire up Python, start typing and try to learn. You type something, press Enter, and it shows you something, you observe it, and repeat. Eventually, you may or may not learn to create a very basic hello world app. It would take you many hours, if not days or even months. This is outcome-based learning. You never learn how Python works, you only learn what working with it looks like. You might even become better than a newcomer after wasting thousands of hours. But the difference between you and someone who just started learning it the correct way is that when something gets messed up, your only option is to start experimenting again until you may or may not find an answer. "Oops, the user database got deleted, let me experiment and see what happened... Oops, the admin database got deleted too". This way of learning and approaching a task is exactly how AI development works. That's also why it's extremely hard and time-consuming to get good and effective at vibe coding.
But as a programmer, you not only have the option to just test things; you also have a ton of information available to find the exact answer, sometimes even before running it!
AI developers might claim that the authority you lose because of this lack of determinism doesn't matter, but they overlook a lot of downsides, which I'll discuss in the next section.
On the effects of AI on the industry
AI has already changed a lot of things about programming and the industry. This effect could be directly related to AI, or indirectly related (scapegoats for example). One thing worth knowing is that these downsides are all connected and intensify each other.
1. Speed is being misinterpreted
Average AI output is about 100 tokens per second. There are models that generate up to 2,000 TPS, and the average speed of a human developer is about 5 TPS. These numbers alone are not enough to compare speed, because AI writes faster but fails faster too, so more time is spent fixing bugs and finding mismatches. Human developers, by contrast, spend a significant amount of time thinking and analyzing the situation and the codebase. Overall, you can see how much faster and more cost-effective AI is compared to human developers—or that's what the hype wants you to think.
AI is not only intelligent, but also fast. This changes the game from a business perspective, and I'm talking about the effects at the individual level as well as at the level of large corporations.
For example, it costs very little, almost (or sometimes exactly) nothing, to develop a prototype. You don't need to waste resources (time, energy, money, etc.) on a prototype that is meant to be a one-time thing to test an idea.
But another concept inferred from AI being fast is that "it's so fast that we can risk more" (in production). Of course, when you can do something really fast, the cost of failure is not really as important as before. But this is a biased mindset, and I have three reasons for it:
- Not all risks are immediate. What if your product turns out to be actually good, and now you can't just halt the whole thing and tell everybody, "Hey, it turns out you liked our product, so we're taking it down to rebuild it from scratch, properly and risk-free!" The common answer to this argument is, "Well, you can vibe-code the production project in a few days too," but this argument is essentially based on the premise that all risks are immediate. I understand some people think they can build relatively risk-free projects in a very short time, but that's another topic that we have to discuss. Right now, the long-term risk is mostly ignored.
- Success is something people easily forget; failure is something they always remember. If you don't believe that, take a look at Unity. It still hasn't recovered from that one bad choice. If you keep making stuff and keep failing, you will automatically be put into the "slop" category and it's not because of the current anti-AI phase. Back then you physically couldn't make fast stuff. You had to invest a considerable amount of time and energy. This naturally prevented you from creating constant slop and actually put effort into things. Even if you failed, people knew you had tried, and you didn't treat the work as something cheap. But now you just throw things at them and visibly treat them like test subjects to see which project they react to. This would never feel nice to a customer. As a business owner, if your customer finds out you're testing on them, you're doing your job incorrectly. The effectiveness of A/B testing, for example, comes from the fact that the user doesn't know it's happening.
- Failure accumulates, and before you know it, there is a mountain of things that are going wrong and you don't know why. I will talk about this in rollbacks and the triple debt.
2. Making software engineering even more stressful
Dr. Alok Kanojia, also known as Dr. K, is the psychiatrist I've followed most closely. There have been times when his YouTube videos completely changed my mindset and the way I was living.
One of his videos is called "Why Software Devs Keep Burning Out" (which I highly recommend, especially if you are or want to be a developer). He starts the video with the statistical fact that SWE is among the jobs with the highest suicide rates. Inspired by this video and my own experiences, I'm gonna talk about what I think is the core reason for stress and burnout in software engineering.
If you've ever been to a therapist or watched videos about sleep problems (Dr. K has some, too), you know that there's a direct connection between how productive you've been in your day and how well you're able to sleep. This is burned into our DNA at this point. The whole point of our lives is to be productive because that's the most valuable thing for society; hence, it's perhaps the only way we can give value to ourselves. You can test this, too: go through a whole day being unproductive, watching reels all day. Then, when you want to sleep at night, you realize you can't and have to lie in bed for hours before falling asleep. If you do the same but are productive even a little—say, for 30 minutes before bed—that helps immensely.
This is also the whole thing about "loving your job". Every job is hard. No job becomes easy or looks like a video game. But there's a difference between a job whose every aspect you absolutely hate and a job that makes you tired but leaves you feeling productive. The reason why the term "corporate job" is used as a negative term is that most of these jobs give you no feeling of being productive. You're just making some product for some higher manager that wants to show off their ideas and get promoted and so on (you can read a lot of these in the comment section of Dr. K's video). You've got to have some feeling of ownership, of partnership, to feel like you're "doing something". Not just wasting time. Even if you waste time, you should at least get something in return—not just money, but experience and knowledge, too. If you get none of that, you'll hate your job and burn out pretty soon.
Programming and development have a fundamental productivity issue: they're too result-oriented. Sometimes you find that you've been working on a project for a week, a month, or even several months, but on the surface, the project hasn't changed at all (for example, if it's a website, it still looks the same). Sometimes you see that the backend hasn't changed either, and no feature has been added. You've just cleaned up the code so that in the future you'll "run into fewer problems" (also known as refactoring). Getting a sense of productivity and reward from this is very difficult. If you happen to have a programmer friend and you see them sitting and coding until 4 AM, the reason is that they're waiting to reach some kind of result so they can feel satisfied enough to go to bed (though there are other reasons too).
You may have seen inspirational sayings like "the journey is what matters, not the destination." It's really misleading when it comes to programming. Don't get me wrong, I absolutely love the process and act of programming myself. But I wouldn't love it if I didn't reach any goals and felt like I'd done nothing. As a programmer, you often find yourself raging over a bug because you've wasted a lot of hours on it and it's not being fixed. You don't rage at the roadside because you don't see a cow or something; you can just enjoy whatever happens. But in programming you can't force yourself to enjoy a literal problem. I mean, if you can enjoy that, there's absolutely nothing in the world that can make you unhappy.
This comes from a very important concept in programming and development in general: you don't know. When you write a script, most of the time you're not intentionally writing buggy code. You're doing whatever you think is correct. Your whole mindset is that "I'm doing this the right way." You might even be super sure about what you just wrote or changed. But then you run the program, and all of a sudden there are a thousand and one errors being thrown at you. You might eventually fix them, but the issue is that it's literally against your comfort zone by nature. It's always contradicting you, telling you directly, "You've done a bad job; you did something wrong." And it refuses to work as intended until you fix it. You can ignore a bug or error (game devs are used to even shipping games that show errors), but what I'm trying to say is that it never feels nice. You can manipulate yourself into thinking you enjoy it, but I'm sorry, that's just Stockholm syndrome. The fact is, you enjoy the journey only because you care about the destination. Without it, all these bugs just become a burden to you.
I intentionally named that concept "you don't know" to tell you about an even more frustrating nature of programming: when you face bugs, you don't know why they happened in the first place or how long it will take to fix them. It's really damn hard to develop a sense for the length each bug takes you to fix, because sometimes it's just deeper than you thought. Do you know how stressful it feels to work in such a field? When you have deadlines and a single bug can ruin your timing?
It gets even worse when you realize that it's not just bugs but the program itself, too. As you gain more experience, you will develop an innate feeling and understanding of how long things will take you to develop. But in the end, unless you've done the same project with the same scope, you really can't be sure how long it would take you. And it's not as simple as researching it and finding out. Sometimes you need to do it first. This is because the bottleneck you're afraid of is placed deep within the project timeline and is not something that a simple research or prototype can show. There are methods, however, such as the tracer bullet method (discussed in The Pragmatic Programmer); but these methods don't always guarantee you safety.
And when you think it can't be worse, it gets worse. As you see in Dr. K's video, one of the most common reasons devs burn out is that they are being set up to fail. In the video he talks about how the scope and timeline of a project always change in software development. Six weeks before launch, the CEO watches a podcast and suddenly asks you to add this and that feature or completely change how you work because a new AI tool has been released. And if you fail to do it, you're the one who's blamed for it. And worse, if you succeed by working overtime and hurting your body and sleep schedule, the norm changes. They suddenly expect more from you. The video discusses remote work and much more, which can make this even worse.
But one thing that I wanna add to this is that it's not just about changing features and timelines now, but also about ruining your skillset. The more you offload your work to AI, the more you'll forget your skills. I will explain this more, but to wrap it up, what happens is that you get weaker, your programs become more buggy, and when it fails, you don't have anyone to blame, not even yourself. This causes a lot of stress and burnout in the short or long term. This is especially true in a work environment where you have responsibilities.
Because of bad expectations and management, AI has ruined the good parts of the job and left us with the worst parts. The reason we felt confident accepting hard projects was that we had authority over them. We could accept deadlines with much more confidence. We knew why everything was created. We created it. Even if we weren't involved from the beginning and were given a pre-existing codebase, we could at least blame the previous developers by running a little git blame and showing managers why the bug had been there from the beginning or why the legacy codebase was a limitation. Now everyone is claiming that "software is solved," so if you fail to do something, then you definitely have a skill issue. In Humans become responsible I explained how the managers trusted the people working on their projects. It doesn't feel economically safe to trust AI with your project. This is where it backfires. You're responsible for what AI generates (one answer to this is "just read the code," but we'll talk about that later).
And it's not just about responsibilities. As I explained, the reason we endured all the downsides of our profession (being against productivity and all that) was that we enjoyed what we created. We felt ownership over the result. Instead of creating things, our whole job has become "finding bugs and issues that we didn't make but we're responsible for." Fixing issues that shouldn't exist never feels productive. If the project is yours, the idea and everything, that can be a little different. But if you're doing work for someone, then you're just a human AI wrapper. You're acting like a punching bag when AI makes bugs and the contractor or manager wants to blame someone. I'm sorry, but this is just the recipe to burnout.
3. Only code generation has sped up
There's a great video by Adam Bender, a principal engineer at Google, in which he talks about AI and its future. It's an absolute gem of a video.
One of the key concepts he talks about is that there are many aspects, both social and technical, to each software project. AI has sped up only some parts, while other parts are still slow. For example, code generation has sped up tenfold, but code review has not (for those who care about code review). This leads us to conclude that humans are the bottleneck. "And humans do funny things when they're under pressure" (he's talking about the pressure of being a bottleneck). And I can't agree more.
Programming is hard; programming without the feeling of productivity is harder; and programming while feeling unproductive AND feeling like you're slowing down the team/company is the worst. It's like every little corner of this system is draining you and you don't truly know why you're doing this. This is also very scary when you're hired to do something. You'd think, "if they find out I'm slowing them down, they'll fire me". And this stress makes you burn out real fast.
And even if you don't feel like you're the bottleneck, you'd still feel like bad because AI has not only made your job easier, but it has made it worse. Your own body, your energy, your time, none of them have been increased tenfold. But the expectations did.
There's a comment under that video that I really liked, and it was basically saying that "humans are not the bottleneck, rather the rate limiter". The job of a rate limiter is to limit each user so they don't overload the system. The same applies to programming. Humans are not the bottleneck; they're the ones keeping everything structured. This requires a mindset that says "software engineering is not just programming and implementing features, but most importantly, designing a system that scales and is maintainable". Unfortunately, this mindset is not something all managers know and respect enough. Sometimes they legitimately expect you to ship a prototype because it looks too polished to them (especially in the age of AI). So you'd end up being set up for failure and be blamed for it.
4. Rollbacks
With speed comes responsibility. - agentic aunt may
"AI is an amplifier." DORA said this, and I think this is the most accurate representation of the nature of AI. The thing is, you may have successfully sped up your workflow, but now you've also increased your chances of failure. If you used to face 10 errors each day, now you face 100. It sounds like this part belongs to effect No. 3, but the reason I said it here is that the bugs accumulate. You're coding faster and merging faster, or even worse, shipping faster. If there's a bug in a previous version, you might find out much later, depending on how many bug reports you receive.
Back then, because you were developing more slowly, a lot of these bugs were naturally found sooner. This allowed you to have a safer approach. You could simply fix it without breaking too many things or roll back more safely. The thing about rollbacks is that they're risky most of the time. If you've changed the structure of something (say, the database itself), you can't just roll back and call it a day. User information could be lost.
And now, before anyone notices, you have developed a million more features. Maybe you have even relied on the bug working. So finding your bugs later would result in a lot of wasted time and money.
This might sound like a one-in-a-million scenario to you if you're inexperienced, but the more experience you gain, the less safe you feel. It's like that famous quote that the more you know, the more you understand that you don't know. A junior might write code that's awful. It works, but that's it; it only works in that moment. As a senior, you see those code smells and your intuition warns you that you MUST NOT let that slide. Even if you deliberately keep some code smells and bugs, you must be aware of them so you don't assume the project works perfectly and accumulate more issues. And this rollback issue, alongside other issues mentioned, doesn't really feel safe.
5.1. You don't learn anymore
One of the things that worries me most about offloading coding to AI is that it can really hurt your growth. So let me explain what I mean by giving you an example of a process that people who do AI development go through:
You start a new project. You may even be a programmer yourself, but you don't know the tools you want to use in this project. And you certainly haven't done this exact type of project before.
You download Claude Code.
You may jump right into implementation with a brief explanation, or, if you're experienced enough, you may first design the system and architecture as much as you can. You may chat for half an hour with AI, fine-tuning the specs as much as you can, or you may even do some coding too. You try to make good soil—the perfect foundation for AI to build upon. This may even take days or weeks to manage due to the topic and tools being somewhat new to you.
You run the agents, the frontier models, with the agentic workflow you created for them. They thrive, but you pause to read the code. You want to have a deep understanding of the project because you're a pragmatic programmer who's going to be held accountable for what they created.
Funny enough, you find errors in the generated code too: technical, cognitive, or intent issues. You address them one by one and tell Claude to memorize them. You write them in the project's ADR or CLAUDE.md file so the same issue never happens again.
You repeat this process, and at some point you realize a bunch of things at the same time:
- The project is getting harder to understand. You are a programmer, you're even a senior in other fields, you may have made an objectively perfect foundation for the project too. But there are many things you have to learn just by reading the code. These include the programming language, the frameworks, the tools, and the project type itself. You know it's possible to learn them all at once, but at the very least, you need time.
- The AI is becoming better. The more it works on the project, the better it becomes. It always follows the conventions at this point. And it's becoming increasingly harder to detect the flaws. You know that at some point, the project becomes big enough that you wouldn't be able to track what's connected to what. The AI clearly sees the connections much better than you because, let's be honest, It's a machine. It can recite 10 scripts without a single missing comma. Your brain is limited; you can't understand what's going on in 10,000 lines of code when all you've done is review it.
- You feel like you're the bottleneck. The model can completely overhaul the project in 20 hours, and you're wasting almost all of it by putting pauses in-between to review and learn.
You repeat the process more, and at some point you think, "What the hell am I doing here?" You lose your purpose in what you're doing. You don't feel like you've done anything at all. You're just slowing the progress down, and it's taking significantly longer than the deadline you anticipated. It feels like you almost gained no speed boost.
You gradually stop reading the code and let Claude do everything. You've officially become the human Claude wrapper.
By the way, you also have a lot of free time because you've offloaded everything to AI. You go wash the dishes and think to yourself, "I'm washing the dishes and AI is doing my job. It was supposed to be vice versa." Existential crisis says hi to you.
This is the exact process everyone goes through. If you're coming from different fields and are not quite familiar with SWE, you might say, "Well, don't use AI to this extent in fields and topics you haven't worked with before," expecting the developer to first learn those things and then use AI to automate them. But this suggestion shows a fundamental lack of understanding of—or ignorance toward—what being a programmer means. Unless you're a remarkable human being, you almost certainly don't know many things. There are many languages that you definitely don't know, many tools that you don't know, and many projects you really haven't tried, even as a senior developer with many years of experience! Just recently I watched a video from Google engineers, and one of them—Aja Hammerly—literally said that she's always working with ADK (a Google framework) without knowing the syntax: "I generate all that code." Unless you have a very fixed job and don't get laid off and everything goes as planned, you're going to jump between a lot of tools and stacks. Being a senior means you learn them super fast and can use each one like a tool and build your experience with them as you go.
And keep in mind, you'd never learn a language completely. After six years of writing in pure Python, I still find out very basic things about it, even about basic keywords. I learned them over the first five years, and I can't remember them all now. And this is the language that I have used the most. This is because you don't need to know everything beforehand. You need to learn them on the fly. But how can you learn on the fly when your cognition gets impaired mid-flight?
I'm not against vibe coding as a job. If you're being paid to vibe code, then in my opinion you're justified to do so. But keep in mind that you're basically being paid to forget your skillset. You're not learning from your job anymore. Maybe you'll learn some high-level things, but that requires working at a really good, experienced company on advanced problems—not working on startup problems as a throwaway employee.
You're not senior in everything
There's also something that I would like to highlight, and it's that seniority isn't just a permanent badge of honor you put on yourself. It's very much true that seniority translates very well to different environments, but in the end, if you've never done web development, you can't really call yourself a senior web developer. Each language, framework, and tool has its own quirks and its own ways of handling tasks, optimizing code, and supporting clean code. You can only call yourself a senior programmer in general. The more closely your experience transfers, the more you can call yourself a senior in that specific field. This is why it's not really fair to say "just don't use AI like that". Especially when the whole premise of AI is that it speeds up your process, enabling you to make software in languages you haven't touched before. Not everyone enters the era of AI engineering with 20 years of full-time software engineering experience and a massive range of tools at hand. What about the juniors then? Oh, and about that...
No juniors, no investment
Yet another very important aspect of AI is that it has completely ruined the industry for the juniors. There's virtually no benefit in hiring junior devs, and this has been the perfect moment for founders to ruin the future of the industry and their companies. How are juniors supposed to gain experience when they're either given AI and expected to offload everything to it or, worse, not hired in the first place? Even as a senior, it's hard to keep your learning journey sharp in this era. The juniors will stay juniors unless they are lucky enough to start their own company and build huge things themselves. Even then, without a mentor, they'd fall very easily into the trap of using AI and gaining false confidence about their skills.
False confidence and imposter syndrome
As for false confidence, one emerging behavior I've noticed is that people are talking about imposter syndrome less often (props to @CodingJesus for bringing this up). Now, this might just be my biased experience (we need real statistics for it), but it explains the situation too: everyone is offloading work to AI, and everyone wants to feel productive because otherwise they don't feel ownership, and that lack of ownership raises a lot of anger in people. You don't feel like you've done anything important; you feel like all these years of experience and expertise mean nothing anymore. Funny enough, imposter syndrome needs some sort of effort to work. Usually a decent amount of effort too. For example, right now, while I'm writing this book, I'm fighting the desire to never make it public, to avoid harsh judgments. But if the work is not done by me, then I can't take harsh judgments personally. When you feel like you didn't put any effort into something, you start to lose the feeling of imposter syndrome too, stepping into the pothole of overconfidence.
Humans need to touch things
As a human, you're very much used to learning things by physically interacting with them. Your whole worldview is based on (and sometimes limited to) your five senses. An infant learns about things by eating them. They're not tasty, it just wants to learn what they are and human mouth is a very sensitive organ. Even concepts are understood because you can relate them to physical things to some extent. Love is experienced through hugging, kissing, and touching. Hatred is experienced through the release of anger hormones, fighting, and yelling.
Even things as abstract as philosophy itself can be explained like this. First of all, language itself (the thing that you use to think with) is interpreted using real things. Secondly, when things become hard to understand and track, what do we do? We talk to ourselves, to other people, we write it down, we try to simulate it in real life. We make it more down to earth.
If you don't touch code, if you never practice, and if you stay sunk deep in your own thoughts, you never really grasp things. You can't expect your brain to suddenly adapt to the "no hands involved" style of programming because technology has introduced a new era again. Even a powerful concept like love gets impaired when you remove all physical interactions. AI is an absolutely mind-blowing tool for learning things. But using it responsibly is very important.
No time to process
You have no time to process any possible input knowledge anymore. In Programming was deterministic I explained how doomscrolling gives you no advantage. Time and practice complement each other to make something stay in your head. If someone flashes a piece of good-quality code to you, you don't learn from it. Even if you manage to read it once, you still need to study it more and practice it hands-on. Your brain needs time and stimuli to save that knowledge as something important, not as something disposable. You can't 10x this one.
5.2. You don't search anymore
One of the things that has brought us both benefit and harm is that AI has mostly replaced every type of "looking for an answer." Back then, when you had bugs and issues, you had to search the internet for an answer. This took a significant amount of time and energy, and you had to go through a ton of irrelevant data to get to your answer.
But now you "waste" much less time. You want an answer, so you ask AI. Some bugs that could take literal weeks to solve and understand now take a few minutes or hours at most. And the result is sometimes even better because you can ask the LLM as much as you want until you completely get it.
But one hidden effect of not searching is that you lose that time to exposure. The "irrelevant data" that you were constantly exposed to was a source of info. I can't count how many times I searched for an issue and found out what I was doing wrong in a completely different topic. For example, I wanted to fix a bug regarding how to use a framework, but while searching for it, I found out that there was this nice feature in the language or framework that I'm using, and I didn't know about it. I was doing it the hard way, thinking it was the only way. It could be the same with AI, but many of these improvements happened because I was following irrelevant info that, well, taught me more than I needed for that problem.
Also, most importantly, the act of working through those bugs helped you build your intuition and knowledge. When you fix a hard bug in two minutes, it naturally feels less important to you. This is just how your brain works. When the difference between the time you spend on a hard bug and an easy bug has been reduced to seconds, then your brain can't distinguish between them. Since both are fixed really fast, your brain's like "Meh. Just another casual thing."
I have to admit that AI is insanely faster at fixing bugs and other issues. With the time left, you can start reading books you didn't have time for before. This would alleviate the lack-of-exposure problem. But here's the catch: due to AI being really fast, expectations have increased significantly. There are numerous studies showing that the amount of work that developers are doing due to AI has not decreased but rather increased (which is called "Jevons' paradox," but it really isn't a paradox). If you have time to spend, you have to spend it on the next project.
And this brings me to my conclusion:
5.3. You're constantly producing
As I explained, with the rise of AI, you're not only doing less work but also doing more. The nature of your job is just "doing things." You just make projects, solve issues, solve bugs, implement this and that. You don't have time to learn. Back then, the friction that searching gave you helped you actually learn some stuff. Now this friction no longer exists, and you're constantly producing—not learning anymore. This is good for the investors right now, but the technical debt will skyrocket in a few years.
Recently (September 2026), a group of prominent mathematicians—including more than two dozen Fields Medalists—published an open letter at mathandai.org titled "A Severe Misalignment of AI in Mathematics." When I read this letter, I could completely understand what was going on and it's quite exactly the same thing that I'm explaining here. Now I'm not a mathematician, but what they're trying to say—which makes sense to me—is that solving an issue is something, learning and growing is another. We're constantly producing and forgetting that the reason why we can produce right now is that we grew up to be like this. Not investing in juniors, not valuing understanding and growth, only thinking about output and other similar things are the reasons why we're gonna have a rough time in the future. The technology might be thriving now, but it can possibly even downgrade us in the future when all the debts catch up.
6. The triple debt
There's a really good article by Margaret-Anne Storey called "From Technical Debt to Cognitive and Intent Debt: Rethinking Software Health in the Age of AI." I highly recommend reading it because it's very much aligned with this book, and she explains the terms and concepts in a much more thorough and professional way.
In this article, she talks about three types of debt in software engineering:
technical debt refers to problems in the code layer, cognitive debt refers to erosion of shared understanding across a team over time, and intent debt refers to a lack of externalized goals, constraints, and rationale that both humans and AI systems need to work safely and efficiently with the codebase. Technical debt makes systems harder to change. Cognitive debt makes systems harder to understand. Intent debt makes it difficult to know what the system is actually for.
— Margaret-Anne Storey, "From Technical Debt to Cognitive and Intent Debt: Rethinking Software Health in the Age of AI," arXiv:2603.22106 (2026), licensed under CC BY 4.0. Formatting adjusted.
And keep in mind that these all influence each other in every way possible.
When you connect the dots in this book to this article, a lot of points emerge. Some examples:
6.1. Cognitive debt and human experience
In Humans need to touch things, we saw how your whole understanding of things is tied to experiencing them. Cognitive debt comes from the same place. This is the cost of abstraction and automation in general. Take a look at current programming languages, for example. You may know how to write C code but not Assembly language. Abstraction has cut you off from this intimate understanding of the system. If there is an issue with the generated assembly code, you're cooked. You've let go of that knowledge long ago. It's not cognitive debt anymore; it's cognitive bankruptcy at this point. There are two reasons we don't care about it anymore, both of which I've discussed: the C-to-Assembly compiler is both deterministic and generated by humans. Therefore our trust comes from the humans responsible for it. This also brings me to the next thing:
6.2. "Stable version" doesn't mean anything if a human isn't involved
I know it sounds wild, but what I'm saying is that the word "stable" doesn't mean the same thing we used to mean. AI generates, AI verifies, AI calls it stable. The authority that you lost, that some people think means nothing, becomes very important here. This matters when you want to build software that will become the foundation of future technology, or software that people need to use to its fullest extent. I already gave you an example in 6.1.: you don't care about the C–Assembly compiler because the compiler has been proven by humans and not some hallucinating code generator. And if you really think AI is that reliable, then you practically mean SWE is dead, and that, again, goes back to the apocalypse argument.
6.3. Tests and technical debt
Why did we write tests back then? Was it to test the line of code you just wrote? Like literally, was it that you wrote a piece of code, then, before running it, you wrote a couple of tests and ran them to make sure they worked? You may not even understand what I mean due to how weird it sounds. But it's how we're relying on tests now.
There are a lot of reasons why we wrote tests, but the core philosophy behind them all was that we want to make sure something that already works keeps on working. And why did we consider that it "was already working"? Because we trusted the human who wrote it: when you write the code, run it, and see that it works, you naturally trust it. The same is true when others write the code and you trust them. If you trust it because AI told you so, you're relying on an unreliable source of truth which on its own is a loop of mistakes (looped argument). When you do things manually, you usually run the program many times in between, very gradually making sure everything is alright. Not after you've written 700 lines of code. This builds trust in you.
Now the verification system is impaired. There's no human to trust, the cognitive and intent debt is thriving, so to not lose the technical debt too, we have resorted to using tests as our first way of making sure something works. But we know it's not enough either, so Quality Assurance has become a very important role. As someone once put it (I don't remember who), people aren't seeking programming advice anymore; they're seeking feedbacks, which they feed back to AI with the instruction, "Fix it all, make no mistakes."
6.4. Blamed for hidden debts
The manager wants you to ship as fast as possible. But to do so, you have to sacrifice a lot and embrace all these debts. And the nature of them makes them hidden. You'd be like, "how did I miss this?", and the manager says "you're fired."
6.5. Specification paradox
Your cognitive understanding of the project grows while you're developing. The same is true of your understanding of its intent, though to a lesser extent. Both are influenced by your technical understanding. This means that your understanding of what the project is and will become is—in fact—connected to the project itself. Yet you're expected to provide a perfect specification before the project starts. That's impossible, so the project becomes unmaintainable, and you're blamed for it.
6.6. Cognitive limitations leading into debts
As I explained in human cognitive limitations, many of the limitations you experience during development are due to the limitations of the human brain and language. Cognitive debt wasn't a thing back then (or wasn't important enough to be mentioned) because now, we're offloading the process to AI and expecting ourselves to keep up with it while we are physically limited.
7. Guilt?
Matt Pocock, a very famous figure in the vibe coding community, has a tweet from September 14 that he pinned to his account (as of writing this) in which he explains that someone took his courses, became an AI person at a company, and now feels guilty for taking his job (Matt went on to say that he's actually proud and all that jazz). While we don't know if it's a real interaction or just a self-promo tweet, I think it's pretty obvious to everyone that it's quite possible. The barrier to entry has been lowered so much that you feel like you haven't done anything, and if you're not falsely confident, you'd feel like an imposter.
And this is actually funny. Compare it to digital art, for example: back then, digital artists were mocked for being lazy for using digital tools instead of doing things by hand. They never felt guilty about it for supposedly "doing nothing and achieving everything." If you've ever done digital art, you know that it requires a lot of effort. If you're a traditional painter who switched to digital, you know that your skill set translates smoothly to the new medium, and you wouldn't be a good digital artist if you didn't have that beforehand. But now everyone feels like coding is solved, programming is solved, and all you have to do is buy some tokens and burn them. You don't feel productive, and you feel like you're immediately at the level of your so-called "teacher."
And to be fair, it's not really some personal, temporary thing either. If you look at the skills in Matt's GitHub, you'd realize that they're not the sort of things you'd understand as a non-programmer. You wouldn't know what TDD is, what a spec is, what code review really is, and so many other concepts that you would only know if you're a programmer; therefore, you wouldn't be able to make them yourself. But you need them to work. The harness that you use works like this too. There are huge system prompts inside Claude that teach it how to be a good programmer and agent, many of which you don't even know exist.
You'd feel guilty because you're not in control of them at all; you're using the knowledge other people honed over years, even decades, to write something. All these "coding is solved" tweets would vanish if you removed all the system prompts and skills (at least as of the current state of AI). This guilt alone is a very good indicator that AI (or, more precisely, AI hype) has changed the industry toward what I have explained in Software becomes dead. This is the price you pay when a market gets democratized to this level.
Dependency hell
One of the things that I learned through these years of programming is that dependency is not something you should take lightly. Each dependency can be a new way to harm yourself and your product. I have already written a blog post about how a dependency ruined one of the most used Telegram features.
Dependency in software is the same as dependency in the real world. Let's say you found a stash of money in your garden. You think to yourself "Where did that money even come from?" You don't find any answer other than "the wind brought it here." You may even think God dropped it if you're religious. So you take the money and use it. It's enough for a week.
Next week you find a similar thing again, surprised by why it happened again, you take it and use it.
This keeps happening. It's been a year. You think to yourself: "Why am I wasting my time in this company when I have free money dropping for me every week?" So you quit your job not knowing that the next week, it's not gonna happen anymore. You didn't know why it kept happening, now you don't know why it stopped happening. You were dependent on that money and now that it's gone, you're cooked.
It's the same as other dependencies as well. They make your energy and mood dependent on them. If you don't smoke for one day, or even a couple of hours, you feel bad. Now your day to day functioning is dependent on that cigarette and you'd even sacrifice necessary things to not lose it. Such as your health.
We, as senior developers, honed this intuition to know that you shouldn't thoughtlessly add new dependencies to your project. You should always be mindful about them and try keeping them as minimal as possible. Because you don't know what happens in the future. Who thought Google itself might one day decide to not support Tenor gif API anymore?
And right now, AI has become the biggest dependency of all software and developers. Your job is dependent on one or a couple of companies that can do whatever they want with it. If one day, for any reason—even political—your AI model ceases to exist, your whole company would collapse. One simple bug is enough to bring you to the depth of dependency hell. This might not feel like an issue now, you still feel safe because you remember a lot of stuff. But at some point when you haven't been coding for years, when there's a lack of senior devs, you'd sacrifice anything to not lose your AI models.
Tokens and dependency hell
Another important aspect is that AI is not perfect, at least not right now. And it will continue to be imperfect for a good while. Every time a new model drops, everyone is making projects with it, saying that they "one-shot" the whole thing: just one prompt, and AI did everything else. This one shot they're talking about is not one shot in the sense that AI does it in one shot; it's one shot in the sense that the operator used only one prompt. They give the AI something called a "goal," then the AI makes a plan for itself, plans some verification system, and keeps trying to make the app until it apparently reaches the goal. It generates code, runs it, encounters errors, edits the code, generates more, and continues. But that's the thing: it still makes errors. This is what imperfection is. Now what happens if you get stuck?
Let's say you vibe-coded an entire platform, and now it's live with tens, hundreds, or thousands of users. Now, if the AI fails, you have to go through the trial-and-error process: giving it feedback, asking it to "fix the problem," and waiting until it gets everything right. But sometimes it gets stuck in a loop, takes a hacky and bad route, and becomes increasingly confused with each turn. You have to babysit it for so long, making sure it's not doing something weird (that's all you can tell). You might run out of tokens. You might have something important to do; maybe some new feature has a deadline for tomorrow, or the day after tomorrow, but you're close to reaching your weekly limit and the bug is important too. So you think to yourself: "OK, this is where I have to put the AI aside and get my hands dirty and fix it myself."
But the thing is, you weren't involved in the project yourself. It's like the first day you were given a large codebase. You have no idea where everything is, and it would take you even longer to fix the problem, so you go back to AI and beg it to fix the issue. Remember, since it's a bug, you can't truly give proper feedback. You yourself might not know why it happened at all; all you can do is illustrate to the AI why and when it happens. And this illustration sometimes takes a huge amount of effort. To turn everything that you see into words, you have to be VERY literate.
Some people believe that the fix to this is code review. But code review is not the answer and I have explained this in the next chapter.
And this is all because you are dependent. AI is your employee, not your tool. A tool never makes you dependent like this. And this employee is one hell of an untrustworthy employee. Even right now—as I'm writing this text—Codex is down with no prior warning. Last night it got down the same way too. Isn't that fun? Playing Russian roulette with your career.
Code review is not the answer
When it comes to how we should use AI as software engineers, there's a wide range of gray opinions: from people who think you should offload all coding and review to AI and only do general purpose stuff like architecture design and team management, to people who think that you should only use AI for the bare minimum.
For those who don't know, code review is the act of reading the code that's been implemented or edited to make sure it follows conventions, is free of bugs, and includes everything we need. Before AI, a senior developer did it to make sure junior developers are merging valid code into the codebase. It was also a good opportunity to mentor the juniors, to teach them that there's more to good code than whether it works.
Regarding whether you should or should not do code review on the AI-generated stuff, there is still no accepted answer. People even change their minds from week to week. And I think this would take a couple of years to settle. Or maybe just a couple of months.
There are a couple of things that I have to say to explain why code review is not the answer, but, once again, these reasons are all related to each other. I just separated them to make it easier to follow and understand.
Overlapping steps
There are three steps to coding: implementing, debugging, and reviewing. These steps are by no means separate. Even while you're adding new features, you're constantly reviewing the code that you've just written and fixing bugs too (the simplest example: you fix typos as you go). It's not like you write 20 long scripts and then start debugging or reviewing them. You do them all at once, and in the end you can have separate phases for debugging and code review as well. And most of the time, even if you're debugging or refactoring the code, you will get a new idea for adding a new feature. Sometimes these new features even play a key role in how the debugging or refactoring goes.
People are treating "code reviews" as if they're activities that require so much more creativity and brainpower than coding itself. While it is true that AI-generated code, when reviewed, has shortcomings and flaws, you must understand that this is a temporary argument based on the current state of AI. If AI could take the role of a coder entirely, leaving you with only code review, then one day it's going to take that job as well. It's already doing a huge amount of code review, refactoring, and debugging itself, too.
I mean, think about it, which part of code review seems bizarre to you? It's just reading and connecting dots. Guess what. AI can do it way better. In Adam Bender's video that I mentioned, there is a section where he talks about how AI understands the big picture better. He asks the audience, can you write a perfect diagram and knowledge graph of the codebase of your company? Can your colleagues do that? I bet none of you can, because there's just too much info to remember. Machines have been surpassing us in this field for years. Even previous AI models were reasonably good at finding connections in a very large codebase.
I was once able to contribute to the Godot engine (manually) without knowing C++ beforehand or having much low-level knowledge at all. AI helped me connect some dots that would have been practically impossible for me to find in such a short time in a codebase this large.
You might say that system and architecture design is still something that AI lacks and can't replace, therefore we still need software engineers. But you have to understand the why. If it's just the current state of AI, then mention it, be aware of it. If you think it's practically impossible for AI to do these jobs, then I'd say you need to rethink why it was able to do all the coding and code review. What if architecture design is a mechanical job too, and AI can do that as well as it improves? If you don't know what the answer to this is, you might get surprised with the future AI models and all the ongoing "System design is solved" tweets.
Due to their overlapping nature, you can't truly omit one without the others. It's like asking the chef to stop cooking (because some AI has automated it) and start giving feedback on the result so that the AI would fix itself. A huge part of the job is defined by doing it. Judging is different from this; this is quality assurance. A judge only gives some instructive feedback and lets the chef do whatever they want with their career and project(s).
If it can do the cooking perfectly, then it might as well do the verification too. If not now, then in a few months or years.
Losing the cognitive understanding
The more you lose touch with the code, the more you lose your understanding of the project. Senior devs did code review, but they did coding too. They were deeply connected to the technical side of things. This not only kept them moving forward by giving them a feeling of satisfaction and ownership, but also helped them not get lazy and lose sight of the project.
As I have said, your brain needs time to process it. The so-called "friction" in your workflow was a driving factor in not forgetting what you just learned. If your whole job is reviewing, you would easily lose many of the nuances in the project. Even if you read every line of code and put a lot of time into code review, you'd still forget it soon. A few weeks is enough for you to completely forget what the project was and how to review the code. Shared understanding and the big picture don't take shape easily.
Resource intensive
There are three levels to code review based on how focused it is:
Skimming
Level one is mostly skimming. You just review some code, or you may not even review the code at all; you rely on the description provided by the developer of what the changes and code are. There are also comments and documentation, which are basically plain text inside code files; these help make skimming faster. Top maintainers who get dozens of new merge requests are like this because there's no way for them to understand even a small amount of that code. And the further you get from the technical details, the harder it becomes to have authority over them. Linus Torvalds, for example, has explicitly said he doesn't read the code except very occasionally: "My job is working with people."
This level ensures you have a rough say in where the application is heading. You can very easily miss many bugs, but that doesn't matter because you trust the employees you have not to silently betray you, lie to you, hallucinate, or do anything like that. They have proven to be good devs, but the trust comes from the human relationship, the same way Linus said that he trusts them because they have been working together for over 20 years. They are reputable to him.
Reasonable
The second level is the most common and reasonable type of code review. You're a developer in touch with the project; you review the code and give feedback from different perspectives.
At this level, you might still miss some issues, such as naming-convention issues, typos, or misuse of tools. The coder might have disregarded some of the best practices, such as the DRY principle (Don't Repeat Yourself). You'd only find a range of issues, not the ones that are harder to detect in a few minutes. You still might read most of the code, but you don't dig deeply because, again, you trust the developer.
Paranoid
The third level is like a paranoid person. You review line by line, request a lot of description, ask the coder why they chose this or that particular approach if you can't infer it from the code, and so on.
There could be various reasons why you would review code like that. Maybe you're interviewing someone, maybe the project is a huge, sensitive project, or maybe you're trying to hate on the person and want to nitpick, etc.
Of these three levels, this level is what makes you truly responsible. It's literally like coding, but instead of coding, you write and understand the whole code as if you had written it. This way, you can be confidently responsible for it when, for example, a higher manager asks you why you let this code pass.
Many developers—from people as prominent as Linus Torvalds to the creator of the Zig language—say that they are facing issues with the amount of code and number of bug fixes being thrown at them. You can ask any developer in a work environment (one that respects code review), and they'll tell you how the amount of code has created problems of its own, forcing them to put some bug fixes and similar things aside so they can dedicate time to more important work.
Zig's owner has even banned vibe-coded merge requests, saying that, with only five developers on the team, reviewing the code costs them a lot of time and causes them to fall behind schedule. But it's not just the time. Two other issues play huge roles in this regard, which, in my opinion, are the overlooked aspects of code review.
Lack of responsibility
Someone contributes to your project. You, as the owner of a project like Zig, put your precious time into reviewing the code. You find some weird choices and seemingly bad decisions, and you don't find them at a glance. You have to really pay attention to find them because the code is working. You ask the contributor, "Why did you implement it this way?" They either ignore you or send your question straight to AI and reply with its answer. Not only is this really rude, but it also shows a lack of responsibility.
The vibe-coder doesn't know anything and hasn't learned anything. All they were doing was producing—just adding features. "If it works, it works." They pass the responsibility to the reviewer by acting as mere operators of the AI agent rather than true contributors.
Code review as an investment
Zig has a philosophy of mentoring those who contribute to its project, helping them grow and become better contributors. It's an investment. The more the developer knows about Zig, the better and more aligned their contributions can be, and therefore the less time it would take to review their code. Over time, they might even be hired as contractors. I think this philosophy is not only very good and essential to large open-source projects, but also something that is directly or indirectly adopted by other projects. But a lack of responsibility makes it pointless and impossible.
Sometimes it's easier to ban it
You can ask contributors to contribute only good AI-generated code. But then it becomes a new task for the developers to verify what good and bad code mean, so it actually makes it more resource-intensive.
Just because AI is helpful doesn't mean it's always manageable. Everything has its own trade-offs. The nature of AI has its own downsides and that can become the bottleneck.
The reason why it takes time
In "Lack of responsibility," I explained how just because the code is working doesn't mean the code is following standards, is scalable, maintainable, and all those sorts of things. And because humans can't trust it, you ought to use the third level of code review: line by line, as if there definitely is an issue. Otherwise, your understanding of what was implemented is limited.
"Why do you care that much?"
It's valid to say that most of the time, if not always, you're gonna develop an imperfect product. And it's alright. Scope creep is not financially viable. Most of the time, you have tight deadlines. The whole industry is built on these imperfections, with people shipping products that haven't been cared for enough. Unless you're paid for it, there's nothing morally or professionally wrong about making a product with suboptimal stability. The world wouldn't end if your product had some issues. Make money; you can perfect it later.
But when it comes to AI, this mindset is comparing human flaws with AI flaws. While I have talked about this topic later in "we used to copy-paste code", it's worth explaining the situation here and being a bit more general.
First, AI flaws are much more random. That's why we call them hallucinations. Terence Tao mentioned in one of his videos that AI is like a really knowledgeable person but a slightly drunk one, and I think this is one of the best depictions. AI hallucinates and may make mistakes anywhere. A human doesn't do that.
Second, when a human finds out what was wrong, they learn a ton from it. They not only learn to avoid that specific problem, but build a ton of patterns around it. To add a cherry on top, they also find patterns in their own belief system, realize why they were facing that issue the other day, and make long-term changes to their mindset. It requires a ton of resources to be this powerful, and the human brain (and body) has been optimized for that.
And third, the devil is in the details. Software, just like many other products, is something that is written layer by layer. Issues accumulate. Debts pile up. As the twig is bent, so is the tree inclined. One simple issue might harm you in the long run in more ways than imaginable. Programming was always about this: tiny adjustments and issues that, when not taken care of, can make the project awful to maintain. The devil is in the details. You can make it exist, then make it perfect. But while you were making it exist, you ruined its future. This is the whole reason why we distinguish between junior and senior. A senior is not just a junior with more dedication.
Shipping with issues
You can ship with issues if you want to, but at least you gotta be mindful of them and aware of the risky points in your project. Even if your awareness is reduced, it's still better than forgetting everything forever. There are enough issues hidden from you already; it's not wise to intentionally hide more.
And to be aware of them, you first have to review the code like a paranoid person. You have to be able to claim the code. And doing that takes a ton of time—enough to make using AI not even worth it at some point. So, to make the use of AI justified, what tends to happen is that people do the second or even the first level of code review, but they frame it only as "I review the code," as if that were enough.
The complexity is exponential
Later in How to use AI properly you'll see how I'm not against the use of AI. I'm not saying that because code review of AI-generated code is too time-consuming to be worth it, you shouldn't use AI for code generation at all. In fact, I do think there's a middle ground.
But there's something about programming: the bigger the codebase becomes, the harder it gets to have a cognitive understanding of it. But this relation is not 1:1; it's exponential. If you make the code changes twice as large, the problems become much more than twice as large. A lot of connections and pain points emerge the more you code. That's why we've always been told to keep the scope of each change small so we can roll back and so on. You can use AI to generate simple things for you, read them line by line, and understand them, but the larger the changes become, the harder it is to actually understand anything.
So what happens is that people lie, both to themselves and to the media. They tell you they're reviewing the code generated by AI, but there's no way, given the context, that they can take in 5x, 10x, or 20x as much code and then review it all and understand it. Even if they review the code perfectly, since they've removed the time, practice, and feeling of accomplishment from the process, they'll soon forget it too. The reason why medical students can take in a lot of information and data is that they study their lessons thoroughly, learn all the patterns, and try to make as much sense of them as possible. They don't just review the documents; they learn them, which takes so much time and energy. Not to mention that they still need to look things up all the time, even at work. You can't just read code all day, pretend that you're focused while experiencing no feeling of reward, and then claim that you have reviewed the code. You've just swept the dirt under the rug. It's better than nothing, but not a suitable solution.
Code review doesn't remove dependency
Code review doesn't remove the dependency described in Tokens and dependency hell. You might think these issues matter only when the AI model keeps failing, but that is exactly when reviewing the code provides the least help. If a bug appears, you still have to rely on the model to diagnose and fix it. If it loops, you waste time and tokens while the deadline gets closer.
Let's say you vibe-coded an entire platform and now it's live with tens, hundreds, or thousands of users. You may have reviewed the code, but if you weren't involved in building the project, you're still like someone seeing a large codebase for the first time. You can understand roughly what the code does without understanding why it was built that way or how everything connects. When the AI fails, you have to go back to it and beg it to fix the problem.
Since it's a bug, you can't always give proper feedback. You might not know why it happened; all you can do is describe to the AI when it happens. That description sometimes takes a huge amount of effort. To turn everything you see into words, you have to be VERY literate. This is why code review is not the answer: it can show you what the code does, but it cannot give you the understanding that comes from building and maintaining it yourself.
False comparisons
There are a couple of famous comparisons that people make while trying to either justify or reject the use of AI that I think are plainly wrong. As I said before, when judging AI, you must also prove why the judgment is not temporary and won't be invalidated in the next couple of months. You also gotta know why and how it's different from what a human does. The whole point is to justify using humans instead of machines. If you prove that AI is as bad as humans, then we definitely don't need human programmers anymore.
"You were a programmer, now you're a manager"
The only way you can describe the role of programmers in the current era of programming is by comparing them to managers: the work has supposedly been elevated. If you used to write code and were managed by some higher-level manager, now you're the manager. The "agents" are your employees, doing the coding for you; you have to manage them to maximize their productivity.
And I believe this mindset is a huge load of nonsense. Ask yourself this: Which vibe coder do you know who has read a book about people management to improve their vibe-coding capabilities (whatever that means)?
The whole point of management is that you interact with people. The experience you gain as a manager by talking to different people, managing their emotions and needs, making them comfortable and motivated in the work environment, and therefore improving their productivity is what's useful. As a manager, you don't write a loop and expect people to follow it step by step according to a schedule, unless you're a horrible manager who's not doing what they're meant to do.
Not to mention that, with this crucial responsibility as a manager, you have abilities as well. You can fire the person who is lazy or merges bad code into the codebase. Can you do that with an LLM?
What has really happened instead is that we were suddenly forced to adapt to "being a manager," and at the same time, we lost all the benefits of being a manager. Continue this for long enough, and not only will you lose your technical abilities, but you will also gain nothing from being a manager. You stay at your level forever.
"we used to copy-paste code"
One of the most common arguments that I've heard in favor of vibe coding is that we, as developers, were used to copy-pasting code from Stack Overflow or GitHub so it's not as if much has changed. This argument is as misleading as the argument that compares LLMs to compilers. Let me tell you a little about my journey first.
The pivotal point in my career
I have been programming since October 2019. I started with the Python programming language. Even though I spent a considerable amount of time each day learning Python, I didn't truly improve my core understanding of programming. I didn't read software engineering books, and I didn't know about clean code or care about it. I just wanted to make some stuff. And my expertise was too narrow, limited to Telegram bots and some automation tools.
There was a pivotal point in my development career when I worked on a medium-scale Telegram bot that now hosts thousands of monthly users. This project was not a simple thing. Some problems I solved hadn't been solved by any of its competitors, and they still haven't been. I'm still proud of this project.
But the codebase was absolute garbage. Don't look at its current state. Even though it's still garbage, it was even worse. If you're a Python programmer, you might not believe it but I didn't even know what __init__.py really does so I never used it. I was not a pragmatic programmer. I was programming by coincidence.
But I still made a really great bot in a fairly short time (two months at most) by hand. The reason for this contradiction is that copy-pasting code is not as bad as they make it sound.
It's literally impossible to copy-paste your way through. It's not like the whole project is out there and you just have to find all the pieces of code and stick them together. If it were, everyone could make programs back then, the same way everyone can make programs with AI right now. You have to know so much to even be able to copy-paste. It's the same way artists use references. Just attaching them together doesn't work. You have to know how to do it.
How everything caught up
In the beginning of 2025, I changed my life. I started working really hard. I decided to become a game dev and put so much energy into it. The wisdom I had gained from that Telegram bot opened my eyes to the fact that there's more to programming, and I took this pragmatic way of looking at things to expand my expertise and become the person I am today.
Even though I was working really hard, I was improving and growing even faster than I expected. I was already making a very complex card game within the first few months. It was really surprising to me how I was able to do something I deemed impossible a few months ago.
I realized that all those years of programming and expanding my knowledge had caught up. In the past, I had tried touching each programming language a little bit. I had tried C a little bit, Java a little bit, I knew some basic HTML and CSS, I read the Mozilla JS course but didn't practice it at all, I had touched React Native a little bit, Django to some extent, and more. I did the bare minimum with each one and didn't gain much from any individual one. But trying out different things and getting to know different perspectives helped me become an ocean only 1 cm deep: I knew a little about many things but nothing in depth.
I wasn't a pragmatic programmer at first, but if I hadn't been the garbage programmer I was, I couldn't have become the good programmer I am today. I was still a programmer, and there is merit in that. Copy-pasting code is by no means comparable to vibe coding. This comparison is just your coping mechanism.
"AI has a low context window and bad attention"
One famous judgment that people make when trying to sound rational is to mention that AI has a low context window that hasn't been evolving much. A context window is the amount of data that an AI can hold at a time. So the AI agent can't hold your whole codebase in its memory and remember everything. It's very limited. Attention isn't perfect either, so some parts of the context are lost. To learn more you can watch this video; it's also an example of this false judgment that I'm talking about.
We have to first understand: Is it really different from what humans do? Which programmer do you know who has the whole codebase in their working memory while developing? And I'd argue AI is even better than a human if we compare them directly instead of judging each on its own. AI has a lot of tools for retrieving data from various parts of the project, many of which are pretty fast and accurate compared with humans. Humans get distracted easily (especially by real-life stimuli); AI doesn't.
But there's another way that we can look at this problem, and it would make complete sense: humans are trained on everything they've learned, especially the project at hand; LLMs almost never are trained this way. Every time you encounter a problem as a programmer, every time you invest time in it, touch it, deal with it, and solve it yourself, you feel a sense of success and achievement; you feel a release of dopamine. You're constantly training your brain on things while also memorizing them (the same concept was discussed in "Why do you care that much?", too). But this is not happening with AI models. Every time you fire up the agent to change your code, it reads the project from scratch. This is essentially why documentation has become very important: it's the only way we can preserve that understanding. It's quite literally similar to hiring a new developer and giving them the entire project every morning.
It's not quite fair to compare an LLM's context to human knowledge either. Humans do have context windows too, and they're called memory. Not only is this memory far better than AI's in terms of context management (for example, it can delete unimportant things pretty accurately, and you still remember a lot of things from decades ago—you have a much larger context window too, given current AI capacity), but human understanding is also comparable to AI's built-in parameters and learned patterns. I have already talked about this quite a lot.
Devaluing seniority and the field
This part belongs to On the effects of AI on the industry, but I'm separating it because it deserves its own section.
One of the most common things that people from different fields have been dealing with is how much other people devalue your work simply because they don't understand it. It's true for almost all jobs out there. You're a mechanic, but people think that you don't deserve good money because you fixed their car in a few minutes instead of hours. You're a dentist, and people think you don't deserve money for simply examining their teeth. You're a graphic designer and people think all you do is make some shapes with photoshop and "they can do it too". Even if you seemingly didn't do anything that special, your time is still valuable, but other people don't see that value and have this weird emotional judgment, thinking that you have to be paid only for the "amount of work" you have done and the immediate advantage it gave.
The reason why this happens is, in my opinion, something for sociologists and psychologists to find out. But we can safely say that it's definitely not a correct mindset. Not only do I think you can't judge the price of a product or service using "morality" (there's no objective way of assessing it; it's just supply and demand), but you also have to consider the fact that the person doing the job for you has not only put a lot of time into learning it, but could also perhaps do something better and more financially rewarding. Sometimes you pay someone simply for the time they spend, not for what they offer. It's a trade, in the end. If they think they won't get as much as (or more than) they lose from this trade, they have every right to price themselves higher.
This is exactly what has been happening to the tech industry, and it has worsened significantly with the introduction of LLMs. People who didn't see the merit in this profession are now more confidently expressing their false expectations and ruining the experience for technicians. One of the most common ways non-programmers judge programmers is by seeing whether the code "works." But making the code "just work" is something juniors can do too. So what does seniority mean? This is where it becomes obvious that those non-programmers don't even value being a senior developer. If your code works, they expect you to ship it, even if it's a prototype and you're warning them left and right. You're a senior because you know that just because it works right now doesn't mean it will continue to work. Remember, seniority means solving problems before they even have the chance to appear. It's an investment, and that investment is being lost in this sea of hype.
What should you learn for vibe coding?
There's a lot of confusion that everyone is experiencing right now. If you put the extremists aside, we are being told left and right, from the people who have "transitioned" from conventional programming to the new era of programming, that you still need to learn. Even worse, some tell you that it's even more important than ever to learn and "you need to become a senior".
And it's so damn confusing. What exactly should we learn? If coding is given to the almighty machine, then what should we learn? System design?
Even the best programming books out there that are supposed to teach you system design teach you almost nothing. They just teach you some mindsets and expect you to learn by "experience". But what could they really do? It's like reading a swimming book and expecting it to make you a swimmer all of a sudden.
The only answer left is to "learn how to work with AI," which makes even less sense.
1. The cost
You're aware of how expensive AI is right now, right? And it's not like you can learn by working with a weak model. Every one of the vibe coders mocks you when you're not using the top frontier models that burn through your usage limit in one shot, telling you "you're missing out". Not to mention that it takes much more effort—and therefore many more tokens—to learn than to produce.
I have to admit, it might get cheaper over time. But if that's your excuse, don't claim coding is solved until then. And you have to understand that this part of the equation is heavily related to hardware and hardware science is not improving as fast as software science, so your prediction could be severely wrong if you're judging it the same way.
2. No way to verify
A programmer friend of mine who had not tried AI until two months ago finally decided to get his hands dirty and start learning its concepts. He had followed the media coverage of AI, but he never touched it himself. He had heard there's this thing called a skill and it's really good and important and helps you make very good stuff. He went and studied it, then came back to me and said, "is that all a skill is? You just talk to the computer?"
How do we learn if we have no way of verifying whether what we've learned is true? As I previously explained, AI is indeterministic. There's no logical reason why it works in a certain way, not the type of logic that we—as humans—need in order to understand. I tell the LLM something, and it responds with something. If I can't understand what connects the input to the output, my whole logical processor is impaired. And it's really damn hard to learn when you can't find objective connections.
We learn things by learning the patterns in them. Learning patterns is when you become independent from tutorials.
But in AI development, the pattern is not explicit. It's not even agreed upon. Everyone has their own opinion about it. So you're not given directions or scientific ways of learning; you're given a tool and expected to learn it by running it a million times (at the same time, not wasting thousands of dollars). And in the end, you realize the same logic doesn't apply to different models and you have to start experimenting from scratch.
I've experienced this multiple times while trying to achieve success with AI: I look at programming, understand what it's made of, extract explicit principles from it, and then try to replicate them with AI, but it keeps failing. It fails and I'm not sure why exactly, the same way you don't know why a bug happened, but this time you don't know if it's a skill issue or a legitimate limitation either. The only way to understand this is to run the model enough times that it becomes practically impossible to blame the failure on AI. This introduces a lot of friction and costs too much; you also can't do it for every bug. You see, in scientific professions, when you want to solve an issue, you have to isolate it as much as you can because you don't want to confuse yourself with fallacies. You might not understand the source of an issue and could fix something only remotely related, leaving the issue unresolved while thinking you've done something. But with AI, you don't have this luxury to question the tool. The boundaries are unclear. So in the end, you're left thinking, "Am I the problem?" and you have no objective answer for it. No one gives you practical answers; everyone's just like "if you can't replace your whole career with it, it's a skill issue. Source? Trust me bro"
When you can't objectively verify your understanding, you don't feel the reward, you don't feel like you've actually learned something. Quoting again, if you don't know why something works, you wouldn't know why it stopped working.
AI maximalism means no one is safe
Software engineering used to be considered a highly professional field that requires a lot of hands-on problem-solving. If this whole field is "solved," it's really damn hard to claim other jobs are safe. The reason why we don't see as many advancements in other fields is that AI has not improved enough in image recognition, though it's improving.
This brings us back to the end is near argument. I'd rather ignore the conspiracy theories telling me the end of the world is near. Because the trade-off is obvious. I don't want to waste my life thinking the end is near, only for it to turn out to be far, far away, while it's not as though believing them would help me at all.
Any argument that implies this falls under this section. "I can produce a high-quality application with one junior and Claude," "AI has increased our team's output a hundredfold," "We replaced 200 senior devs with three devs and unlimited AI," and so on.
No need for AI experts
We have an expertise called SEO, search engine optimization. Back when the internet was in its early stages, SEO experts could do a lot of things. Keyword spamming was one of the things they did. It helped websites rank higher in Google search results. But at some point, Google updated its algorithm and penalized everyone who did that. This is because Google wants a fair game. It wants to show each user what they really need and enjoy. Google aims to remove the need for people like SEO experts. Justice doesn't need hacks.
Even though SEO experts still exist, they are much less in demand than before. The same would happen to AI experts. The LLM aims to remove the need for people like them. So don't think you're safe if you learn how to work with an LLM, you're not safe either.
It's scary as an experienced programmer
As I explained before, being a programmer is about this intuition and ocean of knowledge that you gain, keep sharp, and continue to grow over time. And it has been made like this because we were deep in the trenches, dealing with problems, letting our brains process what dealing with an issue looks like, learning by interacting, learning by being exposed to new and irrelevant info, and much more.
It's not like AI has just changed the programming language that we used. It has overhauled our process beyond recognition. Every programmer knows that adapting to vibe coding requires a huge mindset shift.
Senior developers, you have sharpened this intuition of yours, this spidey sense, so that when you're doing something bad, you feel it in yourself and stop. That's why all your senses are tingling when it comes to offloading work to AI. It's not just being addicted to the previous form of software development. This mindset shift isn't just about how you work; it contradicts your whole worldview. I don't know about you, but I don't know how to trust my intuition anymore if it has become this unreliable.
How to use AI properly
Using AI properly means understanding it as a tool, resisting the hype around it, and planning carefully to avoid long-term harm. It's not easy, I have to admit. The speed of things, the constant exposure to FOMO-inducing statements, the hard-to-grasp nature of this field, which suddenly expects programmers to become philosophers, and AI psychosis all make it harder for you to think rationally.
It's been really hard for me, too. As I said in the preface, I initially wrote this book for myself, to gather my thoughts and understand where I'm mentally at, to finally accept my situation.
But it wasn't always like this. I remember that a year ago, I bought Claude to help with my game development. I couldn't be happier. It felt much more like a tool than a new employee I couldn't trust. I was actually learning stuff and growing to become a better programmer, a better game dev. But right now, I'm using these LLMs to do all the coding, and I feel like I'm stuck.
The difference is in how I used AI. I wasn't asking it to just do everything. I made a lot of the things myself. I used it from time to time to generate some stuff, but then I read all the code it generated and tried to understand as much as I could. I remember using it only once for problem-solving without verification. And it was something like a conversion tool. It was just a simple script, though a crucial one. I couldn't understand it because it required a lot of knowledge regarding the programming language (C#) and I tested it multiple times and found that it worked. I postponed it until I could write a couple of tests for it and call it a day.
What I did and I suggest you to do is summarized in two categories:
The proper ways
There are two ways you can harness the power of AI without its downsides:
1. Non-problem-solving issues
The easiest is this. You use it for things that require no problem-solving and are just mechanical. In programming, most of the refactoring could be done by AI. But keep in mind that not all refactoring is mechanical. The larger it gets in scale, the less it's mechanical. Moving your codebase from Python to Go is definitely not as mechanical as mass renaming files and variables.
2. As an untrusted employee
Think of it this way: someone emails you and tells you they're looking for a job. You look at their portfolio and realize they're not very good. But their rate is so low that it's worth it. You hire them, but you're extra cautious with their output.
You may ask AI to write code and implement things, but you have to read every line and understand what it was thinking and why it implemented something. If you don't know, ask it. Never assume "there must be a reason for that that I don't know." This could easily lead to the triple debt.
The slightly improper ways
Of course, I understand. Not all code is supposed to be perfectly written, free of structural and maintenance issues, or understood to the core. You would want to avoid scope creep. So it's okay to take risks, but your risks must be educated. It's okay to occasionally ask AI to generate stuff and trust it with some scripts and tools here and there. But always remember what you have trusted and what you haven't. If you can put unit tests around them, do so. This is the best way to take educated risks. If you can't, either remember them or write them somewhere. I suggest a single file inspired by ADR, but for all decisions. Later, if you have time left, you should review these.
Most of the time, you can't use it properly
The biggest struggle with AI for the developers themselves (those who don't want to vibe code everything) is how to keep learning in this era. And one of the issues stems from something that's unpredictable by nature, so there's literally no way around it: bugs. As I explained in You don't search anymore, the time you used to spend on bugs is a contributing factor to you learning and growing. And I'd argue it is one of the biggest factors too, because programming is, most of the time, about finding issues and bugs.
But the thing is, programming is against you by nature. Bugs are not something you deliberately make. They just happen and most of the time you don't know why. This means that you also don't know if the bug is something important or worth learning or not. Sometimes they're just silly things and sometimes they're not. If you use AI to fix bugs, you're gambling with your knowledge. And it's not something that you can fix by reading books or practicing by hand. When bugs happen, it's your only chance to learn how to solve them. Once they're solved, you're left with a finished puzzle that teaches you nothing.
When you continue this chain of thoughts, you realize most other use cases are the same too. The act of digging through the codebase to learn is an important part of your learning journey. In Code review isn't the answer, I explained how I was able to use AI to add a feature to Godot. But a hidden caveat that I didn't tell you is that I wasn't able to continue this journey. I tried multiple times after that to fix some open bugs or do anything at all, but I failed miserably. I realized that—while using AI—I had offloaded the process of understanding the codebase and the programming language to AI. I was just producing. I managed to add that feature, but that was just it: adding that feature. That knowledge was mostly throwaway knowledge. This is essentially the same as that doom-scrolling example. Juniors will remain juniors with AI.
One important aspect that makes AI quite incompatible with programmers is explained in "AI has a low context window and bad attention". I'm not saying that you can't or shouldn't use AI in your work as a programmer. I'm just explaining why there's a lot of friction here that people might have missed. Everyone thinks AI is our new tool, while this tool is completely different in nature from us, and somehow we have to manage converting our human workflow into an AI workflow while maintaining the same productivity. It simply doesn't work that way. Your high hopes don't make reality any different, even if the world adapts to you.
