Tips to junior developers, now that a coding agent writes the code
In 2017 I wrote four tips to junior developers. Your application is never done. Don't judge other people's code. Never fix a bug until you understand why it happens. Fast programmers aren't necessarily better programmers.
They still hold. But every one of them was about the code you type yourself, and today a coding agent does most of the typing. It writes faster than any of us ever did, and it never gets tired of boilerplate. So the question for a junior is no longer how to write the code. It's how to tell whether the code that was written is any good, and how to build a code base where the coding agent finds its own mistakes.
That takes a different set of skills. Here they are.
Learn architecture before syntax
A coding agent can write a function in any language you ask for. What it can't do on its own is decide where that function belongs.
That's architecture: which part of the system owns a concept, what may depend on what, and where the boundaries go. Get it right and a change touches one folder. Get it wrong and every feature is an edit across ten files, which the coding agent will happily make, and which nobody can review.
So learn to read a structure, not a line. Why is business logic kept apart from data access? Why organise by feature instead of by technical layer? What happens to a code base when everything can call everything? A junior who can answer those questions can review a coding agent's work. A junior who only knows the syntax can check that it compiles, and the compiler already does that.
Learn how the whole solution fits together
Above the code base sits the solution: the services, the database, the queue, the third-party API, the background job. Most production problems live in the seams between them. A timeout nobody chose. A message processed twice. A database transaction that commits after the response was already sent.
A coding agent writes each piece correctly in isolation and has no idea how they behave together under load or failure, unless someone designed for it. Learn what happens when each piece is slow, down or answers twice. That is where your judgement is needed, because it's exactly where the coding agent has none.
Know what every pattern costs
When I started, learning a pattern felt like collecting a tool. Repository, unit of work, inheritance, events, dependency injection. The more you knew, the better.
Patterns aren't free. Each one buys something and costs something, and the cost usually shows up later, in someone else's hands. A generic repository saves a few lines and leaks the database into the domain. A base class saves duplication and forces every reader to open two files to understand one. Events decouple senders from receivers, and make it impossible to see from the code what happens when you send one.
A coding agent knows every pattern, and has no opinion on when one is a mistake. Ask it for a clean architecture and it will give you one with all the layers, whether your problem needs them or not. Your job is to know the consequences: what a principle protects you from, and what it costs when there is nothing to protect.
Learn to measure quality
"It works" is the only thing a coding agent's output reliably is. Whether it's maintainable is another question, and you can't answer it with a feeling.
So learn how quality is measured. How complex a function is, and when it's too complex to follow. How big a file or a type may grow before nobody can hold it in their head. Which duplication actually costs you and which is harmless. And above all, what a test proves: a test written from the code asserts what the code already does and breaks on every refactoring, while a test written from a business rule fails exactly when the rule breaks. I wrote more about that in How do you know the agent isn't quietly rotting your codebase?
Numbers don't replace judgement, but they tell you where to point it.
Learn error management, properly
This is the one I would put first.
When I coded everything myself, every reported error hurt. It interrupted what I was doing, it usually came with too little information, and I had to dig through logs and a debugger to work out what happened. It was tempting to make errors go away: catch the exception, log something vague, return a default and move on.
With a coding agent, that changes completely. Every error that is reported is a gift. The coding agent reads the message, finds the line and fixes it, often in the same run. An error that is swallowed is the opposite: the coding agent can't see it, so it can't fix it, and it carries on building on top of a broken assumption.
Compare these two:
InvalidCastException: Unable to cast object of type 'System.Int64' to type 'System.Int32'.
Column 'age' is Int64, not Int32.
The first one sends the coding agent guessing through every cast in the file. The second one names the column and the types, and the fix is one line. The difference isn't the coding agent. It's the person who designed the error.
So learn what exceptions are for, and be strict about them:
- Fail when a function can't do what its name promises. Don't return null or a default and hope the caller checks. A failure that happens far from its cause is the most expensive kind to find.
- Fail early. Check arguments and state where they enter, not three calls later where they blow up.
- Put the context in the message. Which value, which entity, what was expected. Write it for a reader who sees nothing but the message, because the coding agent is exactly that reader.
- Never swallow an exception. An empty catch block is a bug. If you can't recover, let it pass.
- Only catch where you can do something. Recover, or add context and pass it on. Everything else is caught once, at the top, and reported.
- Keep the original. Wrap it as the inner exception, so its stack trace survives.
I wrote about this more than ten years ago, in What are exceptions?, How to design exceptions and Throwing exceptions. Back then, strict error handling saved you hours of debugging. Now it decides whether a coding agent can fix its own mistakes, or has to wait for you to find them.
The old tips, revisited
Your application is never done. Still true, and it changes faster than ever. A code base that a coding agent changes every day needs boundaries that hold, or it decays one reasonable change at a time.
Don't judge other people's code. Still true. Now some of that code is the coding agent's, and judging it is your job. Judge it against rules you can name, not against taste.
Never fix a bug until you understand why it happens. Still true, and now it's also about the system. If you had to dig to find the cause, the next bug will hide the same way. Fix the bug, then fix the error that should have told you.
Fast isn't better. The coding agent is fast. Your value is in knowing where it's going.
The new four
If I had to put it on a sticky note today:
- Learn where code belongs, not just how to write it.
- Know what every pattern costs before you use it.
- Measure quality instead of feeling it.
- Make every error loud, early and precise. A reported error is the fastest feedback a coding agent can get.