Short article for a Kotlin trick that I found usef...
# feed
m
Short article for a Kotlin trick that I found useful: https://proandroiddev.com/interface-singleton-in-kotlin-4c14d862cd67
👍 11
c
As a general rule, singletons go against the principle of dependency injection,
I don’t understand that. Singletons are perfect candidates for DI. What does it mean that they “go against the principle of DI”?
m
I see your point, my phrasing is indeed wrong. I meant that accessing singleton instances directly went against dependency injection. But of course you’re right, singletons themselves aren’t an issue at all.
c
Mmh... I still don't follow. Why is it against DI to access singletons? What does that mean?
m
If I call a method on a singleton instance and obtain it directly, typically using
SingletonClass.getInstance()
, then I have a dependency on that singleton class, but I’m not injecting it
c
If you inject a Singleton, you also have a dependency on it.
👏 2
m
Not if a singleton implements a interface
➕ 2
m
If your class is being injected with the singleton instance, it doesn’t know that it’s a singleton, and depend on that fact.
m
I think the misunderstanding here is between Singleton (pattern, capital ‘S’) and singleton as in creation mode. Singleton is harmful for DI like Martin specified, when you construct or obtain the instance inside your class. A singleton object , existing only in one instance, isn’t harmful at all when passed as a dependency of the class through a constructor. Notice that singleton =/=> Singleton, that is having only one instance doesn’t imply that class has to follow the Singleton pattern. (in fact that’s what Spring does to your `@Component`s: take care of creating one and only one instance for you)
c
I still don't see why "Singleton is harmful for DI"
DI is what makes singletons not just harmless but useful and testable
s
@Martin Devillers advocates for inversion of control, where the caller/user provides all dependencies (push) instead of the callee figuring out where the dependencies are (pull). The fact that the dependency is a singleton or not is, when using inversion of control, not important to the callee.
➕ 3
m
so,
Singleton.getInstance()
- bad, breaks DI singleton as constructor param - good, testable
c
Yes, that's more like it. There's nothing intrinsically wrong about singletons in general, they are not just very useful, they are often unavoidable. What's wrong is certain implementations of singletons, such as
static
.
m
yes absolutely, but only when
Singleton.getInstance()
is called inside the class — same applies for a regular object instantiation: that penalizes IoC and testability
I suggest reading this, it’s very insightful: http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/
c
I know that article and fundamentally disagrees with parts of it :)
➕ 1
m
feel free
s
I think that the term ‘liars’ is not correct, a bit too harsh. But Singletons can be scattered around your codebase and you’d need knowledge of a class’ implementation to see which singletons/dependencies are needed. In general, using inversion of control and providing the dependencies explicitly in the constructor of a class or in a method of a class, makes clear what is needed and what is not needed. If inversion of control is well done, the signature of a class-constructor and the signatures of its methods are a complete description of what the class needs (for dependencies) to function well (no need to look at its implementation and hunt for dependencies providers)
🤝 1
👏 1
Also, the fact that a dependency for a class is a singleton or not should not be important to a class’ implementation. That decision should be up to the ‘outer-edge’ of your app, which will provide the appropriate dependencies based on its context/environment and it will decide which ones will be singletons or not.
d
IMHO, the obvious answer to "XXX breaks DI" is not "Dont Use XXX" but rather "Dont use DI" -- A non-scientific off-the-cuff assessment of comparing "Things that don't work well with DI" vs "Things that work well except with DI" leads me to the generalization that its DI thats the problem. In fact one reason for my personal conversion to Kotlin was that built into kotlin are features that address, or enable coding such such that DI isn't (or isn't as much) needed in the first place. So when I read a comment/blog/article about "XXX is BAD because it breaks DI" -- my take is thats one more reason Im glad to be using Kotlin for as many projects as I can -- there are so fewer compelling reasons to have to adopt either DI or the frameworks that require it as a dependency. Frameworks such as Spring which arose over the years as a way to manage the complexities of writing serious code in Java -- Remove the original problems and the resulting solution is no longer that compelling.