Introduction
The fear of executing on a plan is one of the most dangerous mindsets that can start to creep its way into development teams. You've probably seen it before: the meetings that lead to more endless meetings, the endless research, the what-ifs, and the unknown unknowns. It ends with a paralyzing fear of making a plan and executing on that plan. Often, this fear leads to abandoned refactorings or feature improvements that get tossed into the 'what could have been' graveyard. Realistically, this failure falls on leadership and senior developers. Getting through that mindset and pushing forward requires a collective effort to do the hard things. It's often said in the military that a plan is only good until first contact; the same logic can be applied to software development. You can make a plan, but the first unknown you hit, the plan is no longer effective. You need to move past that fear and learn how to evaluate, adapt, and change course.
How does this fear manifest?
There are a few clear warning signs that this mindset is starting to take hold. The most obvious is when teams start moving away from making small changes in legacy code because it simply needs to be rewritten from scratch, which will rarely happen without a substantial benefit to the business or client. This idea of needing to start over exists because developers are afraid to make changes to the legacy code. So instead of researching, creating a plan, and executing that plan, it just goes straight to impossible. Realistically, you can make small controlled changes hidden behind feature flags or using sprout methods with sensible fallbacks in case of errors. There are many patterns you can use to make refactoring safer and more reliable. The most important thing is end-to-end test coverage, and that is often missing in the dark corners of the map that your developers are afraid to change. Still, this needs to be a change from the top down; we can't settle for "it needs to be rewritten and all hope is lost " as an answer, that can't be acceptable. There needs to be a concerted effort to demonstrate that a path can be planned, managed, and executed.
Another, more subtle indicator is how developers talk about these areas of code. The minefields that are filled with unknown unknowns in the dark corners of the legacy code swamp, which will take 10 points to figure out. Usually, the reluctance to work in an area is where the fear starts. The mountain of impossible obstacles that developers don't want to deal with. It's essential to acknowledge this here and begin countering the growing mindset of fear and the perception of impossible changes. Do exercises with developers like talking them through the steps of what needs to happen, ask questions about what the task is, and not in the do you understand the feature way. Try asking things like "I am a database wrapper that needs to process a query, how do I accomplish that?" Lead them through what they are doing in a hybrid of whiteboarding and pseudo-coding to get them thinking and seeing that this isn't impossible. Create a plan with them and ensure they execute it. When the unexpected arises, reevaluate with them and adjust the plan, but keep moving forward.
When this mindset goes unchecked long enough, it can slow work on tech debt, refactoring, and improvements to a standstill. I've seen it end with months of meetings about refactoring code that went nowhere, only to result in more meetings. In the end, nothing got refactored, the code stayed the same, and developers realized it was ok to be afraid, even to try and tackle an area. Those areas of code decay more, and the fog of war increases around them as time goes on, compounding the fear of making the change. One of my favorite quotes on software development is from Tanya Reilly:
When you join a new company, most of the big picture is completely unknown to you. A big part of starting a new job is building context, learning how your new organization works, and uncovering everyone's goals. Think of it like the fog of war in a video game, where you can't see what awaits you in the parts of the map you haven't explored yet. As you scout around, you clear the fog and get a better picture of the terrain, learning what's surrounding you and whether there are wolves coming to bother your villagers. You can set out to uncover the obscured parts in all three of the maps and find ways to make that information easy for other people to understand. For instance: Your locator map can help you make sure the teams you work with really understand their purpose in the organization, who their customers are, and how their work affects other people. Your topographical map can help highlight the friction and gaps between teams and open up the paths of communication. Your treasure map can help you make sure everyone knows exactly what they're trying to achieve and why. You'll be able to clear some parts of the map through everyday learning, but you'll need to deliberately set out to clear other parts. A core theme of this chapter is how important it is to know things: to have continual context and a sense of what's going on. Knowing things takes both skill and opportunity, and you might need to work at it for a while before you start seeing what you're not seeing.1
Although Reilly's quote is more focused on joining a new company as a Staff Engineer, the idea itself is relevant to understanding the fear of executing. The unknowns, the minefields, the lack of coverage, all of it is fog of war that allows that fear to creep in. The only way to get rid of that is to explore, lead, and discover the map.
Easy wins and big refactors
Often, this fear causes developers to overlook the easy wins —the things they can change in controlled ways that make an impact. These are good places to start to build confidence and buy credit with leadership or clients who may be growing frustrated. Look for things like:
- Database queries running in loops: can they be pulled out and run beforehand in one large query?
- Inefficient queries: legacy code often has poorly adapted queries that have changed with time. Do they need changes or better index coverage?
- Caching: would caching data help reduce latency or increase performance?
These are relatively small, focused changes that can have a compounding impact on legacy code. The best part of these types of changes is that they show developers you can make a plan, execute it, and get real results. They are small, quick wins that buy social credit and may only be a handful of points or hours of work in the long run.
To tackle larger changes, you will want to be more deliberate and use patterns for refactoring that have been well-documented and discussed. There are clear paths and strategies, some of which we wrote about in Refactoring Legacy Code. The key point is leading the team and showing them it is possible. Utilize proven methods, create a plan, and execute it effectively. In the end, how you approach the change will most likely change, but you can limit the scope of the change and the likelihood of massive deviations from the plan by planning and preparing beforehand. You have to see it through; that is the most critical part. If you end up in a meeting inception or a half-completed refactor, it reinforces the fear of executing. You'll hear the "the last time we tried this it blew up" rhetoric. Make a plan, execute the plan, adapt, and complete the change.
Conclusion
The fear of making changes in legacy code can slow down teams, cost clients, and increase the time to live for product improvements. As leaders, we should be vigilant for the early signs of this mindset taking hold and intervene as soon as possible. We need to lead from the front and show teams that complicated changes in legacy code can be successfully completed and that even if you execute on a plan and it falls apart, you haven't failed. You adapt, evolve, and overcome.
References
- The Staff Engineers Path - Tanya Reilly
Top comments (0)