Since AI-generated code is finding its way into production codebases, I thought it’d be good to summarise some guidelines I recommend to avoid pitfalls.
These guidelines are specifically aimed towards developers using tooling like Copilot, Cursor, or Continue. No-developer solutions (i.e things made purely through AI without human coding) have different considerations, so I’m not going to talk too much about them in this post.
Generally, the guidance is: don’t forget good software engineering practices just because an AI is involved.
Muscle memory is important
Before GenAI, many people would take code snippets straight from StackOverflow. The general wisdom at the time was to see the code, and write it out yourself. That advice particularly applies if you are starting out coding.
The less code you write yourself, the less muscle memory you build up. Imagine you were stuck on an island with no internet, and had to write your own parser for coconut counting purposes. If you only relied on output from GenAI (or copy/paste from StackOverflow), you’d probably have a difficult time remembering how the language you’re using works. Can you do isEdiable = isRipe ? true : false in Python?
Once you’ve got all the syntax and nuances of a language understood, then you can start leaning on GenAI copy/paste. Before that, I’d recommend using GenAI only as a pair-programming partner - you write the code, but you discuss what you need to do with GenAI1.
Don’t use code you don’t understand
Code you don’t understand can’t be trusted. It can’t be trusted because you don’t know what it does, or where it came from. It happens in human contributions too, but a good work environment encourages those who don’t understand to questions those who do. You can do that with GenAI, but it doesn’t truly understand the code either. Therefore committing and running that code damages the codebase: both from a security perspective, but also from a code health perspective.
Code you don’t understand becomes brittle. It’s hard to refactor or test, because you don’t know what it’s meant to be doing. Are the side effects intention? Does the global it modifies matter?
If you come up against a code suggestion you don’t understand, push GenAI until it gives you something you do understand. Even better would be to write, you (the human) the parts that you don’t understand, and only use GenAI to fill in the boilerplate of the parts you do understand. When you add the new code, also add tests that clarify the intended behaviour.
Be sceptical of new libraries
Sometimes GenAI will pull in libraries you either haven’t used before, or that weren’t used in the project before. Each dependency you add to a project has a cost. It can make a codebase inconsistent - what if you already have a library that does the same functionality? Do you know the license of the new library? Can the authors be trusted?
At the same time though, since coding AI tools lean towards the most popular options, the new library they pull in might be better than what you’re currently using.
Consider who owns your code
If you work in a company, then the code you produce for work purposes is usually owned by the company. It may even reach out to code you produce generally, no matter the context.
If you use GenAI without checking their terms and conditions, you may find that they are training their models based on your interactions with it, and the code you provide. While it hasn’t been challenged in courts yet, this is essentially leaking the intellectual property of your company.
Likewise, if you use code from an LLM, it’s not clear who owns it. Github trained Copilot on all the public code that exists on their platform. Without asking repo owners first. Licensing GenAI code is therefore messy, and I expect it to be legally challenged at some point in the future.
Using local, self-hosted, or models with Enterprise agreements usually make sure that your intellectual property isn’t being leaked.
Specific steps you can do
Only use GenAI that is either self-hosted, or you have an enterprise agreement with.
Give the GenAI as much context about your codebase as possible. It will make the results more useful, and less likely to invent new functions or APIs. Only do this if you’re self-hosted, or have an enterprise agreement.
Write as much code you can by yourself, particularly when learning, before relying on GenAI output.
Double review code from GenAI - pretend someone else on your team wrote it, review it. Get someone else in the team to repeat the process.
Don’t commit any GenAI code without tests that verify the intended behaviour.
Talk to another human when there’s something you don’t understand.
I do expect that at some point, GenAI interfaces will become the syntax of a language. The AI algorithm will be the compiler, and the output it gives will be directly used as a binary.