Building with AI
Before you start
You need: Article 03, and enough of your route to be writing real project code — around month three.
Also useful: Track 16 Git. Reviewing generated code is far easier when you can see a clean diff.
Time: about 45 minutes, at the keyboard with your own project open.
Learning objective
Use AI to write real project code, and review it so that everything you commit is something you can explain.
Topics
- Learning with AI versus building with AI
- Sizing a change you can actually check
- The review checklist that matters
- The four silent rules
- Committing generated work
- When to stop prompting
- Your AI evidence log
Learning with AI versus building with AI
Article 03 was about understanding. This is about shipping.
| Learning | Building |
|---|---|
| Ask for a critique of your attempt | Ask for the code, then review it |
| The goal is your understanding | The goal is working, defensible code |
| Wrong answers cost you nothing | Wrong answers reach your portfolio |
| "Don't rewrite it" | "Here is my context, write it, I will check it" |
Both are legitimate. The mistake is using building-mode while you are still learning the topic — you get a working feature and no idea how it works, and the interview finds that.
A workable rule: generate what you have already learned to write. Use AI to go faster at things you understand, not to skip things you do not. Generating a repository method in month four, after Track 07 taught you what one is, is efficiency. Generating it in month two is avoidance.
Sizing a change you can actually check
Ask for a whole feature and you get 400 lines across six files. It compiles. It looks right. You cannot review it, so you approve it — and that is how unexplainable code reaches your project.
| Change | Size | Can you verify it? |
|---|---|---|
| One repository method | ~15 lines | Yes — run it against real data |
| One endpoint | ~20 lines | Yes — call it in Postman |
| One validation rule | ~5 lines | Yes — send a bad request |
| "The whole fee module" | 400 lines | No |
A good change is one you can hold in your head. Build the fee feature in six steps — SQL query, repository method, service method, endpoint, frontend call, rendering — verifying each. Six verified steps beat one unverified feature, and when step three is wrong you know exactly where.
Commit after each verified step. Then a bad next change is one git restore away instead of an archaeology exercise.
Giving it enough context
Generated code matches your project only if you tell it what your project is. The model knows ASP.NET Core; it does not know your rules.
I'm working on a multi-tenant school management API in ASP.NET Core 9
using Dapper.
Entity:
public class Student
{
public int Id { get; set; }
public int SchoolId { get; set; }
public string Name { get; set; }
public string RollNumber { get; set; }
public bool IsDeleted { get; set; }
}
Here's an existing repository method, follow this style exactly:
[paste one real method]
Write GetByClassAsync(int schoolId, string className).
Rules:
- SchoolId always filtered; it comes from the auth claim, never a parameter
the caller controls
- Exclude soft-deleted rows
- Parameterised SQL, no string concatenation
- decimal for money, never double
- Full braces, explicit types, no var
Every rule in that list exists because omitting it produces a bug. Paste one real method rather than describing your style — one example teaches more than a paragraph.
Add "don't change anything else" whenever you paste an existing file. Without it you get a rewritten file and a diff you cannot review.
The review checklist
Read generated code in this order. It takes two minutes.
1. Does it do what I asked? Not something adjacent, not more.
2. Does it follow the four silent rules? The section below.
3. Does it handle the edge cases? Null, empty, zero, absent, duplicate.
4. Is anything invented? Method names, packages, configuration keys.
5. Is it more than I need? Generated code adds caching, retries and interfaces you did not ask for. Delete them — every unrequested abstraction is something you must maintain and explain.
6. Can I explain every line? If not, ask about that line before accepting it.
The four silent rules
These matter more than everything else on this page, because none of them produces an error. The code compiles, runs, and is wrong.
SchoolId from the token, never the request
// Reject — any signed-in user can read any school
public async Task<IActionResult> GetStudents([FromQuery] int schoolId)
// Accept
int schoolId = int.Parse(User.FindFirst("schoolId").Value);
This is a data breach with a 200 response. Nothing is logged. Test it by signing in as School 1 and requesting School 2 — the only way to find it.
The absent check comes first
// Reject — an absent student is reported as Fail
if (result.MarksObtained >= subject.PassingMarks) { return "Pass"; }
if (result.IsAbsent) { return "Absent"; }
// Accept
if (result.IsAbsent) { return "Absent"; }
if (result.MarksObtained >= subject.PassingMarks) { return "Pass"; }
An absent student's marks are null, and any comparison with null is false — so execution falls through to Fail. This is the rule generated code breaks most often.
Money is decimal
public double Amount { get; set; } // Reject
public decimal Amount { get; set; } // Accept
Base-2 fractions do not sum exactly. A fee report off by paise is always this.
Every command inside a transaction receives it
await connection.ExecuteAsync(sql1, p1, transaction);
await connection.ExecuteAsync(sql2, p2); // Reject — no transaction
await connection.ExecuteAsync(sql2, p2, transaction); // Accept
Miss one and a rollback leaves half the operation applied.
Check these four on every generated piece of data or business code. It takes thirty seconds and it is the difference between a portfolio you can defend and one that falls apart under a follow-up question.
Committing generated work
Commit before generating. git status clean first. Then:
git diff --stat # if you asked for one method and five files changed, stop
git diff # read it, not the AI's summary of it
git add -p # accept hunk by hunk
Read the diff, not the summary. A summary is a description; the diff is what happened. They differ more often than you would expect.
Never commit code you have not read. That single rule prevents most of the ways this goes wrong.
In the commit message, record what you verified rather than what wrote it:
Add fee defaulter query to FeeRepository
Returns accounts with a balance above zero past the due date, for one
school. Filters by SchoolId from the claim and excludes soft-deleted
students.
Written with Claude, reviewed against the four rules, tested against
seed data including a student with two fee accounts.
When to stop prompting
| Situation | Do it yourself |
|---|---|
| Third attempt still wrong | Yes — the prompt is not the problem |
| Business logic you understand better | Yes |
| Anything security-related | Yes, or review it as if hostile |
| A change you could type faster | Yes |
| Code you would not be able to explain | Yes |
| Boilerplate DTOs and mappers | No — generate them |
Three failed attempts means the task is under-specified or genuinely hard. More prompting fixes neither, and the fourth attempt costs more than writing it.
Correcting generated code you do not understand is the worst position available. You are debugging someone else's assumptions with nobody to ask.
Your AI evidence log
Start this now. It takes a line per week and it becomes an interview answer.
Week 14 Generated FeeRepository.GetDefaultersAsync.
Took schoolId as a method parameter fed by the query string.
Fixed to read the claim. Would have leaked across schools.
Week 16 Generated grading logic. Absent check was second.
Absent students would have shown as Fail on report cards.
Week 17 Generated a payment endpoint. Amount was double.
Changed to decimal.
Week 19 Generated a React list. No key prop, and no empty state.
By week 24 you have a real record, and this is the answer to "do you use AI?" that separates you from every other candidate:
"Yes — and I review it against a checklist. On my project the generated repository method took
SchoolIdfrom the request instead of the token, which would have let one school read another's students. I keep a log; it happened four times in six months, always the same four kinds of thing."
Nobody can rehearse that. You either did the work or you did not.
Common mistakes
- Asking for a whole feature at once
- Accepting code without reading it
- Treating "it compiles" as verification
- Generating things you have not learned yet
- Not checking the four silent rules
- Keeping abstractions you did not ask for
- Reading the summary instead of the diff
- Generating on top of uncommitted work
- Prompting a fourth time instead of writing it
- Not keeping the evidence log
Practice
- Ask for a complete feature in one prompt. Count the lines. Time a proper review.
- Build the same feature in six verified steps. Compare the time and the bugs found.
- Write a full context prompt with your entity, one real method, and the four rules.
- Prompt without the tenant rule. Check where
SchoolIdcomes from. Record it. - Ask for grading logic five times. Count how often the absent check is first.
- Generate a money field. Check the type in both C# and SQL.
- Generate a multi-statement transaction. Check every command receives it.
- Commit, then generate, then read
git diff --stat. Note anything unexpected. - Prompt three times for something it keeps getting wrong. Then write it yourself and compare.
- Start your evidence log today. One line per finding.
Exercise 5 gives you your own number for how often this fails. Whatever it is, that is the rate you must catch in review.
You can now
- Tell learning-mode from building-mode, and choose deliberately
- Size a change so you can verify it
- Give a model the context it cannot infer
- Check the four rules that fail silently
- Read a diff rather than a summary
- Know when to stop prompting and write it
- Keep an evidence log that becomes an interview answer
Review questions
- Why is a 400-line generated change worse than six 20-line ones, even if it works?
- Which four rules produce no error when broken, and how do you test each?
- Why read the diff rather than the AI's description of what it did?
- What makes the evidence log impossible for another candidate to fake?
Next: Add an AI feature