Why You Should Never Let AI Debug for You
And 3 ways you should be using AI to code
If you’re interested in machine learning engineering, don’t forget to subscribe to get articles like these in your inbox each week. My goal is to help 10,000 software engineers learn ML by the end of this year. You can also find me on X, LinkedIn, and YouTube for more content like this. Enjoy!
This past week saw the release of many different coding models and tools. These releases brought up an interesting conversation that is more important than ever for software engineers to pay attention to.
The first party in this conversation I like to call Team “Software Engineers are Cooked”. They’ve been around and going strong for about three years now. Every time a new model comes out, demos pop up on social media showing what the model is capable of and how it can replace software engineers.
The second party was definitely the minority, but much louder than usual last week. This is Team “Don’t ruin your skills by coding with AI.” This team has popped up primarily in opposition to the above team. There is a strong voice not to let engineering skills atrophy by outsourcing engineering work to AI.
This situation is nuanced, of course. The counterargument to the first group is that only the successful demos tend to go viral. The failures of these models tend to be shared less. However, the failures are much more interesting when evaluating model viability for complex projects.
The counterargument to the second is that coding with AI has already proven to provide enormous productivity gains when done correctly. However, we’re now at the point where we can see the long-term negative impact from incorrect use. We’re also realizing that the magnitude of these negatives can be immense.
As someone who has coded with AI quite a bit at work (Google has been doing it since before it was cool) and on my personal projects, I want to provide a bit of important context about coding with AI. This article will go over the importance of never letting AI debug for you and mention three applications for which you should let AI code for you.
And, yes, this is another article similar to others you might find online about “How to code with AI.” The important distinction between this article and those is that those articles are about making your code better using AI. This article is about coding with AI in a way that will make you better.
Tedium: The secret sauce of software engineering
The first tasks to get automated with AI are anything tedious. Humans hate working on things that are time consuming, progress slowly, and can be monotonous. No one likes wasting time and no one wants to feel like they’re struggling on something that should be an easy task.
Software engineering is a field rife with tedium. Debugging, writing documentation, creating tests, code reviews, refactoring code, etc. are all tasks that can feel incredibly tedious, yet they’re essential to the job. It actually takes a great deal of effort as a software engineer not to get stuck in a rut when doing these tasks for hours on end.
Since software engineers are most familiar with new technology and software engineers deal with many tedious tasks, it makes sense for us to try and automate these tasks with AI. This is why we see so many posts online about software engineering being replaced by AI when in reality many more jobs would take the hit before we do. It’s because we’re so close to the technology and apply it to what we’re working on.
Replacing all tedious software engineering tasks with AI is a problem. Just because a task is tedious doesn’t mean it’s bad. In software engineering, the tedious tasks are often the ones we learn the most from. The tedium can be a struggle, but it’s the effort required on these tasks that help us improve.
Just think about the hardest bug you’ve ever had to troubleshoot. In my experience, the difficult bugs require me to get very technical and really understanding what’s going on. I usually come out of these debugging sessions with a better understanding of the system as a whole and a greater knowledge of the specific topics that contributed to the error. I’ve found this knowledge to almost always be applicable to a later project.
If I had told AI, “Here’s my error message. Take a look at my code and fix it.” I never would have had that experience and I never would have learned. That’s a big issue in software engineering. Just like being a doctor or lawyer, continued education is paramount. The field moves quickly and if you aren’t constantly learning, you’ll fall behind.
I’m very specific about using debugging as an example. It seems to be the task engineers are most excited about automating. It’s also the task that’s most beneficial for an engineer to do themselves. You should never let AI debug for you. Automating this task has major long-term ramifications on you and your capabilities. This doesn’t mean you should never use AI to debug. Instead of letting it debug for you, you should let it debug with you (more on this below).
There are three applications where I’ve found it particularly helpful to have AI code for me:
Vibe coding
Working on particular tasks
Planning and understanding
Vibe coding
Vibe coding is a term coined by Andrej Karpathy on X that is essentially giving AI a list of system requirements and letting it take over from there. Engineers take a more hands-off approach to let the AI “do its thing”.
Vibe coding has really made waves for one specific reason: It allows people with next to zero programming knowledge to build their own applications. This is huge, there’s no doubt about it, but there’s also a very real value for those who do know how to code too.
First, vibe coding is great for prototyping. Now that AI can build things from the ground up, it can be a great tool for saying, “This is what I’m thinking of building, let me know what you come up with” and sitting back to see what it does. Waiting on a prompt generally takes a few minutes and can end with a working prototype. That speed is invaluable.
Second, vibe coding can grow a project beyond what you had anticipated. Giving the AI a bit more freedom allows it to write code uninhibited. Without strict requirements, it can be more creative. It’s great for coming up with alternate ways of satisfying the original requirements.
Vibe coding shines when the AI is given less requirements. Vibe coding fails when you try to adhere to a specific vision or requirements for a project. It can be very difficult to exactly match those specifications via prompting.
Stricter requirements are more common in industry and that’s why vibe coding works well on standalone projects but isn’t as successful when making changes to a complex and large codebase. It’s very difficult to non-specifically prompt a model to make a change while both ensuring the change is correct and it doesn’t have unintended side effects.
Working on particular tasks
While vibe coding doesn’t work for particular tasks, AI can still be used for those tasks. It just requires the engineer to have more knowledge of the code themselves. A prompt to do this would be something like: “I need X function to handle this case. I also need the tests adjusted to check for X.”
The more specific the prompt (and task) is, the better chance the AI will be able to succeed at the task without breaking functionality elsewhere in the code. Vibe coding doesn’t work in this case because it’s difficult to make a specific enough prompt without knowing the codebase.
You might ask: Why use AI for a change like this when I can do it myself?
First: speed. Just because the task is specific and the engineer knows what change needs to be made to the code doesn’t mean actually making the change itself is fast. This depends on many factors but codebase health is a big one. I’ve seen many simple changes require many lines of refactoring and additions in unhealthy codebases.
Second: AI is much better at avoiding “human errors”. Some examples of these are forgetting some references or not adjusting some tests when committing a change. These are things an engineer likely knows needs to be done but misses them for some reason or another.
A great example of a particular task that can be made much easier with AI is the task we discussed earlier: debugging. If you know what your error code is, where in the code you’re looking, and what you need that code to do, you can prompt a model to help you with it. Using prompting specific to the actual code (i.e. “this function needs…” and not just “do this”) will help you work through a problem while understanding what caused it.
Planning and understanding
AI is an excellent tool for learning while coding because you can learn in the context of the project you’re working on. Anyone can learn about system design, technical topics, etc. by asking an LLM or looking online, but learning these topics becomes more valuable (and easier) when you’re learning them in the context of the project you’re working on.
I use AI to help me plan and understand the systems I’m trying to build before I dig into them. I found it an excellent tool for planning projects, clarifying system goals, and understanding the optimal way for putting a system together. Again, you don’t want the AI to do these things for you. You want the AI to do them with you.
I’ve found this to work best when I reason with the model. I start my conversation with a long prompt with a lot of context and my reasoning behind the decisions I’ve already made and tradeoffs I’ve already considered. The prompt generally takes this form: “I want to make X change. I’m thinking about doing it X way because of X…” and runs for at least a paragraph.
I’ve found this prompt particularly helpful for a few reasons:
It provides complete context of what I’m trying to learn to the model. You can also provide this context with back and forth prompting, but I’ve found it less effective. Models tend to focus more on what has been said more recently and forget the context provided further back.
The model will explain correct and incorrect assumptions in detail. By prompting the model with the explanations it tends to reply in kind. This is exactly what I need when I’m trying to learn.
The model doesn’t give into my questions and suggestions nearly as easily. Most language models are trained to be agreeable. That’s particularly bad when coding with them because they tend to rate a user’s questions/suggestions highly when considering correctness. So when I ask, “Shouldn’t we do this?” the model will automatically agree that we should even if I’m wrong. The above prompt has helped mitigate this significantly.
The model avoids spinning its wheels. By adding explanations to the prompt, I’ve found models to spin their wheels less. I’ve gotten into situations where a model goes back and forth between two incorrect responses multiple times. Explanations and proper context seem to help with this.
It’s invaluable to have a learning tool directly integrated with your code and I greatly recommend using it, just make sure to take care to use it to learn and not to do things for you.
A few more tips
Here are just a few more tips for coding with AI that aren’t directly related to maximizing your long-term potential, but I still think are worth mentioning:
Make small changes. Just like commits, have AI make small changes and frequently accept them.
Make sure to review your AI-generated changes. This should be obvious, but it’s worth mentioning.
Use Git especially if you’re new to programming and you’re vibe coding. Don’t end up like this.
Ignore hype and test models yourself. The random people online aren’t going to know which model is best for your use case.
Pay attention to model output, not just code changes. The model will output the code and also the “why” behind it. The “why” is more important than the change itself.
Important Takeaways
The first important takeaway from this article is tedium isn’t always bad. In software engineering it’s the tedious tasks that help us grow as engineers. This is especially true about debugging. However unpleasant it is, don’t let AI debug for you. Let AI do it with you.
A follow-on to this is to never replace your learning experiences with AI. Identify the things you’re doing that help you learn and make sure you continue those actions. Replace unhelpful tasks with AI instead. I see this pitfall a lot in writing. People try to replace their writing with AI when the act of writing is the learning experience.
Third, these lessons are most important to be intentional about now more than ever because of where AI is at. We’re seeing the long-term effects of coding with AI causing engineering skills to atrophy and the negative impact that has on a person (and their work) long-term.
AI has become performant enough at coding to do some important tasks entirely for us. However, AI isn’t good enough to solve everything for you. If you lose your skill set due to
AI, you’ll be in a very bad position when you reach a problem AI can’t solve for you.
Essentially, we’re seeing AI coding become good enough to be helpful, but still bad enough to be even more detrimental if used incorrectly. I urge you to be cognizant about how you’re using AI to code. If you’re using it correctly, you’ll surpass what you were previously capable of. If you use it incorrectly, you’ll fall far behind.
Let me know how you’re intentional about your AI use in general in the comments. I’m always up for learning new tips and tricks.