Why don’t most programming languages - including K...
# getting-started
e
Why don’t most programming languages - including Kotlin - provide native, automatic, implicit dependency injection feature in the language level itself? Instead we get this feature from frameworks like Spring, Koin and respective frameworks from other languages?
Instead, some of them bring smth like implementation inheritance even though of established principle "prefer composition over inheritance". I think if we had automatic dependency injection in the language itself, there is no need for implementation inheritance. This question is more for "off-topic" channel, but seems there is no one in this community
t
They do - it's called the constructor 🙂
Admittedly they're more explicit, but you could argue default parameters are the implicit part that you're looking for.
e
Edited for clarity: Relying solely on constructors - or even Kotlin’s context parameters - falls short of enabling automatic, implicit component wiring; both approaches still require manually propagating every dependency throughout the application. Intermediate components still serve as dependency passers (these components see these dependencies even though these components do not rely on them for performing their job, they just pass them down). What we get is application with components knowing too much - increased coupling. I believe that is why we have Spring DI and Koin DI and NestJS DI, .NET DI, ... to eliminate that
t
IME, this becoming painful is normally a sign of architectural problems. If you adopt a more functional core in your application, prioritising calculations over actions, you'll find the need to inject a dependency deep into your dependency graph rare. Most of your dependencies are then used in the surface layers of your application. Utilising default parameters can also be really helpful in this regard. You can configure lightweight builders (normally in the form of just functions that take default parameters in the most part) for both your production application and test application. Where it makes sense to do so, you can override a dependency.
👍 3
The book "Grokking Simplicity", or @dmcg's YouTube channel (

https://youtu.be/OG6wwCkljaA?si=1ZCgkMynUoU1qV25

) are both great resources for learning more about this topic.
👍 3
e
Yep, I wanted to ask for resources, thanks
t
No problem - do fire away with any questions you have.
👍 2
w
One problem is that DI frameworks are always opinionated, unless it's part of a language's vision, they generally don't enter into such opinionated territory. Interestingly some languages actually kind of have first class DI support. An example is Scala with their `given`/`using` (contextual abstraction). While the main intent is to use it for type classes, it also allows users to use it as a DI wiring tool as well. And tbh, using it made me realize how many features existing DI frameworks have that we don't need :) (Private statement btw, not related to JetBrains)
👍 2
💡 1
a
@Edgar Avuzi what is the alternative? Which language has built-in dependency injection?
e
@AndreyVanDenHaag Here is a minimalistic example of what I meant. Using Scala 3 `given`/`using` . Feels like automatic implicit wiring of singletons built in the language itself https://scastie.scala-lang.org/8N4xFJ1ZSouXQT9woBfrEA
a
I may misunderstand what is "dependency". My assumption is that a dependency does not have to be present during the compile time. A dependency must be injected during the runtime. Important - it is INJECTED to the code which was already prepared to be executed (compiled, tested, packaged). As far as I understand your example assumes that the compiler knows all the participants and it can link them.
👍 1
e
"Dependency" can mean different things depending on the context. e.g. this doc https://docs.scala-lang.org/scala3/reference/contextual/using-clauses.html treats "dependencies" as function parameters. It's just a matter of defining and agreeing on the term "dependency"
btw, interestingly they mention "_context parameter_" in that Scala doc. And in Kotlin we have "_context parameters_" feature, but it is a different thing
Yeah, runtime-based DI allows one to do more things
a
I am afraid in the context of dependency injection, function parameters are out of scope. (the first is about runtime, the second is about compile time)
w
It's not uncommon for DI frameworks to be fully static. Runtime injection resolution is just an additional feature that some of them might support. I wouldn't go as far as to say that it's the definition of a dependency in this context
a
I assume there is enough support in Kotlin for static DI (whatever it is)
w
"Static" in the context of languages effectively means "known at compile time". Eg. Kotlin is a statically typed language
a
@Wout Werkman which is the same as above: Kotlin as a statically compiled language has already enough support for the static dependency injection (even though I would rather avoid using the term DI in this context)
w
Hmm, interesting, I guess there is something I don't understand. In my opinion dependency wiring is the main responsibility of a DI framework. And from this perspective Kotlin does not have this out of the box (aside from context parameters with extremely limited applicability). What I mean with static DI frameworks is a framework like Dagger, which does all DI wiring at compile time. By all means, I'd love to get to know your view, but I also have no intention of hijacking Edhar's thread :)
e
No hijacking at all 😀 - hearing a lot of views helps me understand perspectives of others
❤️ 3
🔥 1
👍 1
t
my 2 cents to this discussion, in the case of Spring framework, you dont get Spring for DI, instead its the other way around, Spring needs DI in order to work. Using an opinionated framework like spring means mixing your own code with framework code. Having both of them in the application context makes this easy. Also, the idea of DI is quite simple, but handling all edge cases on where and how you get beans in the context and how to deal with duplicates etc when getting out might be something that is too opinionated for a language to have as a core feature. As in, Spring can do amazing things with DI, but its all runtime, another framework might have less features but its compile time. Neither are good or bad options depending on what your needs are. Im currently working on a talk that mentions a lot of DI 😄 so im curious about this topic and please tell me if my insights here are not correct.
Also, @Alejandro Serrano.Mena, this might be a good topic to share your views on as well 🙂
a
@Ties well, Spring started as DI. At least this is how I started to use it 20 years ago. Now it is a mega huge thing which has everything. But ApplicationContext is still its central component.
t
😛 Im too young (I dont get to say that that often anymore) to have used spring only for dependency injection. But that would mostly be my second point I think? My comment with spring was mostly that I think a lot of frameworks wont be able to do well without DI in order to do their framework things (as in, if it makes a rest endpoint, it need to know what custom code it needs to call etc)
t
I've been spoilt by http4k I guess - you have a toolkit of all the things you need, but without the weight of a framework magically constructing your application and everything it touches.
a
@Tim Mortimer if you do not need in a single application • RabbitMQ • Redis • PostgresQL • prometheus • AWS services • JWT tokens • test containers you may choose whatever you wish (there are plenty of possibilities)
By the way: how do you manage data in a relation DB?
t
You can use all those things with http4k no problem. When it's my choice, for relational DBs, I tend to lean on jOOQ.