Don’t write reusable code

Scott Boring
4 min readJul 7, 2022

--

Reusable code is often a goal for developers and leaders alike. I’ve been told many times by directors and VP’s that we have a “reusability problem” and we need to have more reusable code. The DRY (Don’t repeat yourself) principal is often referenced to support the behavior of writing reusable code. In my experience, some of the most harmful and difficult to maintain code was written with a code reusability mindset.

I don’t write reusable code and I actively discourage other developers from doing so. That doesn’t mean that my code doesn’t achieve reuse; in fact, my code often achieves significant reuse. This article is about avoiding a common coding pitfall and ironically; it is also a guide for how to achieve code reuse by not putting forth any effort to write reusable code.

Reuse is not a problem; it’s a solution. I have never been able to define a “reusability problem”, or extract details about it from those that believe it exists. I believe that when people say they have a “reusability problem”, they really have a low productivity problem, or a high maintenance problem. Ironically, attempting to force reusability into code will likely make both of those problems worse. It’s entirely possible that the low productivity and high maintenance problems are caused by forced reusability of code.

I believe a reason that so many developers and leaders advocate for reuse is because they have seen successful code bases that contain a significant amount of reusable code. From this, a false assumption is made that the code was written to be reusable. But that is probably not what happened. The reusable code that is produced is a side effect of writing concise code that solves a well defined and specific problem.

Code should never be written to be reusable. It’s fundamentally a bad idea. The fundamental problem with writing reusable code is that there is no pattern or definition for how to do that. Reuse is an outcome, not a design pattern. Code that is written to be reusable will typically be written with assumptions about the future and/or it will be written with configurations so that its behavior can change to solve multiple use cases. Both of these approaches are anti patterns.

Making assumptions about a future you can’t control rarely works. Even if you have experience with the problem and well thought out ideas about future; you can’t control the external influences that will shape the future. Companies constantly reorg with teams splitting up or merging; as well as new leadership, often highly opinionated leadership. New technologies enter the scene, and companies adapt their business goals based on the ever changing world around them. If you look at a code base that has been in use for more than a year at company; you are likely to find dead code and configurations that were intended for future usage that never came to fruition.

Writing code with configurations is often the most dangerous and harmful code that can be written. It often achieves some level of reuse through force; while also lowering productivity and increasing maintenance. Configurable code is error prone because it introduces multiple points of failure and can be difficult to understand which configurations are valid. Configurable code is difficult to maintain as each use case must be considered. This is particularly harmful as developers can often be creative in their usage of code and often misuse code in unintended ways. The likely outcome of this type of code reuse is the classic “Spaghetti code” in which an improvement or bug fix results in one or more new bugs being introduced. This often results in code bases in which developers and leaders are scared to make changes.

Code should be written to solve a small and specific problem. The smaller and more specific the problem, the better. This will result in highly maintainable code that can evolve as the problem it solves evolves. This type of code is easy to understand and is difficult for developers to misuse in creative and unintended ways.

Code reuse occurs when a problem reoccurs. When a problem reoccurs, code can be reused to solve it. If the problem doesn’t reoccur, the code is still needed to solve that problem. Thus, it is unnecessary to put forth any effort in determining if a problem will reoccur. Developers and leaders only need to focus on understanding the problem and writing simple and concise code to solve that specific problem. Code reuse will happen naturally as problems reoccur.

By not writing reusable code; you will be surprised at how much code reuse you achieve.

Case study: Spring Framework

https://github.com/spring-projects/spring-framework

Here are the top ten most reused classes in the Spring Framework code base as determined by import statements.

1,279 Assert.java
491 StringUtils.java
403 Log.java
365 LogFactory.java
289 ObjectUtils.java
299 ClassUtils.java
252 HttpHeaders.java
222 CollectionUtils.java
204 MethodParameter.java
197 MediaType.java

Each of these classes solve a small and specific problem. Most constructors and methods are simple and only take one or fewer arguments. None of these classes make assumptions about the future of the Spring Framework. None of these classes are configurable so that they may solve multiple use cases. Each class solves a problem that reoccurs throughout the code base.

--

--