Engineering Practice · 3 min read
Engineering Lessons: Why Simple Code and Simple Systems Win
Clean code is not architecture, and more abstraction is not better. What years of building taught me about simplicity and seniority.
By Ali Iftikhar · · Updated

Some of the things I was most confident about as a developer, I no longer believe.
Five years ago I thought I knew what good engineering looked like: more clean code, more abstraction, more planning, more complex systems. I was wrong about some of it.
"Clean code means good architecture"
It does not. You can have beautifully written code inside a system that is painful to change.
Clean code makes a function easy to read. Architecture decides whether the system can evolve: where boundaries sit, how components depend on each other, and how much a change in one place disturbs another. You need both, and the first does not give you the second.
"More abstraction means better engineering"
I used to equate more layers, more patterns and more flexibility with quality. Sometimes that is just making a simple problem complicated.
An abstraction has a cost: every new layer is something the next developer must learn before they can change anything. It earns its place only when it removes more complexity than it adds.
A rule I use now: wait for the third use. Do not abstract after the first case. Often not after the second. Abstract when the pattern is real.
"Plan everything before writing code"
I used to want everything figured out before the first line was written. Now I have learned that some things only make sense once you start building.
You cannot predict every problem from a diagram. Planning still matters, but I now prefer:
- Plan enough to choose a direction and spot the biggest risks.
- Build a thin vertical slice that works end to end.
- Learn from it, then adjust the plan.
"Senior developers write complex systems"
The biggest change is how I see seniority. I thought it meant writing sophisticated systems and clever solutions. Now I think it is often the opposite.
The best developers I have worked with usually make things feel simpler. They know:
- when to build,
- when to wait,
- when to simplify,
- and when not to build anything at all.
A simplicity checklist
When I review a design or a pull request, I ask:
- Could this be done with less? Fewer moving parts, fewer services, fewer config options.
- Is this solving a problem we have today? Or one we imagine we might have?
- Would a new teammate understand it in ten minutes?
- What is the simplest thing that could possibly work, and why is that not enough?
- Can we delete something instead of adding something?
Deleting code is underrated. Code you never write has no bugs and needs no maintenance.
Why this matters even more with AI
When AI can generate large amounts of code in seconds, complexity becomes dangerously cheap to create. The skill that stays valuable is knowing what not to build. I wrote about the related risk in AI is making developers stop thinking.
What experience actually teaches
Maybe that is what experience really teaches you. Good engineering is not about handling complexity. It is about not creating it in the first place.