DEV Community

Generic Singletons

Andreas Jakof on October 07, 2019

When design patterns are concerned, the most commonly used might be the factory and the singleton. As a quick disclaimer: This works with C#, but I...
Collapse
 
thebuzzsaw profile image
Kelly Brown

Good.

Now never use singletons in your code. :D

Collapse
 
andreasjakof profile image
Andreas Jakof

Now I am curious... Why?

Collapse
 
thebuzzsaw profile image
Kelly Brown

I can write many paragraphs in response, but I want to start small. The short version is that singletons offer incredibly low value and bring a fair number of problems along for the ride. I actively avoid singletons in all my code now.

Thread Thread
 
andreasjakof profile image
Andreas Jakof

I usually do too, but in my case, creating a new instance takes a considerable amount of time. Having it instantiated once and then just using it, will have quite an impact on performance, considering about 120000 items, that are to be used with it in a go. Adding 1/2 second each time sums up to about 17 hours, just for creating new instances... not even considering memory fragmentation, which causes other issues.

So in my case, it is a tradeoff beween two evils, chosing the lesser one.
And again, there is no general right or wrong.

I know, that one can achieve almost the same result, with a slightly different design without Singletons, but then again, I know that, others won't necessarily.

And to be honest: having a good documentation is not always enough to keep others from using it wrong, so creating it in a way, other just cannot use it wrongly, is again the lesser evil.

Thread Thread
 
thebuzzsaw profile image
Kelly Brown • Edited

The situation you are describing does not call for a singleton. This is a mistake I made early on in my career. It's completely normal and healthy to have situations where you need to reuse one instance instead of creating new ones. A singleton is so much more than that, though. A singleton is a heavy-handed approach that introduces so many new restrictions on your application.

If you need one instance... then make and share one instance! That's it! Sharing one instance does not mean you need to make it global, statically initialized, and (henceforth) completely invisible as a dependency in method signatures. You don't need to choose evil at all! Just code pragmatically.

I can't remember where I read it, but I really liked what someone said: you should only use a singleton for a subsystem where there literally cannot be more than one instance and/or allowing the user to instantiate that class would lead to danger/instability. There are very few things in programming that fall under this category.

When design patterns are concerned, the most commonly used might be the factory and the singleton.

Goodness, I hope not. How many singletons are you seeing in your code bases? :(

Thread Thread
 
andreasjakof profile image
Andreas Jakof

The situation you are describing does not call for a singleton.

I know, but I really want to enforce the usage of just ONE instance of a type. And experience told me, that I need to enforce it, otherwise it won't be used like that.

If you need one instance... then make and share one instance! That's it! ... Just code pragmatically.

I'd prefer that approach, too, but then again... I saw, how others in the team used a class, I designed to load encrypted credentials... and that told me a lot about, what I need to enforce and how they are going to use it. It was as if the two pages extensive step-by-step examples were not there at all. And I made it as simple as var creds = MyCreds.Load(Certificate, encryptedData);

When design patterns are concerned, the most commonly used might be the factory and the singleton.

Goodness, I hope not. How many singletons are you seeing in your code bases? :(

Okay, maybe not the most commonly used, but the most well known.
Actually, there currently are 10 Singletons all of the same "kind", encapsulating access to an Azure AD Group each. I like to have a name for something instead of a GUID. User.HasService<Android>() is better readable than User.HasService(someGuid).

Actually, the Singletons I described in my initial blog post, weren't singletons at first, but became such only afterwards, when I saw, that even I not always followed my own intention of using just ONE instance of it. So I made it, that I had to and the compiler just won't let me do it otherwise. I like the compiler, he is my friend and if I am doing it right, he can tell me, whether I did something wrong or not.