Photo by James Lee on Unsplash
A year ago I almost fell into a trap.
A trap I see people fall in time and time again. Sometimes it visible staring us in the face and other times it’s harder to see.
It’s the feeling of wanting to rewrite code that isn't ours.
It’s thinking that rewriting code is easier than understanding the code we just inherited.
It’s the feeling of anxiety as you inherit code, and just want to rewrite it.
This is what I identify as The Code Rewrite Trap.
If any of those feelings or thoughts resonate with you, then continue reading this short post where I will share with you my recent experience of almost falling into this trap and ways we managed to steer around it.•••
Falling into the trap
A year ago I decided to leave a well-paid job at a large successful company to join a small start-up called DeadHappy. We had just secured our Series A funding and already had an MVP product out in production (written in PHP). I was hired to help build up the architecture, technical team, and continue to support and build our product.
Before joining we already made plans with the CTO to rebuild the architecture and platform. That was the plan. That was the trap.•••
After a decade of software engineering, I have seen many people (including myself multiple times) fall into this default way of thinking, the feeling of wanting to rebuild or refactor code we inherit, code we work on and ultimately code we don’t understand.
I have no idea why… maybe as engineers, we subconsciously think in this way?
As engineers, we love to build stuff. It’s what we do and crave. So when we get an opportunity for a greenfield project we tend to jump at the chance right?
It was definitely my thinking at the time, but I soon learnt it wasn't the right thing to do and to be honest… it often might not be.
Over the last year, I have learnt there are ways to refactor, continue to add features and ultimately continue to deliver value without a massive upfront rebuild.
But before we go into them, first let’s talk about the problems of a rewrite.•••
Potential problems with a Rewrite
So put yourself in our position.
We just inherited a domain and codebase our team wasn’t familiar with. Everything in our gut was pointing to a rewrite in a language we could support and architecture we could be comfortable with.
Now given the age of DeadHappy and things we need to deliver to survive a massive rewrite probably isn't going to be the best option.
Think about it. Spending the next 3–6 months rewriting value that we already had seems a bit mad.
Why should we replace the existing value with the same value just written differently?
So if we decided to rewrite what would our customers get? Not much really...
So what options do we have?
Well we know we have to be Agile, develop features at speed and move over to an architecture we want to build and support.
So where do we start?
It all starts with the domain.•••
Understanding the domain
Something I wished I had done sooner when joining DeadHappy was to really understand our domain.
I thought I had a good understanding, but did I really understand it?
I’m talking about understanding the customers, business, domain and it’s bounded context.
So what is the best way to understand the business domain? Luckily there is an exercise that can help: Event Storming.
EventStorming is a flexible workshop format for collaborative exploration of complex business domains. — https://www.eventstorming.com/
Event Storming is a great way to get a team (new or old) to start documenting and understand the domain they are operating in.
Event Storming can work with new and old projects. The idea is everybody maps out events, commands, actions and starts to paint the picture of the business domain.
Naturally, domains start to form and the bounded context becomes quite visible and it’s easier to start to look at domain-driven designs.
To help us rebuild and refactor we have to understand the domain.
Unfortunately at DeadHappy, we did this late in the process. I spent hours talking to people, going through the code to build up my own version of our domain. I believe if we had done this sooner, it would have helped out massively. Next time I will start with this.
The best thing about Event Storming is we get a shared understanding of our domain and that is invaluable.
Once we understand our domain it becomes easier for us to understand and design the architecture we want and start to plan a migration plan towards it whilst still adding value to customers.
Breaking into parts
So we just inherited a codebase. All the domain was within one application.
So whats next?
One option is we could start by chopping up the code into small microservices, modules and applications?
That would be a good strategy, but we have to remember the Code Refactor Trap here in this context. Why replace the existing value with the same value?
Now some of you might be thinking rebuild and refactoring is good. Yes is it. There will be times we need to move over to new software and architecture and replace things but in the context of just joining a fairly new startup, it wasn't really the right thing to do here. We have to always remember the context of what you're doing and why.
So at this point, we have a good understanding of our domain, we know we have an application that is quite coupled together, we want to move into an architecture we are comfortable with and a language we can support.
I recommend starting by understanding what’s coming up next. What features are coming up, what parts of the domain will be worked on next? Where is the technical debt?
Ask yourself, Is it possible to rebuild whilst adding value?
Rebuild whilst adding value
Ideally in this situation, we want to rebuild as we add value. Remember as I said above we don’t have months to sit in a dark room refactoring over, we need to continue to move, add features and build architecture.
So how can we do this?
We need to learn how to rebuild or refactor our software whilst we continue to add value. We need to be aware of falling into the Code Rewrite Trap and challenge our thoughts.
To help us, let’s go through a quick example together…•••
Let’s say we have inherited an application. Everything is in one application. You identify that your business has these domains:
- Store (Customers view products)
- Customer Account
- Insurance Processing (Business rules for insurance rules)
Let’s say we are tasked to redesign the UI for the store and add some new features.
So here are some options that might be presented to us (all are legit)•••
Option 1: We rebuild the store into its own domain and add the features (Rebuild Approach)
This approach will allow us to move part of the domain out of the legacy system and start to rearchitect and plan for the future of this domain better than was originally designed.
The major tradeoff here is it could take more time and get things done but benefits would be you are a step forward adding value whilst rebuilding.
Option 2: We keep the store within the existing application and add the features there.
This approach might allow us to deliver the feature faster but comes at the cost of maintaining and adding to the debt we have to migrate over later.
The major trade-off here is time vs debt.
Option 3: We rebuild parts of it whilst keeping parts within the original application. (Hybrid Approach)
This approach allows us to start to move over to a new design and architecture whilst still keeping our foot in the other application.
An example here might be creating a new front end application whilst continuing to use the APIS from your existing application.
We benefit here as we are moving towards a target solution, but we also might not tackling our debt as we keep the code we already have.•••
The problem is, that all these options are legit. They will all work but each one of them will have its own set of tradeoffs.
Understanding the tradeoffs will really help us make informed decisions, but equally remember we will never get everything right. Something I have learnt is if you can get things about 80% right, it tends to end up OK.
So which of the option do we choose?
Well, it depends (sorry)…. but here is a quick formula that might help:
- If the effort to rebuild is slightly greater or equal to doing the work in the existing app we will rebuild it whilst adding the new features.
- If the effort is greatly increased doing a rebuild vs doing it in the existing app it needs to be thought about, and trade-offs thinking about.
- If the effort is super small do it in the existing app. (Comes with costs)
Our choices here aren't black and white. Building software isn't easy.
We have to understand the tradeoffs, the domain and make decisions that make sense to us.
Just rebuilding things because we fall into this “Code Rebuild Trap” doesn't really make much sense, and I feel we can challenge our own thoughts.
I have used these thoughts and techniques for my first year at DeadHappy to help guide our team into a planned architecture whilst still adding value. I’m glad we didn't just rewrite our application but started to split up the domain and start to rewrite areas when we could also add value.
I have fallen in this Code Rewrite Trap many times before and will no doubt will continue to fall into it but this time I’m aware.
I have learnt that many of us believe it’s easier to rewrite things than it is to understand them, I feel this is just a natural way of thinking.
I believe we have to challenge our own thought process and be aware and learn what other options we have available to us.
At times rebuilding/refactoring does make sense but just remember we might have other options to consider. We need to take time our think about them.
We need to spend time understanding our domain and code before we tackle it.
Can we add value whilst migrating over to a new architecture vs sitting in a dark room for months rewriting value we already have?
Ultimately I learnt we need to make informed choices, understand our tradeoffs and be aware of the Rewrite Trap.•••
In the fast-paced world, we live in today, most companies are trying to add value to their customers as fast as possible.
Falling into the trap and locking ourself away to rebuild and refactor things without understanding the cost vs value is dangerous. We need to think and strategise our refactors and rebuilds. Understand the tradeoffs and explore our options.
My Key Lesson I learnt: Take time to think, explore options and continue to work in ways that can add value.
If you got down this far, well done 🙏. I hope you enjoyed reading this post. I would be keen to hear your thoughts or experience. This post was mainly a note to me to try and stay out of the rebuild trap and think about things. Hope it will help you too.