We all have reasons for holding onto the past, like that Transformers lunchbox that I couldn’t handle throwing away. I loved it, but the truth is I was never going to use it again. But in the realm of professional software engineering, holding onto anything that isn’t being utilized can wreak havoc on a codebase through unintentional bugs and clutter that hurts maintainability and team moral. This unused code is called “dead code.” But how do we know when code is dead? And worse yet, how do we convince ourselves that it’s finally okay to let go of that lunchbox you’re not using anymore? The following tips will help you to get rid of the hoarding problem.
But first, what is “dead code?” Dead code that is any code that is no longer in use by a customer or a “if branch” that can’t possibly be hit. And since there is a proven correlation between the number of lines of code to the number of bugs (1) , it’s best to slim your code down whenever possible. The best way to find it is to go looking for it every time you add to the code. But maybe you’re too afraid to delete the code? It’s an understandable fear, so here are a few tips to get you and your team more comfortable:
Before we talk about the many technical solutions that can make large refactoring possible, let’s talk a little bit about the emotional challenges to deleting code. While I can just tell you that letting go can and will make you happier… it’s not always so easy to believe it. The past is already gone, so why are we letting it bother us? Sometimes this is really, really hard to accept. For instance, when I was starting this blog, I wanted to set up an office in my basement so I could have a quiet, productive space to focus on producing articles… unfortunately I couldn’t even walk in the basement because I had approximately 1 billion moving boxes from when we bought the house. Every time I opened a box, my brain said, “Oh, you’re totally going to need this later” which was almost always untrue. Did I still need a box of t-shirts from my high school glory days? How about that collection of harmonicas that I found too challenging to ever learn? No, these were all relics of the past and they were LITERALLY preventing me from enjoying my current goals.
There are some people who might say “Wait, I thought that as programmers we were supposed to add value by adding code?” No, sometimes the best code is the code that you don’t have to write. Or as Bill Gates is credited with saying: “Measuring programming progress by lines of code is like measuring aircraft building progress by weight.” So take that advice and enjoy the moments when you get to make your aircraft much less heavy. This is the kind of pull request you get to have fun submitting:
But sure, I hear you. That sounds scary to cut out massive parts of the code. So our next tip involves deleting tiny bits as you go.
If you have a garden, the best way to keep the good plants healthy is to walk outside every day and pull a few weeds. It’s certainly much easier than waiting till your garden is overgrown. It’s the same with the story above about my basement– If I had simply unpacked one box per day, then I would have achieved my goal of a clean working environment much, much sooner. This is exactly the kind of proactive atmosphere you should be creating on your team. Some of your teammates might feel down or discouraged. Show your teammates that it’s 100% possible to weed the dead code out of your old, unmaintainable codebase.
Even if you peers become confident in your hunting skills, it doesn’t mean that they have confidence in their own abilities. You can raise their confidence and understanding by taking time each week to share domain knowledge amongst the entire team so that each developer can think about the business domain while they’re in the code. Since your peers will now understand the effect of their changes, they can understand more viscerally what effect the change will have on the users. This will make a huge impact. But sometimes domain knowledge isn’t enough to prevent developers from being scared of making big sweeping changes. That’s when you’ll need better metrics, tooling, and testing.
- Test automation: Continue to add enough automated unit tests and API tests so that you can confidently delete code and ensure that the major functionalities still work. While unit testing is undoubtably important, it also pays to have some tests that are higher than unit tests. You can have white box tests that automatically verify the entire functionality of a feature. If those tests are green after you delete the code that you think is no longer in use… then you should be happy knowing that you just made the lives of future developers much easier. And now that there are less chances for bugs, you’ve improved the lives of the users too.
- Let the compiler do the work for you: While automated tests like Cypress.io might get you the highest value in highly complex areas like the user interface (UI), there are areas such as the backend and middle-layer that would undoubtably benefit from static typing. If you have static typing like C#, Java, or (my favorite) TypeScript, then you can let the compiler tell you which parts of the code can’t be hit. It can basically find the dead code for you. One way to accomplish this is to remove a feature flag (i.e. a variable that turns on or off a feature for a particular subset of users) from the code and then you’ll know which part can be deleted… because it’s the part with tons of red squiggly lines telling you that you can’t compile.
- Trust the metrics: Put in analytic hooks like Google Analytics or New Relic to see how frequently each particular feature is being used. That way when you have to delete the entire feature you can see if too many customers will mind when it’s gone. Or if you’re nervous about touching a piece of code that is confusing, you might feel more comfortable doing the invasive surgery if you know that the code is part of a lesser-used feature.
- Have a narrow focus: If you don’t have analytics on usage rates, you can make a judgement call to delete code that is “questionably in-use” because, as Steve Jobs would often say, “focus is about saying no” (2). Think of your software as a living thing, like a tree. If a tree has a limb or two that start to wither or way, isn’t it healthy to cut off those limbs? Then the tree will be free to send its vital nutrients to the branches that are healthy and flowering. Do the same with your code– If a part of your code isn’t in use anymore, why look at those lines anymore? Do the same with your time: If a software product isn’t bringing in the revenue it needs to be bringing in, or it’s not making the social impact that it should be… then stop maintaining it.Ultimately these tips will allow you to focus more on what your users need in this present moment. And if you’re being a mindful person, you’ll remove the things that are impeding your ability to be helpful.
Remember, it’s much easier to pull weeds from your garden when there are only a couple tiny offenders than it is to spend hours weeding when your garden is overgrown.
That being said: I have a bunch of weeds in my yard right now! Hey, no one is perfect, and that’s okay!