Systems As Mirrors
Conway’s Law tells us systems reflect their makers. But what if they reveal more than structure — what if they surface what we didn’t define? There’s something quietly unsettling about Conway’s Law. Most people who’ve worked in software long enough can sense its truth. What unsettles is what it reveals when you sit with it. The law definition, in its original form, is: Organizations which design systems (in the broad sense used here) are constrained to produce designs which are copies of the communication structures of these organizations. — Melvin E. Conway, How Do Committees Invent? At first, it seems structural. Org charts become system diagrams. Split your teams by department, and the system splits the same way. But over time, the reflection deepens. The system doesn’t only mirror who talks to whom — it starts echoing what’s understood, and what’s avoided. The most confusing systems I’ve seen don’t reflect complexity. They reflect ambiguity. You see it in familiar places. One service checks a user’s admin flag. Another checks something else entirely. A third overrides both. A field like “approved” means one thing to scoring, another to compliance, and something looser to product. The code bends around uncertainty. But what it adapts to isn’t complexity — it’s a missing decision. This gets worse when teams try to support everything. A lending flow starts with a clean path. Then you add freelancers, students, returning users. You don’t create new flows. You add flags: Each rule makes sense in isolation. But together, they blur the center. “ApplicationApproved” starts meaning different things depending on the path taken. Eventually, no one can say what it means — only how it behaves under certain conditions. The system still works. But its meaning doesn’t. This is where outcome-driven modeling helps. Jobs To Be Done is one approach. It shifts the focus from who the user is to what they’re trying to accomplish. It asks what outcome they’re hiring the system to deliver — and what tradeoffs they’re willing to make. A persona tells you the user is a freelancer who prefers mobile and has irregular income. The job tells you: access a short-term loan using recent invoices. Suddenly, the model sharpens. Income is about pattern, not payslips. Risk is about volatility. Rejection isn’t the fallback — manual review is. When you model from outcome, the system knows what it’s trying to do. This is also where domain boundaries matter. Domain-Driven Design introduces the idea of bounded contexts: each part of the system defines its own meaning. Duplication isn’t always a mistake — it’s often how clarity is preserved. Reuse works best when meaning aligns. Take the classic Some say duplication is always bad. But that’s a narrow view. It depends on what’s being repeated. Echoing confusion spreads it. But repeating meaning reinforces clarity. Duplication isn’t the enemy — imprecision is. Once each model speaks a single truth, everything downstream improves. The backend is easier to debug. The frontend becomes more predictable. Changes get safer. Teams stop negotiating the meaning of basic terms and start delivering again. And that brings us back to the mirror. Conway’s Law tells us systems mirror their makers. But reflections go further than structure. They echo our indecision, our shortcuts, the choices we didn’t make. So the real question is:hasPayslip
, isStudent
, incomeSource
. Logic branches. Models fork. Scenarios pile up.User
model. In KYC, it means identity: documents, name, status. In Scoring, it means applicant: income, employment, credit history. In Auth, it means account: credentials, sessions, MFA. Reusing the ID is fine. Reusing the model leads to something brittle: dozens of nullable fields, conflicting assumptions, tangled dependencies.
If every system is a mirror — what part of ourselves are we willing to see?