Patterns first, principles second: how I teach architecture to junior-heavy teams
Senior engineers reach for principles first because principles are how seniors think. Juniors learn the other way round. Here is why patterns-first teaching transfers more reasoning capacity per hour of mentor time, and when to flip the order.
The ordering most seniors default to
When a senior engineer is asked to bring a junior up to speed on a codebase, the instinct is almost always the same. Start with the principles. Separation of concerns. Single responsibility. Don't repeat yourself. Dependency inversion. The grand ideas first, the code samples second.
I understand the instinct, because I have done it myself for years. The principle feels load-bearing. If you understand the principle, you can derive any number of patterns from it, so teaching the principle feels like the high-leverage move. You are handing them the key, not one of the doors.
The trouble is that the ordering reflects how the senior thinks, not how the junior learns. By the time you are senior enough to teach, the principle and the pattern have collapsed into a single mental object. You cannot easily remember what it was like to hold the principle without any concrete pattern to attach it to. So you teach in the order that feels natural to you, and the junior nods politely, and then writes code that looks nothing like what you meant.
Why principles-first lands badly with juniors
The principle is, by definition, abstract. "Respect separation of concerns" is not a thing the developer can copy into their editor. It is a constraint on the shape of code they have not yet written. Until they have written a few endpoints, they have nothing for the constraint to constrain.
Worse, the principle is usually phrased in terms of what to avoid rather than what to do. Don't put business logic in the controller. Don't reach into the database from the view layer. Don't share state across boundaries. The junior is left trying to write code while a list of don'ts hovers over their shoulder, and the result is usually paralysis or a kind of defensive over-engineering where every layer is wrapped in a layer.
I saw this clearly on a recent engagement. Greenfield education-sector platform, around nine developers, the team weighted heavily towards juniors, including bootcamp graduates and a few people working in languages they had not used before. Vue at the front, C# and .NET Aspire at the back, Claude Code in the loop. If I had opened by lecturing on hexagonal architecture or the dependency rule, I would have lost the room inside ten minutes. Not because the ideas are wrong, but because the ideas had nothing to land on.
Patterns are copyable. Principles are not
What worked instead was leading with the pattern, fully worked. "Here is the BFF endpoint. Here is the request DTO, here is the handler, here is the response shape, here is where the validation lives, here is where you call the domain service. When you add a new endpoint, copy this one and change the parts that need to change."
That is a thing a junior can do on Monday morning. It does not require them to have a theory of layered architecture. It requires them to read one file and write a similar file. The cognitive load is bounded.
After two or three endpoints, something quite specific happens. They start asking the right questions on their own. "Why does the validation live here and not in the handler?" "What goes in the DTO and what stays in the domain model?" "Why is the controller so thin?" The pattern has given them a place to stand. From that place, the principle becomes visible, because they can see what the pattern is doing and what it is preventing.
At that point I will answer the principle question, but only because it has been asked. The principle has stopped being a rule imposed from outside and has become a piece of reasoning that explains what they have already been doing. It is theirs. It survives me leaving the engagement, because they did not memorise it from a slide, they reconstructed it from their own work.
A concrete contrast
Consider two ways of onboarding a junior to the BFF pattern.
The principles-first version sounds like this. "Your front end should not be coupled to the shape of your domain. The BFF exists so the back end can change without breaking the client, and so the client can ask for exactly what it needs without leaking domain concerns. Keep the BFF thin, but not so thin it becomes a passthrough. Aggregate where it helps the client, not where it helps the back end."
Every sentence there is true. None of it tells the developer what to type.
The patterns-first version sounds like this. "Open this endpoint. Notice the request DTO is named after the screen, not the entity. Notice the response is shaped to match what the Vue page renders, not what the database stores. Notice the handler calls two domain services and stitches them together, because the page needs both. When you build the next screen, do the same thing. If you find yourself writing a BFF method that takes the database row and returns it untouched, stop and ask whether the front end actually needs that exact shape."
The second version is longer, but the developer can act on it immediately. And after they have written four or five endpoints in that style, they will say something like "the BFF is basically a translator between the client and the domain", and they will be right, and they will have got there themselves.
What changes once the pattern is in their hands
The interesting shift is not just that the code gets better. It is that the conversation in code review changes. Instead of me pointing out that a piece of logic is in the wrong layer, the developer starts noticing it themselves before they push. Instead of asking "is this allowed", they ask "does this fit the pattern, and if not, why not".
That second question is the one I actually want them asking, because most of the interesting architectural decisions on a real project are exactly the cases where the pattern does not fit cleanly. You want a team that can recognise a misfit and reason about it, not a team that follows the pattern by rote and breaks at the first edge case.
You only get to that question by giving them the pattern first. If you start with the principle, they spend their first month trying to deduce the pattern from the principle, and they get it wrong in interesting and time-consuming ways.
The honest qualifier
This is advice for junior-heavy teams. With a senior team it can flip.
A genuinely senior team will push back on a pattern until you have argued the principle behind it, and they are right to. They have written enough code in enough patterns to know that a pattern without a justification is a cargo cult, and they will not adopt it on your say-so. With seniors, lead with the principle, then show how the pattern follows, then negotiate the edges. They will hold you to it, which is exactly what you want.
The mistake is treating one mode as universally correct. Patterns-first is not a better teaching method in the abstract. It is a better teaching method for people who do not yet have enough code under their belt for principles to mean anything concrete. As they accumulate that experience, the balance shifts.
The leadership angle
If you are the senior on a team and your job is to leave behind a group that can reason about the architecture without you, the question worth asking is how much reasoning capacity you transfer per hour of mentor time.
Principles-first feels efficient because you cover a lot of ground in a single session. In practice it transfers very little, because the team has nowhere to put what you said. They write it down, they nod, and then they write code as if the conversation had not happened.
Patterns-first feels slower at the start because you are showing them one specific thing instead of a general truth. But each pattern they internalise becomes a hook the next principle can hang on. By the third or fourth pattern they are deriving principles on their own, which is a much higher rate of transfer than you can achieve by lecturing.
The team I described earlier got to the point, within a few weeks, where the bootcamp graduates were giving sensible architectural feedback in pull requests. Not because they had read a book on clean architecture, but because they had written enough endpoints in a consistent style that the shape of good code had become familiar.
What I would do differently next time
The one thing I would change is the channel. On that engagement, the patterns lived mostly in code review comments and in the worked examples in the repository. That worked for the people on the relevant pull request, but it left the rest of the team to absorb the pattern second-hand.
Next time I would pair the patterns-first review style with a short written patterns document in the repo. Not architectural decision records in the formal sense, just a running list of "here is the pattern we use for X, here is a worked example, here is what to watch for". Two or three paragraphs per pattern. Updated as the team finds the edges.
That gives the people not on a given PR a way to pick up the pattern without waiting for it to come round to them. It also gives the team a place to push back, because once the pattern is written down, it can be argued with. Both of those are good for the team, even if they are slightly more work for me.
Closing thought
Principles are how seniors think. Patterns are how juniors learn. The order that feels natural when you are teaching is almost always the order you arrived at the material yourself, and that order is rarely the order the learner needs.
Teach in the order they need to learn, not the order you think. The principles will arrive on their own, and when they do, they will belong to the team rather than to you.
If any of this resonates and you are weighing up how to bring a junior-heavy team up to speed on a new platform, I am happy to compare notes. No pitch, just a conversation.
