Imagine a parallel universe where all is the same, expect that software products don’t actually require any code to be written in order for them to exist. You dream up a product, say some magic words, and puff - it exists. A product managers dream, yet a software developers worst nightmare.
Granted, this is a totally absurd tweak to the laws of physics, but let me ask you a question. In this fictitious universe, you have the option for your product to just exist, or you can apply the traditional method of actually building it with code. Which method would you choose? Of course, anyone with a modicum of business acumen would choose the former. Now let’s bring this back to our reality, where we merely have a choice in the quality, and quantity of code it takes to build a product. There are numerous development practices that can produce more clean, succinct code with identical output to that of a more verbose implementation. But why put in the extra effort? Because code is risk. It’s somewhat of a paradox, but your code is a risk to the success of your product, while actually being your product.
Ask any battle hardened software developer about their past jobs, many will recount a story of the time they joined Dot Com Unicorn, Inc., only to find their product teams were more akin to firefighters than calm, methodical engineers. My personal anecdote is from 2013, when I was a Site Reliability Engineer (SRE) at LivingSocial. I was discussing with then CTO, Aaron Batalion, about the state of our codebase, and the effects of rapid growth. As an SRE, I was battling my fair share of fires, and many other teams were working hard to detangle our monolithic app into more distinct services. To me it felt we were paying a very high price for the technical debt the company had taken on. Perhaps a little more planning along the way could have left us in a better state, without affecting growth. Aaron’s position was that neither of us may have a job if the company hadn’t grown as quickly as it did. While he may have been right, it was clear to me that the current state of our codebase was a risk to our ability to maintain and grow our market position. We were simply not able to deliver on many requests from management because we were too busy refactoring critical subsystems.
When asked why we write unit tests for our code, many developers will reply that it can help reduce bugs. Bugs are unwanted because customers dislike them, therefore bugs are a risk to the success of a product. This may seem like a redundantly obvious statement, but risk is an important distinction.
When we start seeing code as risk, we take on a clearer perspective about the impact our decisions can have on the success of a product, rather than simply the quality of its code. Ask yourself: Is it worth the risk of using a “hack”, instead of spending a little more time to find a correct solution? Is it worth the risk not writing a unit test for a new feature? Is it worth the risk not waiting for a team member to review a change? In isolated situations it may make sense to take on the risk, but in general these kinds of risk should be avoided. Failure to be cognizant of risk on a daily basis can compound over time into a situation such as the one I experienced at LivingSocial.
Removal of unused code is one method of reducing risk. This article perfectly exemplifies the risk that unused code can pose. The New York Stock Exchange lost hundreds of millions of dollars by reusing a feature flag that awakened code that had not been used in years. The resulting downtime time cost them effectively $10 million per minute.
Many development practices designed to mitigate risk by producing more clean, succinct code can be very resource intensive, and sometimes even subjective. Removing unused code is comparatively straightforward, and requires very little effort. Regardless of the programming language you use, I strongly believe removing unused code should be a fundamental practice of professional software development.
For those using Swift, you may want to consider Periphery for identifying unused code in your projects.