In my first few years as an engineer, I’ve been exposed to a wide variety of software products. On one hand, I’ve sifted through million line classes attempting to repurpose an existing feature to fit new requirements. On the other, I’ve created the initial commits for brand new repositories.
My current role has given me reason to reflect on these experiences. I’ve wondered, are all software products doomed to become legacy code? Is it possible to create a system that always seems greenfield? In short, can we create evergreen software?
Legacy Code
Before we talk about a potential solution, it’s important to debunk a myth surrounding legacy code: the chosen technology does not determine if a codebase is considered legacy. Yes, an older technology can contribute to the problem but a codebase does not become legacy the minute a shinier framework comes along.
The stronger determinant of legacy code is the amount of bugs in the system and their relationship to feature development. As the number of bugs in our system grows, our ability to produce high quality features shrinks. At some point, feature development becomes nearly impossible and a rewrite is on the horizon.
The Solution
So how do we avoid the problem? How can we ensure our code always feels brand new and that our velocity accelerates over time? Simple, we fix bugs before implementing features.
Downsides
Before we talk about the benefits of such an approach, it’s important to consider the downsides. What do we lose when features come second?
The biggest thing we lose is feature velocity in the short term. This is particularly true of older systems where fixing every bug would take weeks or even years. Systems like these may need to bend the rules to start trending in the right direction.
A good way to start is to always fix bugs that come about as a result of new development. From there, we can prioritize long-standing issues and new features according to their importance. Such a methodology would ensure our bug count is always going down, which will speed up future development.
While feature velocity is usually a bigger concern for older systems, it’s important to consider the startup implications as well. With startups in general, speed is usually the primary concern. Can we build this feature before our competition? Can we innovate faster than our competition?
Let’s consider two startups, Startup A and Startup B. Startup A priorities features over bugs. And startup B priorities bugs over features. In the short term (6 months – 1 year), startup A will probably win. Their small team of developers understands the entire system. They probably work on both sides of the stack, meet regularly with customers, and understand every feature the company has put out.
But what happens when they start showing signs of success and enter a period of hyper growth? Can they sustain their velocity per developer when each developer only touches a piece of the system?
No way. Instead of paying the price while the team was small, they’ve now multiplied the adverse effect of their early strategy. An entire team of engineers is now building additional features on top of a brittle foundation.
Upsides
To me, it seems like all of the downsides are short term. Let’s consider now the far reaching implications of defect-first development.
Features
The biggest thing we gain in creating an evergreen system is a steady flow of features. Why? Because developers who would otherwise be focused on bugs can fully focus on feature development.
Here’s what I’ve seen in terms of development time in the projects I’ve worked on:
As a project gets closer to being a legacy system, developers spend less and less of their time on features. Even feature-tasked developers move slower in hopes of not breaking existing functionality.
Customer Experience
Aside from additional development resources, the customer experience changes. It’s rare to have a bug free experience in software but when you do, there’s no denying how it makes you feel. This is particularly true of mission critical software where a bug can have huge financial or life-changing consequences.
Developer Retention / Acquisition
Additionally, it’s much easier to retain and attract top talent. Let’s be real, it a competitive engineering market right now. If you’re a talented developer in the market and everything is equal between two companies, are you more likely to take the feature development position or the bug fix position?
Finding Hives
In moving to a bug first approach, you’ll actually end up fixing less issues in total. Why? Because it’s easier to identify hives.
In most software systems, bugs have a similar priority to features. After a bug is found and groomed, its added to a process management tool like Jira. The product team or a project manager will then prioritize these tickets and development will pick them up as part of a sprint or a given phase.
Often times, this means that bugs from a similar feature or place in the code are spread out across multiple months. These bugs may even be spread out across multiple developers.
Now imagine we could see them all together. We’d quickly realize where the bugs are coming from. Instead of eliminating them one by one, we might decide to rewrite a given component or restructure a given service.
Pulling bugs to the top of the queue helps us to see these trends faster. The quicker we recognize hives, the less development time we waste.