You must have heard that static is considered bad or even evil, a complete disaster for your software architecture. But why? Surely there must be a trade-off between advantages and disadvantages, so let’s have a look.
Originally published at Meduim
As a young junior software engineer, I was taught that static is a bad way of coding and that one should always avoid using it no matter what. Back then I didn’t understand why. I thought that static could be useful and more efficient. Over the years I learned what the disadvantages are, and I completely agree that one should always avoid using static.
In this article, I am using Typescript for references and examples but the same idea can be applied for any other programming languages that support static.
Let’s break down the different use cases of static.
This is the most common use of static that I keep seeing. Here’s an example:
What is wrong with it?
Static methods inside a class are usually a good indication of a method that doesn’t belong to this particular class. It doesn’t use the state of the class or other non-static members that the class has, and therefore, they break the Single Responsibility Principle.
Static methods are not polymorphic. The definition of polymorphism is the use of a single interface for entities of different types. So, by definition, static is not polymorphic. The Static method belongs to the class and not to the class instance, therefore you can’t achieve polymorphism with static.
Static methods can’t be used for abstraction and inheritance. You can’t declare a static method in an interface or static abstract method in an abstract class. A static method cannot access non-static class level members, not its own, nor its base class. (Even though in TypeScript and Java, a derived class inherits its base class static members, it still doesn’t fit well as mentioned).
Static methods are bad for testability. Since static methods belong to the class and not a particular instance, mocking them becomes difficult and dangerous. Overriding a static method is not that simple for some languages. Even if you succeed, it will affect other tests that rely on the original implementation and lead to mutations that you didn’t expect to be.
Static methods aren’t associated with any object. It is even wrong to call them methods. They are functions. What’s the difference between a method and a function?
For the above reasons, it is easy to notice that static functions break the OOP concepts.
Given all these downsides, surely there must be some advantages, some trade-off against all these disadvantages? Well, not really.
One of the most common arguments is, why demand that consumers of our class create an instance for invoking this single method, while having no use for the instance afterwards? Creating an instance of a class is a very very cheap operation in most languages, so speed is not an issue. Adding an extra line of code to the consumer is a low cost for laying the foundation of a much more maintainable solution in the future. And finally, if you want to avoid creating instances, simply create a singleton wrapper of your class that allows for easy reuse.
In C#, for example, you even have the feature of a static class. Let’s look at an example:
A static class can’t contain non-static members.
A static class is basically the same as a non-static class, but there is one difference: a static class cannot be instantiated.
A static class cannot be instantiated. All members of a static class are static and are accessed via the class name directly, without creating an instance of the class.
As for today in TypeScript v3.9, we still don’t have this feature. We can achieve a similar behavior, for example, using a private constructor. In this article, I will refer to classes with only static members as static classes.
There isn’t much of a difference between a static and non-static class regarding the use of them. All the reasons mentioned above in “Classes with static and non-static methods” except the Single Responsibility Principle still apply here.
There are some arguments in favor of static classes when it makes sense. Here are some examples:
I don’t find these arguments very convincing. Those use cases can be easily done using singletons or constant variables, which makes it easier for future maintenance without getting the cons of static.
Besides all the cons that we mentioned above regarding static methods, static fields have more disadvantages and are considered by many as much worse.
Static variables represent a global state. Without proper handling, a global state can be a nightmare. The modification of the state can be from everywhere, leading to unexpected mutations across your software and tests.
Memory leaks. The Garbage Collector is the memory manager of your app. Objects that are no longer referenced by any variable or collection are garbage collected. Static members are referenced by their classes and not by a particular object instance, and since the class itself won’t be Garbage Collected even once you’re done using it, the memory of a static variable that referenced by this class cannot be garbage collected. A static variable will persist for the lifetime of the app.
There are different uses for static and all of them have some serious disadvantages. In this article, I focused on Static Methods, Static Classes, and Static Variables.
The disadvantages I mentioned are:
Single responsibility principle
There are more use cases and disadvantages for static and they are different from one programming language to another. In this article, I tried to bring the most common use cases I keep seeing.
For the use cases above I didn’t find a good enough reason to use static except for laziness :) or maybe a quick solution for a POC. Although there may be some different use cases for the static keyword, e.g., extension methods in C# and static nested class in Java.
In my opinion, one should always avoid using static.
I hope you enjoyed the read.
Extra articles and resources to look at: