7 ms·
It often is not enough. Singletons frequently need to be provided to things (a connection pool, etc.).
by almostdeadguy 1y ago
It often is not enough. Singletons frequently need to be provided to things (a connection pool, etc.).
- lgas 1y agoMaybe I'm misunderstanding what you're saying but a connection pool seems like almost a canonical example of something that shouldn't be a singleton. You might want connection pools that connect to different databases or to the same database in read-only vs. read/write mode, etc.
- stickfigure 1y agoThen these different pools can be separate singletons. You still don't want to instantiate multiple identical pools. You can use the type system to your advantage. Cut a new type and inject a ReadOnlyDataSource or a SecondDatabaseDataSource or whatnot. Figure out what should only have one instance in your app, wrap a type around it, put it in the singleton scope, and inject that.
- MrJohz 1y agoI think the point is that you can already do all of that with hand-wired dependency injection. I wrote about an example of that a couple of years ago here: https://jonathan-frere.com/posts/how-i-do-dependency-injection-with-closures/ https://jonathan-frere.com/posts/how-i-do-dependency-injecti... This has the advantage that you don't need an extra framework/dependency to handle DI, and it means that dependencies are usually much easier to trace (because you've literally got all the code in your project, no metaprogramming or reflection required). There are limits to this style of DI, but in practice I've not reached those limits yet, and I suspect if you do reach those limits, your DI is just too complicated in the first place.
- almostdeadguy 1y agoI think most people using these frameworks are aware that DI is just automated instantiation. If your program has a limited number of ways of composing instantiations, it may not be useful to you. The amount of ceremony reduced may not be worth the overhead.
- stickfigure 1y agoThis conversation repeats itself ad infinitum around DI, ORMs, caching, security, logging, validation, etc, etc, etc... no, you don't need a framework. You can write your own. There are three common outcomes of this: * Your framework gets so complicated that someone rips it out and replaces it with one of the standard frameworks. * Your framework gets so complicated that it turns into a popular project in its own right. * Your app dies and your custom framework dies with it. The third one is the most common.
- MrJohz 1y agoI'm not suggesting a custom framework here, I'm suggesting no DI framework at all. No reflection, no extra configuration, no nothing, just composing classes manually using the normal structure of the language. At some point this stops working, I agree — this isn't necessarily an infinitely scalable solution. At that point, switching to (1) is usually a fairly simple endeavour because you're already using DI, you just need to wire it together differently. But I've been surprised at the number of cases where just going without a framework altogether has been completely sufficient, and has been successful for far longer than I'd have originally expected.
- almostdeadguy 1y agoI meant "singleton" in the sense of a single value for a type shared by anything that requires one, i.e. a Guice singleton ( https://github.com/google/guice/wiki/scopes#singleton https://github.com/google/guice/wiki/scopes#singleton ) not a value in global scope. Or maybe a single value by type with an annotation, the salient point is that there are values in a program that must be shared for correctness. Parameterless constructors prohibit you from using these (unless you have global variables).
- hayst4ck 1y agoIf you construct an object once, then what is the difference between that and a singleton? The answer is scope. Singletons exist explicitly for the purpose of violating scoping for the convenience of not having to thread that dependency through constructors. https://testing.googleblog.com/2008/08/root-cause-of-singletons.html https://testing.googleblog.com/2008/08/root-cause-of-singlet...
- almostdeadguy 1y agoCalling these "singletons" maybe created confusion here, I'm more talking about singleton in the sense of a value that is created once and shared (i.e. injecting a value as a "Singleton" via something like Guice). I'm not arguing that you need to have values in global scope, I'm arguing that parameterless constructors prevent you from using shared values (actually _unless_ you have singletons in global scope).