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...
For further actions, you may consider blocking this person and/or reporting abuse
Good.
Now never use singletons in your code. :D
Since I read the "Clean Code", I understand you better now.
Well, DI has it's own flaws (some errors only occure during runtime, which would have been compile time errors), but I am getting used to it and you could check for these errors in a separate unit test.
I still don't mind singletones, but you should not use static classes or objects you only get from a static class. Use Factories instead or DI, which handles the singleton problem for you.
I still like generics, though...
Currently, the only true singletons I put up with are classes that are completely immutable with no configuration options or side effects. Even then, I'm hesitant to lock them down, but sometimes I am OK with hiding the constructor and exposing an
Instance
simply because creating new ones literally just wastes memory.Now I am curious... Why?
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.
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.
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.
Goodness, I hope not. How many singletons are you seeing in your code bases? :(
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.
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);
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 thanUser.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.
I totally understand the desire to steer developers into the "pit of success". This is just an area I feel is more appropriate for something like a Roslyn Analyzer or at the very least code reviews. (And again, your blog post was good. I just had to be first to share the dissenting voice.)
The common issues you'll hear come around testability. Having to 'reset' the singleton is non-trivial at times, and it basically means tests cannot run in parallel. Plus, I don't know about you, but I've had times where I later realized I do need more than one instance. This is where I feel it's important to always use dependency injection so that you are insulated from such decisions. When a method can freely grab
SomeSingleton<SomeWidget>.Instance
, that dependency is less visible. You'd have to know to "Find All References" on the singleton itself.I love the discourse. :)
I like discussing such things as well. If you look at my post „Brilliant but also horribly wrong“, I had like to learn from others, who know more than me.
And I usually don‘t use Singletons much. But in this case, I think, it is fine. The Singletons are usable in multiple threads and they mostly let me compare the membership of a user in an AAD-Group. And they NEVER change. If they would, they would no longer be of the same kind, not only the same instance.
And I know about the issues with testability as well... this is where I have a considerable lack of experience, even though I am already in the business for about 10 years now.
That’s why I am currently looking into DI in .Net Core. To make my code more testable. But then again, the code is mostly glue between systems and I am struggling with the basic approach, hie I will test it. Currently there are some basic unit tests, but lots of untested code, because the CD/CI server does not have access to all the credentials for the different systems I am glueing together. 😳
It's probably better you inject these instances instead of creating a static class to access a singleton objects.
I don't like "never." What would you use in a client-side Blazor application for keeping up with app state if not a singleton service? Which then, by the way, still has to be injected.
I'm actually super happy you brought this up. You're referring to
services.AddSingleton<T>
, yes? I argue that this method is misnamed. I think it should be renamed toAddShared
or something like that. When you inject an object in this manner, it's merely instructing the framework to reuse a single instance. It doesn't suddenly bestow all the qualities of a singleton upon that class. I can still voluntarily create another instance somewhere. The constructor is not locked down per the singleton design pattern.(Oh you said client-side Blazor. I've not made one of those. Regardless, you don't need a true singleton.)