Students new to programming may wonder why they even need to learn to code any more. They can ask the reasonable question: “Why can’t we just use AI for all our programming?” It’s a fair question. The Genie is out of the bottle. We aren’t putting it back. It absolutely does have its uses. But it also can’t be trusted.
For a new programmer, the important skill is no longer remembering syntax, nor is it learning how to make an AI produce code. It’s learning how to solve problems in a systematic way that they understand well enough to trust.
When getting started with AI, use it to help think through the problem, break the work into manageable pieces, elaborate how the pieces interact and only then start to code.
There’s the old adage “Garbage in, garbage out”. If you aren’t able to articulate your problem in an AI-friendly way, we’re well into garbage out territory. The other part of the problem is whilst AI will certainly generate you some code, if you don’t understand what it’s giving back, you can’t trust it to be correct. If you carry on just accepting what it’s saying, it’s like going on a date in a foreign country and putting all your faith in your translation app. Sooner or later you’re unwittingly going to say something that will earn you a slap.
So, instead of just telling it what you want, try:
1. Have the idea.
Write down what you are actually trying to achieve. By explicitly writing it down or reading it out to a rubber duck (yes really), you’ll gain a better understanding of your own idea.
2. Brainstorm with AI.
Ask for several possible approaches and discuss the trade-offs.
3. Choose the architecture.
Ask AI to propose what the smallest useful architecture might be and then get it to justify its choice.
4. Define the modules.
Break the overall goal into modules (tasks). Make each task explicit, it does one thing and one thing only. Give every module a clear responsibility.
5. Define the interfaces.
Agree the data each module receives and what data it returns. Each module should be provided with the bare minimum it needs and no more. It should also be explicitly told what it needs, not have access to some global information.
6. Define the evidence.
Decide how you will know that each module works.
7. Create a handover document.
Record the agreed requirements, design, interfaces, tests and decisions.
8. Start a fresh context for implementation.
Give the AI only the information needed for that particular module.
9. Read what it produces.
Ask questions about anything you do not understand.
10. Test independently.
Use a specification of what something should do, to design the tests rather than letting the implementation define what “correct” means.
11. Simplify.
Ask whether the solution can be made smaller, clearer or more conventional.
12. Verify.
Do not trust an answer simply because it sounds convincing.
Instead of “Build me a web app for tracking books.”
Try: “With the ultimate goal being to create a web app that will record where each book is on each shelf in my house, first propose the smallest architecture to accomplish this. List the modules and their interfaces. List the parameters which may be useful. List acceptance criteria and edge cases. Do not write code yet.”
Starting fresh each time
When you’ve got to the point where there’s a cunning plan, a flow chart of all the individual modules in your code and explicit ideas about what each module will need as input and what it’ll generate as output, now’s the time to start afresh.
A fresh context keeps the conversation focused — Long conversations accumulate assumptions, failed approaches, temporary decisions, and irrelevant details, all of which need processed.
Reduces the chances of solving the same problem twice — Errors that were solved can get reintroduced over long conversations.
Reduces accidental coupling — If one module’s implementation details dominate the conversation, the LLM may unconsciously make other modules depend on them.
Makes review by another LLM easier — After implementing a module, you can give its code and specification to a new context and ask, for example, “Review this as if you had not written it.” his often produces a more useful critique than asking the original context to review its own work.
Creates natural architectural boundaries — Treating each module as its own LLM conversation reinforces the idea that modules should communicate through explicit interfaces rather than through shared implicit assumptions.
Read code more. Write code less.
Your AI can be used to teach you. Understanding the concepts reduces imposter syndrome: You can interrogate it for an answer instead of hoping it is right.
Don’t merely
- Use what it gives you because it runs.
- Accept clever abstractions you can’t explain.
- Patch and keep patching until the tests say they’re fine.
- Run code you don’t understand
Instead try
- Ask: Explain the architecture to me.
- Ask: What does this do?
- Ask: Can we make this simpler?
- Ask: What does this rely on?
- Ask: What are the edge cases?
The goal is not “AI wrote it and it runs” The goal is “I learned enough to know why this works and to trust it if I see it again.”
