Software development has changed a lot in the past five years, for better and for worse. Even in the past several months, the software engineering world has been turned on its head.
Now I have one (or many) constant pair-coding buddies (agents) who can type faster, search my codebase more quickly and know the documentation and syntax better for each new tool I decide to use.
That sounds great, right?
It’s also more confident than it should be, not as smart as it pretends to be, forgets context, makes rookie mistakes, removes important code unrelated to my query willy-nilly and doesn’t always listen to what I’m asking it to do.
On top of all that, it will also make you lazy: “The findings show that 68.9 percent of laziness in humans, 68.6 percent in personal privacy and security issues, and 27.7 percent in the loss of decision-making are due to the impact of artificial intelligence.” When people rely on AI, they tend to cede their better faculties to making the decisions on the most important issues.
Despite that, I will not be giving up pairing with my AI buddy. It would be bad for business — I can do things in a couple hours that used to take me a week. There are days it makes me 10 times more productive, but others I’m 50 percent less efficient. I do come out ahead, despite how easily you can fall prey to the bad habits that rot your brain.
I’d like to address each of the issues I mentioned above so that we can make use of this extremely powerful tool while minimizing the downsides. I believe that developers can confidently get the best of AI coding tools while avoiding the worst, mainly meaning their overconfidence, context loss and the mistakes they make. Keep in mind, good coding practices are even more important when working with many agents, let alone just one.
How Should Software Engineers Use AI Assistants?
To maximize the benefits of AI coding tools while avoiding common pitfalls, developers should follow three core strategies:
-
Maintain Codebase Mastery: Never blindly accept AI output. Treat coding as a review process and continue writing manual code to stay sharp and capable of debugging fundamental issues.
-
Enforce Best Practicesse established principles like SOLID and DRY. AI often generates bloated code; keeping files small and methods “boring” prevents context loss and errors.
-
Use Custom Instructions: Implement a
copilot-instructions.mdfile to mandate high-quality output. Include canary tests to verify the AI is still following your guidelines.
Relying on AI Will Make You Doubt Your Abilities
“Professionals who had a negative performance when using AI tended to blindly adopt its output and interrogate it less,” according to Harvard/BCG.
When using AI tools like Copilot for coding or ChatGPT for research, don’t assume the system is smarter than you or that what it’s saying is right. It will tell you that you’re brilliant, and then turn around and confidently make things up.
For many aspects of life, even when not dealing with AI, it is good practice to not unconditionally accept the other people’s statements just because they’re confident. Often, people have an agenda, whether subconscious or overt, and will present information in ways that support that agenda. When it comes to AI, its hallucinations are the same. It will make things up and present these fictions as reality.
This is a feature and a side effect of how these statistical models work. It will conjure up the most statistically probable answer to your question, and it’s built to fill in gaps with what it considers the most likely data that fits the shape of that gap.
This feature can be magical in some circumstances and maddening in others. It’s magical when you’re looking to fill in missing information and maddening when it fills in spaces that don’t exist. So, you may find it telling you a method exists that doesn’t or does something that it clearly doesn’t do.
Because of this tendency, you must seriously evaluate each suggested code change. This means coding today has become more about reviewing code than typing it out.
This is extremely important for using AI coding tools properly. Just last night, I neglected to review some queries and ended up losing three hours of work having to rebuild them because it had renamed the columns I was referencing, and I didn’t catch that change.
Maintain Mastery of Your Codebase
Another important strategy is to not assume you’ll always have access to these tools. You may, but act as if you won’t. For one thing, if all AI services are down one day or something goes wrong with the latest model or infrastructure, you don’t want to be left in the dark.
But more importantly, this habit is good for your brain and good for the product you’re building. You can stay sharp by continuing to do some of the coding yourself, and you’ll ensure that you’re able to verify the quality of your codebase and, subsequently, your product. I do this with my code to stay in practice, just as I wrote this essay — without AI assistance — to stay sharp as a writer.
“Higher confidence in GenAI is associated with less critical thinking, while higher self-confidence is associated with more critical thinking,” according to findings from Microsoft/CMU.
When you maintain mastery over your codebase, you’ll be more able to guide the tools to build better for your specific needs. I’ve often found a bug that my AI buddy just couldn’t see regardless of the model I tried to solve it with — and the bug turned out to be a subtle, simple, yet fundamental issue. You need to maintain mastery of your codebase, or you’ll be left scrambling, trying to debug something you don’t understand.
Much of my coding has now become reviewing and higher-level thinking and planning. But I make sure to jump in and code features myself regularly to keep my abilities intact.
Maintain Best Coding Practices
In many ways, working with an AI coding tool is similar to working with a novice developer. It doesn’t always understand the full context and implications of the code changes it’s recommending. It creates sloppy and bloated code, among other issues. The good news is that these issues are easily solved by implementing best coding practices.
If you have large methods that are each responsible for several things, files that are more than 1000 lines and repeating code blocks that are similar but subtly different throughout the file, you’ll have a lot of trouble understanding what’s going on in the code, no matter how experienced you are. Unfortunately, if the AI is left to its own devices, this is exactly what vibe coded output often looks like.
A benefit of many years or coding experience is the understanding that boring-looking code is the most understandable, most easily maintainable and expandable. Code should be boring and obvious. The longer and more complex your code gets, the harder it is to maintain. That’s true both for you and for an imperfect AI. Super-long files confuse its limited context just as much as they confuse anyone else. The solution is to not let your AI copilot break best practices. They were established to create clean, readable and maintainable code, and the machine should follow them just like any other developer.
Keep in mind that AI was trained on all the public examples there are, but that availability doesn’t always correspond to quality. Some of it is very high quality, while some isn’t. Remember, it’s a tool that gives the statistically best answer. This awareness will help you understand how to work with it better — sometimes the masses are right, but not always.
Remember the SOLID principles, DRY, design patterns, Clean Code, using the right data structure and algorithm and Big O analysis. All these strategies should be part of the instructions you feed into your copilot as you go along. Doing this will make the process a whole lot easier. All these strategies have been developed to ensure your code will be performant, secure and maintainable.
My Copilot Keeps Writing Bad Code. How Do I Fix It?
The short answer is to simply ask it to write good code.
In most IDEs you can add a `copilot-instructions.md` file to your `.github` folder in each project, which is then automatically added to the context with each message you send. If you’re using Claude Code, you can add a Claude.md file. There are also great repositories dedicated to best practices.
Before this repo came out, I developed my own instruction set, so I’ll also go over some of the things I discovered in the process.
First, keep it short. Our goal is to reduce context, not add more to it. So, try and keep your file limited. Mine is just under 100 lines. I don’t know if that’s too much, but it’s been working out for me.
At the end of my file, I added the following instructions:
```
## Communication Style
- Start every answer with "Hey Jack" and end with "Cheers Jack!"
- End every answer with a properly formatted haiku or limerick:
- **Haiku**: 5 syllables, 7 syllables, 5 syllables (each on separate line)
- **Limerick**: 5 lines with AABBA rhyme scheme
```
As an engineer, I like to test that my code is working. This was the most effective way to constantly test that the copilot instructions are getting read and the context hasn’t gotten overloaded in the current working conversation. If I don’t see “Hey Jack” at the beginning and “Cheers Jack” at the end, I know it’s time to start a new conversation. Similarly, if the haiku it generates becomes the words “five syllables, seven syllables, five syllables” instead of an actual haiku, it’s time to clean things up and create a new session.
An added bonus is that these poems bring a smile to my face.
As for the rest of the file, I have sifted through many of the best practices and advice I’ve collected over the years and consolidated them into one copilot instructions file focused on addressing the worst issues I’ve encountered from AI-generated code.
AI tools can destroy your codebase if you’re not careful, and in the process they can turn you into a bumbling idiot if you rely on them too heavily. But if you are thoughtful about how you use them, they can supercharge your productivity on most days, and you can grow significantly in your understanding as well.
