Why Singletons Are Bad?

Singleton is a widely known design pattern that generally allows you to create a global object that can be accessed from anywhere in your application and it will assure that this object will be initiated only once per lifetime of your application/code.

Before digging into why such a pattern could cause lots of problems in your codebase let us first try and implement it and imagine a use case where it would fit.

How To Implement?

From its name a singleton is a single entity or object that would be created only once, how could we achieve something like that? how could we for example declare an object of type class A for example and disallow any other creations of instances of the same type?

Let us look at the code and discuss it further:

class Singleton {
    private static instance: Singleton;
    private constructor() {

    }
    static getInstance() {
        if (!Singleton.instance) {
            Singleton.instance = new Singleton();
        }
        return Singleton.instance;
    }

    // some other logic
}

let a = Singleton.getInstance();
let b = Singleton.getInstance();

// both a and b points at the same instance

What can we deduce here is that we have made our constructor a private function, meaning if we simply tried let c = new Singleton() an error would occur as we can not access private methods in our class.

Another thing we did is we created a private static member of our Singleton type and then we create a public method that initiates our private static instance if it is not initiated and simply returns it. By doing that we assure that whenever we call the getInstance function we will have the same instance in our codebase.

A Use Case

Where could we use something like this in our application? someone could purpose that if for example, we have an application that requires some kind of authentication we could make our User object treated as a singleton so our whole application code could access it and manipulate it if needed.

class SingletonUser {
    data: any;
    private static instance: SingletonUser;
    private constructor() {}
    //...singleton logic


    changeData(data) {
        this.data = data;
    }

    // some other logic
}

By this, we could for example change the user's data when he logs in or logs out and so on.

Why Singletons Are Bad?

If we think about it for a second we now have our user's object globally initiated and any method or class in our codebase have an access to such object and could easily manipulate it, this could result in creating bugs and issues that are hard to maintain and find because you will have to figure out which part of your codebase changes or interacts with your singletons.

Another reason is that singletons increase coupling and decrease cohesion because if you want to change the behavior or extend its functionality you will have to change the class of the singleton.

The problem here arises when you have lots of areas that depend on your singleton and depend on its functionality, if somehow you needed to change the functionality of your singleton you will now be at risk that all of the areas that depended on it might crash or act in incorrect behavior.

Singletons also could cause you a nightmare when you are writing unit tests for your application. The idea behind unit testing is being able to test your functions/classes/modules without depending on other dependencies, when using singletons we will then have to initiate the correct shape for our singletons so that our methods/classes/modules would act correctly when under testing.

Singletons also violate the Single Responsibility Principle : In addition to their main responsibility, they are also responsible for implementing their own lifecycle.

When a class has multiple responsibilities "Like Singletons" it makes it harder to maintain and test, now you will need to test not only one responsibility but 2 and usually singletons carry lots of logic inside of them because they are being consumed through your whole application.

There are a lot of SOLID principles that Singletons violate like the Dependency Inversion Principle and Open / Closed Principle

Conclusion

Generally, I believe that Singletons have their own use cases but I would not recommend using them as Singletons are very much like the good things in life, they're not bad if used in moderation, and through my coding career that never happened :D