Designs aren't mistakes they are decisions
Created on July 25, 2026.
I recently have been working on a large refactor of a code base. The biggest driver of this was the scalability of adding more teams onto our platform and the requirement of a lot of duplicate code to handle it. It led to me thinking about decisions I have made over the years in software and a refactor like this becomes necessary as a team progresses.
A tale of scopes
If I told you, I have a platform where every time you add a team to it, you have to add 10 new classes and redefine handling of parameters that are used on various field types. Most of this being copy and pasted files with slight edits. The growing file list is now 40 of each of these classes. The resulting PRs are mostly boilerplate. You would likely think that someone made a mistake in the design and are regretting it now.
Let’s flip the script though. What if I told you that I had a system with 5 pages and 3 layers of abstraction allowing you to define the list of inputs and things just work, but requiring a thousand lines of glue code to handle it. At that point, you are likely asking why someone decided to go to extreme levels of abstraction to get a system started.
In this case, both of these designs aren’t bad, but they are being used in the wrong scopes. Having abstraction to cut down on code duplication when you have a few items is much less important and can even be detrimental when you have a small scope, but can be a huge time savings and scalability win when you have a large scope.
Tradeoffs change
Every design comes with choices of tradeoffs. A tradeoff that makes sense within the initial scope of a project, might become a large disadvantage as that scope changes over time. Like in the previous example, abstraction is an important choice in the larger scope, but would’ve created a possible timeline tradeoff in the initial setup that would’ve made it hard to ship in time. By knowing the chosen tradeoffs we can then apply that list to our current view and see if the original design still makes sense.
The importance of empathy
Remembering the changes in the scope and important tradeoffs is important for anchoring your discussions into a form of empathy. We have all been in design discussions where we are questioning why a design choice was made and understanding those reasonings rather than immediately trashing the design, it is key to be more empathetic and to understand the ramifications of changing that design.
Having a design discussion with the original creators can be extremely beneficial because they can provide insights that you might not otherwise have. Entering those discussions without anchoring yourself in that empathy will lead to defensiveness and a general discontent between those involved. Remember that they had reasons behind their designs and tradeoffs that they were trying to optimize for. Those tradeoffs might not be the same ones that you care about now, but they might have other designs that they looked into that could give you a starting point. They also might have explored something and found a reason it didn’t work that having that information will save you discovery time.
An empathetic approach also shows the other engineers in the room that you are open to feedback and understanding, which makes them more likely to provide effective feedback on your designs. It also sets the stage for the other engineers in the room to feel comfortable coming to you with designs later. So, I will end on this last reminder, software designs aren’t mistakes they are decisions that were made with purpose and should be treated as such.
Previous