Customers don’t ask for Refactoring
When you ask your engineering team to extend feature X and they tell you they need to completely refactor before shipping. Sounds like your recurring nightmare?
The hip lean startup approach teaches us to build the most minimal [viable/lovable/you _name_it] version of a feature that maximizes learning at high customer value and low effort to build. This is especially essential at startups, where resources and runway are always short and the time to market and learning cycle makes the difference between growing revenue and going out of business. So, clearly, as a product manager, we’re keen on taking short cuts to get things shipped fast while retaining a certain level of quality.
This makes the company and customers happy, but the developers unhappy. I have not worked in a single company, be it mature or in a startup phase, be it large or small, where retrospectives would not continuously contain developers wishes to “stop shipping feature after feature”, “get time to refactor to reduce technical debt”, “rewrite X” or “get rid of all that legacy code”.
I remember one specific retrospective at which I got quite upset about a similar statement and started quite lengthy discussions with various people about this topic and this blog post puts the results and thoughts into a more structured form:
- The difference between legacy code and technical debt
- The motivation of both sides of the table
- Understanding and assessing the risk of technical debt (and stuff no one dares to say)
- Best practices to handle technical debt
The difference between legacy code and technical debt
Even engineers mix those two concepts up but I believe it’s worth noting the difference:
Code is legacy code as soon as it’s written.
While you may find other definitions available as well, I prefer this one as it really nails it down to the core. Whatever you implement, no matter how well designed, documented and tested, that code may at some point be outdated, you may move on to work on different parts of the system or inherit that code to another engineer in your team.
Technical debt is dirty code that you create deliberately.
Delivering features quickly or resolve incidents quickly quite often means to cut corners, sacrifice UI/UX design or software architecture and/or implement dirty hacks. This technical debt accumulates over time making the system harder to maintain and improve and harder for the user to understand and use.
That being said, I don’t believe there’s ever a system that is free of technical debt and as product managers we’ll always hear above noted feedback from our engineering teams. But there are always two sides of the table and the ones making product decisions and the ones implementing and maintaining the product need to better understand each other’s viewpoints.
Understanding both sides of the table
Depending on the roles we have throughout the product lifecycle, naturally our interests diverge.
The business stakeholders main interests are to keep the business afloat and growing while delivering continues customer and business value. Especially in a startups, product managers and business executives often ask what can be done to deliver X in half the time to have a quicker time to market. We don’t do so that to annoy engineers, we do that to get customer feedback and business value earlier, especially if this is means to keep your startup operational and staying ahead of your competition. (Note: I don’t support arbitrary short deadlines for the sole sake of a timed press release, but that’s material for another blog post)
The engineers main interests (based on my experience) are a sum of delivering quality code they are proud of, they are challenged by doing so, they can try and implement new technologies and design solutions that are easy to maintain and scale. While I know some engineers who love to hack things, most hate to cut corners and are demotivated by reducing scope when developing a first version of a feature. I also know that inheriting code sucks, and you’d rather rebuild/refactor it to “own” that code base and know what’s going on there in case of an incident.
Understanding and assessing (the risk of) technical debt
The different interests lead to a dilemma: How much time should we be focusing on dealing with technical debt at the expense of shipping features to our customers faster?
Truth to be told, I don’t believe there is a general answer to this question. To my own experience this depends heavily on the context you’re operating in. How mature is your company? How mature is your product? What is the size of your company? Is it B2B or B2C? What’s the financial situation of your company? What’s the competitive landscape? …
Avoid technical debt in the first place is not possible and the only way to handle debt is to manage it properly and ensure the root causes are thoroughly understood.
Technical debt may also have a cultural root cause
Especially at super young startups, or when developing a new product, business stakeholders may be inclined to take huge risks when accepting technical debt deliberately and that’s ok. Especially early adopters know that, will be patient and may even help you improve.
But not acting on it as the company and the product matures, is bad leadership and bad culture. After you’ve reached a certain stage and customer volume, fixing things only when they break or changing requirements last minute before a planned release, will have a massive negative impact on your brand, your hiring and retention success and ultimately on your revenue and competitiveness:
- Imagine a bank that does not fix security flaws or looses your transactions. Would you trust that bank?
- Imagine a company where you work with outdated technology and extinguish fires all day instead of new features or architectural changes. What competitive advantage does that bring to your career?
Good (technical) leadership includes:
- to introduce and enforce development standards
- to develop and maintain a clear IT strategy (in accordance with a business and product strategy)
- to follow and improve your product development and decision making processes
- and last but not least to foster ownership and accountability across all levels of the company
Good (product) leadership also includes:
- to listen to the feedback of your team and understand the root cause
- to share your prioritization and reasoning with the team (and make sure you have all the information you need to do so)
- to ensure a common understanding on the importance of this topic across all stakeholders
- to regularly iterate on features (improve them if they are successful, remove them if they failed your experiements)
Plan your debt Imagine you’ve done your research and are convinced there’s a great business case for developing this new feature or product. Following the lean startup you define and build a minimal version of it. When you do the planning for the MVP and decide what’s part of it and what is not, take a bit of additional time to also estimate the parts you won’t do — this not only enables you to reconfirm what’s part of the MVP and what’s not, but also gives you an idea of the costs you need to accept for a potential version 2.
Prioritize your debt: Similar to keeping your product backlog and roadmap up to date, you should maintain your technical backlog (and ideally, they are not separate). Ensure the most critical and pressing items are known to all decision makers (including the consequences of not doing it now) and this list is updated on a regular basis. I personally believe also business stakeholders and executives should be aware on a high-level what the technical items are the team is working on (or at least the amount of time spent on these items).
Pay off your debt: The most profitable time to pay off technical debt is as part of an effort to improve or extent that system part in question. Or if another feature starts to utilize that part. Avoid huge rewrites or redesigns, if possible instead refactor incrementally (On a side note: I’ve gone through huge rewrite projects and to my experience they are impossible to properly estimate, happy if you proof me wrong;-)).
The customers aren’t asking for refactoring or rebuilding. They are asking for product features to work properly and they are asking for new product features — all of it ideally now. They couldn’t care less if it’s implemented as spaghetti code, a not-so-cool programming framework or non-documented code.
If you’re an engineer, next time you want to refactor, reason your request. Provide an assessment what will happen if the coding issues are not dealt with within a given timeline and list possible solutions with proper estimates.
If you’re a business stakeholder, listen to your engineering and design team as an investment into your company’s and customers future and explain your decision making in detail to the team.
Do you have best practices to share how to manage technical debt? Let me know in the comments!