Iterate to More Complexity
Simple code is good. Really good. Simple code is easy to understand, easy to debug, and easy to modify. Everyone can understand simple code, even junior engineers. Simple solutions are stable and reliable.
Always try the simple solution first, no matter what. Even if it’s so simple that it feels dumb, try it out. If the simple solution works, that’s great! Ship it and move on to the next task. You’d be surprised at how often a simple solution is all you need.
You can always iterate to a more complex solution later on if needed. It’s much harder to start from a complex solution and iterate to a simpler one. More often than not you’ll never need the more complex solution. When you do, you can iterate on the simple solution to add the functionality that you need.
If possible, never start with a complex solution. Most of the time you don’t need that extra layer of abstraction in your code, or that added redundancy in your infrastructure from the start. All it does is add complexity. It adds cruft and tech debt that make it harder to iterate on in the future.
Complex solutions are hard to reason about, hard to debug, and hard to modify. Complex solutions fail in unexpected ways that can leave you scratching your head.
Your simple solution may become complex over time after multiple iterations, and that’s okay. The solution should evolve over time as the requirements change. It’s entirely possible to iterate on a simple solution and still keep it simple. Only iterate when it’s absolutely needed, and only iterate when you know what functionality needs to be added.
Always start with the simple solution first, and iterate to a complex solution later if needed.