I've been developing professionally for 6 years and nobody so far during my education or work have been able to explain dependency injection to me in a way that was understandable for me. This video is fire honestly
tbh dependency injection is just a fancy name for passing a value to a function and that value serves the purpose of abstracting the logic away from the function you are passing it into
@@esteban4983 so true. Also, callbacks and IoC are not necessary for reusability and low coupling. More over, IoC tend to harm humanly understandable control flow and cause bugs. From the video i see how to resolve basic SRP violation by delegating responsibility to another object. And that's done with "IoC". But you can just use dependency passed through constructor and that's it. And more, doing this way you move Billing dependency from the Checkout interface to concrete realization details. And that's a big deal for Checkout users. So, is there any point for following IoC? Or we can just use DI with straight control flow without brain inversion?
@@nilpunch2 by "just use DI" do you mean using the constructor? if so, yes I agree. More so, callbacks make it harder to test and at least in OOP I would use the constructor to pass dependencies and not to the method itself
been using nestjs more and more in my backends, and once i realized what the "magic" was under the hood - dependency injection - it was easy to see why it was needed, and i learned to implement it by myself using the good old expressjs in a couple pet projects. having it all setup for you is great, but learning how it actually works so you can confidently keep using such an opinionated framework knowing "the opinions" is way better.
I've been doing Rust for a bit more than 2 years now, and honestly every video I watch that introduces a programming technique makes me understand better just why Rust is so beloved. This one is no exception. So in Rust DI is most commonly done using traits (basically interfaces in OOP lingo). A great example of this is the `Write` trait: it allows a single generic piece of code to write into basically anything - a file, a network stream, a memory location, a deserialiser, and more. And since it's such a core part of the language, the entire library ecosystem is interoperable via traits like this.
DI is one of those things that really make me appreciate functional languages like Haskell. Since functions in Haskell are themselves first-class values, you can easily invert control or abstract some functionality by writing a function which accepts other function(s) as argument(s). So rather than designing and instantiating lots of interfaces and classes that all depend on and call back to each other in intricate ways, all I need to do is directly reference the callee function I want the caller to use. You can also do similar abstractions at a type level if you take advantage of typeclasses and data families. I really recommend that anyone interested in this tries out functional programming. It's very different from what you might be used to, but also has a wealth of new ways of looking at programming problems to offer.
I never learned all the design patterns of OOP, was mostly self-taught and had to write complex scientific simulation software using R (of all languages -.-). I read most of Hadley Wickham's book "advanced R" at the time and then just wrote code the way it made sense to me. Every so often I come across videos like this where some concept is explained and I realize, I've been writing code using these patterns without ever thinking about whether or not they exist. DI was something so obvious to do in languages like R, where functions are both input arguments to functions as well as return values of them. (Wickham calls them functionals and function operators). It all felt natural to me and made sense. Never thought there were some grand design deliberations behind such simple approaches.
While this originated in functional languages, you can do this in most languages these days. And heck, you can even do it in plain old C with function pointers or if you use Apple's clang extensions, block pointers that can capture lexically local references
I have a hard time imagining it makes the logic easier to reason about, but I could see how that would be cleaner than a language where functions are treated as object members.
out of the 5 short videos about Independency injection I just watched I got the most from this one. This is thanks to: 1) a big picture being brought - a bit of history and reason behind the DI technique, together with an architecture of the system; 2) the graphics of the tree of classes vs. when the DI has been implemented. Thank you for creating this. I find it helpful
wooooooowwww!! just like almost everyone else is saying, I couldn't find one person who could explain me what dependency injection is and you've explained it so nicely in this video in fact! I've used this while writing code for a checkout service which uses different payment gateways without knowing it!!!! that was a wonderful coincidence
DI and IoC always sounded like complex terms to me, but your explanation made it so simple to see! You have a great way of explaining things, and the editing really makes it pop out! Thank you! Hopefully you do more design patterns, or honestly anything really.
Thanks, your explanation is perfect for newbie like me who is still confused with so much jargon or terminology in these architecture framework things. I subscribe!
As other have said, this is by far the clearest explanation of dependency injection and inversion of control and the rationale for them I have seen. Also very concisely laid out arguments for and against use of dependency injection frameworks. You got yourself another subscriber!
Great explanation! I’ve been working with Laravel for nearly a decade, but only really started exploring the Service Container recently. It has a great implementation and relies heavily on DI to make testing and mocking very developer-friendly. Your video helped me understand it better conceptually, thanks!
I started learning DI a couple days ago and I think is a easy to understand, but a little hard to put in practice. I'm programming in C# and Microsoft DI library has some features like the lifetime of the dependency etc (Scoped, Transient...).
I agree, I find the trickiness comes from the particular dependency injection library you are using as each has their own “quirks and features”. The general happy-path mostly just works, but sometimes, even when you are familiarized with the library, you can get bit by the abstraction layers hiding a little too much and leading to some obscure bugs. Two fun stories from production: When I was at Google, one of my teams ran into rolling out-of-memory crashes in our fleet of servers. Memory usage would increase predictably, correlated with QPS before a crash and restart. We eventually traced it down to the dependency injection library (Guice) instantiating a particular class with each request, which in turn would do a lot of heavy memory allocations. Once we realized that, it was an easy fix, but it was non-obvious when looking at the code because the instantiation path was abstracted away. Another fun one: Angular has a built-in dependency injection library that on the surface looks pretty straight forward. However, a lesser known fact is that behind the scenes Angular generates a tree of Injectors that inherit from each other. In certain cases you can end up with what you thought was a singleton service instantiated multiple times across this injector tree. In my case I ended up with 2 duplicate caches that slowly would come out of sync and would manifest as unusual behavior in the UI. Took me long time to track down!
If you write your classes to contain no mutable state and only pure functions, you can simplify all of this to just using the singleton lifetime. At that point, classes are really just modules. You don't have to worry as much about thread safety, race conditions, excessive allocations, etc. You get a lot of the advantages of functional languages, make the code easy to test and modify, while keeping the syntax of C#.
This is a better explanation of why dependency injection exists than I ever heard in my years of being forced to use Dagger. I still think the majority of problems it solves are better solved with procedural programming but at least I understand it now.
Thank you for the great explanation. I'm new to programming and DI sounded quite complex when I first heard of it. But your explanation made it much easier to understand. Thanks a lot!
This is such a good overview description of this concept. Great job. I sent this link to the devs on all my teams. Instead of diving into more Angular videos have you considered similar videos for some of the other SOLID principles?
Thanks for sharing. I've been considering doing more general software engineering videos now. This video actually started as an Angular video that I broke up because it was getting too large!
Well, I certanly hope more contento from this guy. So clear and easy to understand such an important concept! Keep the software engineering concepts comming!
wow, a really well done video ! While I find dependency injection super useful is writing modular code, not a fan of the DI libraries i've used so far, in the JS ecosystem. However, with Typescript 5 bringing decorators to stable, I'm keen to see if there is an uptick in these projects !
I'm starting off with my SDE journey with nestjs. Its what I call DI and boilerplate hell, with hard to decode error traces. But i do get the appeal of having modularity & scalability with lots of verified library support right out of the box
Thank you so much for this video you made things a lot easier please stop whateever ur doing lol and start a carreer on youtube because man your the best i already tried many video but once i saw your everything is clear now
inversion of control? Yes! I think every time I write a `.map` it's technically IOC. But I used a library with decorators for NestJS and wasn't a huge fan for the exact reasons you mentioned. It felt like it made things really hard to grok without much benefit.
Use inversion of control a decent amount with functional components in React and occasionally when there's heavy stuff I want to use without having to have much "passing aroound" code (i.e. boiler plate) I remember about how 5 years ago I learned Angular 1 and 2 (in the same 6 week course! - odd) - and I recall that Angular 2 had "dependency injection". So ocassionally I wonder if that would have helped me in those moments, but mostly I'm happy with React so I haven't checked yet. - Funny that UA-cam served this video to me shortly after me thinking about that given that I didn't look anything up to find this :D
In code interviews they always ask “what is dependency injection” and I still struggle to answer it. I know why we do it, I just can’t find the words. I think ctos get too hung up on details like that
I think if I had to distill it to the simplest form: It's a pattern where instead of classes instantiating their dependencies, they are provided to it in the constructor. This makes the code more flexible. Then you could always drill into the benefits or specific framework the interview is asking about.
What frameworks or patterns would you recommend for JS/TS? I recently tried out inversifyJS, but decided not to use it, due to some the issues you mentioned, namely confusing rules about what gets injected where, lack of type safety for injected items, and, as a corrolary, many compile time errors becoming runtime errors. Plus it's basically unmaintained afaict.
I've personally tried tsyringe, typedi and typed-inject, which are all good and you should check them out in case you haven't, specially typed-inject which doesn't use decorators which may be seen as an advantage since now that decorators are in phase 3, some things that did exist back when those libraries were manteined now don't exist, such as parameter decorating. What I ended up doing is to just pass the dependencies via constructor and move dependencies to more abstract things like interfaces to avoid circular dependencies. The JS/TS DI ecosystem is not well developed yet compared to other languages like Java, so this approach ended up being one of the best solutions for me.
Dependency injection via constructor or some builder pattern is very useful; it makes testing using doubles a breeze, makes it easier to make big changes later if needed. I really don't get why anyone wants to use frameworks though. Why would I want to learn another language then not be able to figure out what is wrong when my code isn't working as intended? If you use good naming and follow SOLID principles why would you want to make your life hard again?
I worked for 5 years in a Java Spring environment and while I did understand the @Autowired annotation and the like, I never truly knew the definitions As for whether I like the pattern or not - I love it. I hated the codebase though because the people who wrote it originally made it a monolithic app that took 5 minutes to spin up... which you would need to do every time you make a server change. I don't see why dependency injection would be bad if had a well designed microservice architecture.
I'm a new ( < 1 Yoe ) SWE working on a large spring boot java codebase and the last part you mentioned about moving compile time errors into runtime has bit me more than once.
The solution is really simple: write unit tests. Write a test that calls your DI registrations, and then tries to resolve your root types. For example, if you have a MVC web application, write a test that checks that all of your controllers can be resolved, which by extension checks that the services they need can be resolved, etc.
Dependency injection is great. That said, I hate the frameworks. The barrier of creating a working setup and all the extra configuration classes, interfaces etc. usually make me give up and do the poor man's DI, by just providing the dependencies through the constructors myself.
I remember the days when OO was the hyped new thing, and UIs were turned full OO and the hype got so big that every pixel was put in it's own multiple-inheritance virtual class and whadaya-know, performance started suffering and changing the Pixel class required changing layers and layers of Interfaces. The solution was obvious. Buy pixel-servers! With complex load-balancing to make sure all pixels get updated in time. Ok, I may be exaggerating, but Dependency Injection is a genius idea. And thus, a great tool. But nevertheless, needs some moderation and contemplation to use without causing more damage than good.
React dependency injection doesn’t exist in this way. We use context, hooks, imports and pass by props. It’s arguably simpler in many ways. It’s dependency injection in a different form.
The examples are in Typescript. `(c) => { /* logic */ }` is an arrow function expression (also known as a lambda or anonymous function depending on your language). In this case it is defining a function that accepts a parameter `c` and will execute some logic. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
This is what happens when the temptation to write more "object-oriented" code is strong and you make a bunch of interfaces and used metaprogramming to reduce boilerplate while all you needed was just a f*cking callback function.
I guess I am the oddball that found your explanations awful. But what do I know? I have only been developing software for 40 years, 32 of those in object oriented languages and environments.
Not hardcoding dependencies into your class is not Dependency Injection by any stretch of the imagination. That's just a basic programming concept you learn right after Hello World. Similarly, providing arguments to a constructor is not DI. Passing objects to a constructor is simply the way constructors are supposed to be used. If you think calling a non-default constructor is dependency injection, then you fundamentally don't understand dependency injection.
I agree that non-default constructors are, by themselves, not a form of dependency injection. However, I’d maintain that the pattern of providing dependent resources to a class to avoid the coupling caused by the class creating them itself is.
@@ScottABailey There is nothing special about "providing resources to a class." That's how object oriented programming works. The term Dependency Injection was not coined to describe how object-oriented programming has always been done. This video does not describe dependency injection, and sadly, simply leads to more confusion in the industry.
People really underestimate how useful the testing aspect is. I work everyday with codebases which range from 10+ years old to just a few months old. The older stuff that didn't plan for DI is such a bitch to test because we can't pass in custom mock services, still trying to fight to let me rewrite these
FINALLY! Someone who knows this stuff and can explain it to people that are skeptical. I like the thorough coverage of IoC and DI and how they relate and their goals and purposes and ultimate practical implementation. I like that you pointed out how the abstraction of DI frameworks merely converts code to data, not reducing the complexity much, while introducing some of its own. Bookmarked this in case I have to deal with a fanatic. Thank you!
Amazing explanation🎉 The additional downside of using DI libraries is that these libraries have APIs that keep changing and one has to spend a large amount of time keeping the code current to keep up with the changing APIs and the annotations associated with them. Additionally, these libraries create a ton of generated code that is harder to debug and they also have defects which manifest in concurrency and race conditions
The general approach of making more and more layers of code, with lots of glue code obscure the control flow and logic used in apps, and is a terrible idea behind so much of the lousy i see. Leave it to programmers to find a way to make their products obscure and complex. It always seems motivated by a quest for increased billable hours, and job protection. Every good idea is immediately abused and taken to extremes.
I think dependency injection is unfortunately named. First times i heard of it, my mind instantly related it to SQL injection, just because of the naming, and as such saw it as something negative. First when I sat down and investigated what it was i realized my mistake!
The inversion of control example you gave was really eye-opening for me. I never never thought to have a function that is just meant to gaurd clause or handle logic before executing an important function. Personally, I find that extracting that type of function to resolve to a boolean if the logic is passed or not is a lot simpler than taking in a callback.
I used callbacks as an example for inversion of control here because they make a nice self contained case. You’ll often see the pattern playing out in a bigger scale in frameworks or larger libraries where the frameworks are calling into your code to perform some action, then control flow goes back into the framework An example would be something like a web server (like express.js) where you define custom handlers and tell it how it should process http requests. Or something like React/Angular where your components can have life-cycle hooks. They invert traditional control flow because the library is calling you instead of you calling the library.
I agree with Nathan. IOC is a pattern of having the callee defer to the caller, with one of the more common examples being frameworks (the callee) deferring to custom bits of logic being provided (by the caller). I do agree that coroutines and async code also impact control flow. However, I don’t see the two at odds with each other, rather as tools for different situations. You could design a library that uses IOC as a design pattern for customization while at the same time using coroutines for async work.
I've been developing professionally for 6 years and nobody so far during my education or work have been able to explain dependency injection to me in a way that was understandable for me. This video is fire honestly
I don't get it but this seems like a reason for me to save this video for a later time.
tbh dependency injection is just a fancy name for passing a value to a function and that value serves the purpose of abstracting the logic away from the function you are passing it into
@@esteban4983 so true.
Also, callbacks and IoC are not necessary for reusability and low coupling. More over, IoC tend to harm humanly understandable control flow and cause bugs.
From the video i see how to resolve basic SRP violation by delegating responsibility to another object. And that's done with "IoC". But you can just use dependency passed through constructor and that's it. And more, doing this way you move Billing dependency from the Checkout interface to concrete realization details. And that's a big deal for Checkout users.
So, is there any point for following IoC? Or we can just use DI with straight control flow without brain inversion?
@@nilpunch2 by "just use DI" do you mean using the constructor? if so, yes I agree. More so, callbacks make it harder to test and at least in OOP I would use the constructor to pass dependencies and not to the method itself
I feel sorry for whoever's been employing you to "develop professionally" when you don't understand fundamentals of your field.
I've been a developer for 24 years professionally, and no one has ever explained IoC and DI this clearly. Well done!
Clear and concise explanation with examples that are relatable, cheers Scott!
been using nestjs more and more in my backends, and once i realized what the "magic" was under the hood - dependency injection - it was easy to see why it was needed, and i learned to implement it by myself using the good old expressjs in a couple pet projects.
having it all setup for you is great, but learning how it actually works so you can confidently keep using such an opinionated framework knowing "the opinions" is way better.
I've been doing Rust for a bit more than 2 years now, and honestly every video I watch that introduces a programming technique makes me understand better just why Rust is so beloved. This one is no exception.
So in Rust DI is most commonly done using traits (basically interfaces in OOP lingo). A great example of this is the `Write` trait: it allows a single generic piece of code to write into basically anything - a file, a network stream, a memory location, a deserialiser, and more. And since it's such a core part of the language, the entire library ecosystem is interoperable via traits like this.
DI is one of those things that really make me appreciate functional languages like Haskell. Since functions in Haskell are themselves first-class values, you can easily invert control or abstract some functionality by writing a function which accepts other function(s) as argument(s).
So rather than designing and instantiating lots of interfaces and classes that all depend on and call back to each other in intricate ways, all I need to do is directly reference the callee function I want the caller to use.
You can also do similar abstractions at a type level if you take advantage of typeclasses and data families.
I really recommend that anyone interested in this tries out functional programming. It's very different from what you might be used to, but also has a wealth of new ways of looking at programming problems to offer.
I never learned all the design patterns of OOP, was mostly self-taught and had to write complex scientific simulation software using R (of all languages -.-). I read most of Hadley Wickham's book "advanced R" at the time and then just wrote code the way it made sense to me. Every so often I come across videos like this where some concept is explained and I realize, I've been writing code using these patterns without ever thinking about whether or not they exist. DI was something so obvious to do in languages like R, where functions are both input arguments to functions as well as return values of them. (Wickham calls them functionals and function operators). It all felt natural to me and made sense. Never thought there were some grand design deliberations behind such simple approaches.
While this originated in functional languages, you can do this in most languages these days. And heck, you can even do it in plain old C with function pointers or if you use Apple's clang extensions, block pointers that can capture lexically local references
I have a hard time imagining it makes the logic easier to reason about, but I could see how that would be cleaner than a language where functions are treated as object members.
Thank you so much for explaining dependency injection in the concise way.
As a beginner I Increased my knowledge base.
out of the 5 short videos about Independency injection I just watched I got the most from this one. This is thanks to: 1) a big picture being brought - a bit of history and reason behind the DI technique, together with an architecture of the system; 2) the graphics of the tree of classes vs. when the DI has been implemented. Thank you for creating this. I find it helpful
wooooooowwww!!
just like almost everyone else is saying, I couldn't find one person who could explain me what dependency injection is and you've explained it so nicely in this video
in fact! I've used this while writing code for a checkout service which uses different payment gateways without knowing it!!!!
that was a wonderful coincidence
DI and IoC always sounded like complex terms to me, but your explanation made it so simple to see! You have a great way of explaining things, and the editing really makes it pop out! Thank you! Hopefully you do more design patterns, or honestly anything really.
One of the best explanations on the topic that also addresses the pros and cons objectively and concisely. Outstanding job!
I know about DI but this video has reinforced my understanding of DI as a subtypoe of IoC
Thanks, your explanation is perfect for newbie like me who is still confused with so much jargon or terminology in these architecture framework things. I subscribe!
As other have said, this is by far the clearest explanation of dependency injection and inversion of control and the rationale for them I have seen. Also very concisely laid out arguments for and against use of dependency injection frameworks. You got yourself another subscriber!
This is one of the best videos you can find on DI period.
Great explanation! I’ve been working with Laravel for nearly a decade, but only really started exploring the Service Container recently. It has a great implementation and relies heavily on DI to make testing and mocking very developer-friendly. Your video helped me understand it better conceptually, thanks!
I love Laravel ❤
I started learning DI a couple days ago and I think is a easy to understand, but a little hard to put in practice. I'm programming in C# and Microsoft DI library has some features like the lifetime of the dependency etc (Scoped, Transient...).
I agree, I find the trickiness comes from the particular dependency injection library you are using as each has their own “quirks and features”. The general happy-path mostly just works, but sometimes, even when you are familiarized with the library, you can get bit by the abstraction layers hiding a little too much and leading to some obscure bugs.
Two fun stories from production:
When I was at Google, one of my teams ran into rolling out-of-memory crashes in our fleet of servers. Memory usage would increase predictably, correlated with QPS before a crash and restart. We eventually traced it down to the dependency injection library (Guice) instantiating a particular class with each request, which in turn would do a lot of heavy memory allocations. Once we realized that, it was an easy fix, but it was non-obvious when looking at the code because the instantiation path was abstracted away.
Another fun one: Angular has a built-in dependency injection library that on the surface looks pretty straight forward. However, a lesser known fact is that behind the scenes Angular generates a tree of Injectors that inherit from each other. In certain cases you can end up with what you thought was a singleton service instantiated multiple times across this injector tree. In my case I ended up with 2 duplicate caches that slowly would come out of sync and would manifest as unusual behavior in the UI. Took me long time to track down!
If you write your classes to contain no mutable state and only pure functions, you can simplify all of this to just using the singleton lifetime. At that point, classes are really just modules. You don't have to worry as much about thread safety, race conditions, excessive allocations, etc. You get a lot of the advantages of functional languages, make the code easy to test and modify, while keeping the syntax of C#.
This is a better explanation of why dependency injection exists than I ever heard in my years of being forced to use Dagger. I still think the majority of problems it solves are better solved with procedural programming but at least I understand it now.
Thank you for the great explanation. I'm new to programming and DI sounded quite complex when I first heard of it. But your explanation made it much easier to understand.
Thanks a lot!
finally an explanation that covers both sides of the debate. thanks :)
Never thought I'd learn dependency injection from Tom Hiddleston himself.
😂😂
thanks for that clear and concise explanation.
Just a small hint, at 3:29, there is a typo within "with".
This is such a good overview description of this concept. Great job. I sent this link to the devs on all my teams. Instead of diving into more Angular videos have you considered similar videos for some of the other SOLID principles?
Thanks for sharing. I've been considering doing more general software engineering videos now. This video actually started as an Angular video that I broke up because it was getting too large!
Wow, the ease of explanation you have is just amazing, clear, direct and concise, you have a new subscriber!
The world needs teachers like this
As a beginner for the first time I feel like I understood what an DI really is!
Im liking your down to earth approach at explaining im subbing lol
I'm still in my early career and this really helped me understand when to use it and when not to. Thanks!
Well, I certanly hope more contento from this guy. So clear and easy to understand such an important concept! Keep the software engineering concepts comming!
wow, a really well done video ! While I find dependency injection super useful is writing modular code, not a fan of the DI libraries i've used so far, in the JS ecosystem. However, with Typescript 5 bringing decorators to stable, I'm keen to see if there is an uptick in these projects !
Excellent video.
Keep it up.
Hope you continue uploading about design patterns and programming paradigms.
Perfect explanation for DI & IoC. Thank you so much.
Why can't we have more teachers like you in computer science?? Please make more videos!!
I'm starting off with my SDE journey with nestjs. Its what I call DI and boilerplate hell, with hard to decode error traces. But i do get the appeal of having modularity & scalability with lots of verified library support right out of the box
Thank you so much for this video you made things a lot easier please stop whateever ur doing lol and start a carreer on youtube because man your the best i already tried many video but once i saw your everything is clear now
inversion of control? Yes! I think every time I write a `.map` it's technically IOC. But I used a library with decorators for NestJS and wasn't a huge fan for the exact reasons you mentioned. It felt like it made things really hard to grok without much benefit.
This is really good. Hope you'll make more content in the same format. Kudos
Very good yet simple explanation of the topic! Would love to see other related videos on SOLID.
Very good explanation and right on point! Thank you!
Wow. I love the way you explained. It is so easy to understand now. Thank you so much for your efforts.
Thanks for the video! I often use dependency injection in Angular, but don't understand meaning behind it.
Thank you. Great explanation.
You've got great presentation skills! Looking forward to more content how to make my dev life easier (especially QA part). Thanks
very clear explanation thank you
oh, now I get the idea of this term. thank you!
Use inversion of control a decent amount with functional components in React and occasionally when there's heavy stuff I want to use without having to have much "passing aroound" code (i.e. boiler plate) I remember about how 5 years ago I learned Angular 1 and 2 (in the same 6 week course! - odd) - and I recall that Angular 2 had "dependency injection". So ocassionally I wonder if that would have helped me in those moments, but mostly I'm happy with React so I haven't checked yet. - Funny that UA-cam served this video to me shortly after me thinking about that given that I didn't look anything up to find this :D
Concise and good explanation, subscribed to see more of your content.
I've always thought I hated DI, turns out I only hate DI frameworks, thanks for enlightening me 🙏
In code interviews they always ask “what is dependency injection” and I still struggle to answer it. I know why we do it, I just can’t find the words. I think ctos get too hung up on details like that
I think if I had to distill it to the simplest form:
It's a pattern where instead of classes instantiating their dependencies, they are provided to it in the constructor. This makes the code more flexible.
Then you could always drill into the benefits or specific framework the interview is asking about.
Hi Scott excellent work...please do videos on spring boot
Fantastic video and animation, keep it up!1
Plz make more videos about other programming concepts like this one.a playlist for OOP
Just amazing. Thanks a lot !
Nice and clear.
Awesome video!
Make more 👍
What frameworks or patterns would you recommend for JS/TS?
I recently tried out inversifyJS, but decided not to use it, due to some the issues you mentioned, namely confusing rules about what gets injected where, lack of type safety for injected items, and, as a corrolary, many compile time errors becoming runtime errors. Plus it's basically unmaintained afaict.
I've personally tried tsyringe, typedi and typed-inject, which are all good and you should check them out in case you haven't, specially typed-inject which doesn't use decorators which may be seen as an advantage since now that decorators are in phase 3, some things that did exist back when those libraries were manteined now don't exist, such as parameter decorating. What I ended up doing is to just pass the dependencies via constructor and move dependencies to more abstract things like interfaces to avoid circular dependencies. The JS/TS DI ecosystem is not well developed yet compared to other languages like Java, so this approach ended up being one of the best solutions for me.
Amazing explanation, thanks!!!
A rising star on YT. wooooooohoooo
Dependency injection via constructor or some builder pattern is very useful; it makes testing using doubles a breeze, makes it easier to make big changes later if needed. I really don't get why anyone wants to use frameworks though. Why would I want to learn another language then not be able to figure out what is wrong when my code isn't working as intended? If you use good naming and follow SOLID principles why would you want to make your life hard again?
great video but maybe check how your audio levels compare to other youtubers you watch..i had to turn my volume up quite a bit
Line 5:23 Lethal Injection Exception
I worked for 5 years in a Java Spring environment and while I did understand the @Autowired annotation and the like, I never truly knew the definitions
As for whether I like the pattern or not - I love it. I hated the codebase though because the people who wrote it originally made it a monolithic app that took 5 minutes to spin up... which you would need to do every time you make a server change.
I don't see why dependency injection would be bad if had a well designed microservice architecture.
Im gonna stick to my procedure code, keep my methods micro and build wrappers on these methods to get things done for individual cases.
Rust isn't OOP language but widely uses this pattern too. Maybe you do not need to claim OOP. Otherwise your video is an excellent.
great video
0:30: "Spring", not "Swing". Spring is an extensive framework for Java. Swing as an old UI library.
As a web dev, having to create multiple pages, I solely depend on DI.
I'm a new ( < 1 Yoe ) SWE working on a large spring boot java codebase and the last part you mentioned about moving compile time errors into runtime has bit me more than once.
The solution is really simple: write unit tests.
Write a test that calls your DI registrations, and then tries to resolve your root types.
For example, if you have a MVC web application, write a test that checks that all of your controllers can be resolved, which by extension checks that the services they need can be resolved, etc.
I miss (bigger) real life example here, besides that it's a really good video
good one, keep on going
Some hand-wavy philosophical advantages but the code is obscure and undebugable. Guess which side I'm on 😁
2 words: Elixir/Erlang, ETS. More functional/data drive less issue.
i love pattern in nestjs
i was just think about this today
@2:20 It should spell "Separation", not "Seperation"
Dependency injection is great. That said, I hate the frameworks. The barrier of creating a working setup and all the extra configuration classes, interfaces etc. usually make me give up and do the poor man's DI, by just providing the dependencies through the constructors myself.
I remember the days when OO was the hyped new thing, and UIs were turned full OO and the hype got so big that every pixel was put in it's own multiple-inheritance virtual class and whadaya-know, performance started suffering and changing the Pixel class required changing layers and layers of Interfaces.
The solution was obvious. Buy pixel-servers! With complex load-balancing to make sure all pixels get updated in time.
Ok, I may be exaggerating, but Dependency Injection is a genius idea. And thus, a great tool. But nevertheless, needs some moderation and contemplation to use without causing more damage than good.
React dependency injection doesn’t exist in this way. We use context, hooks, imports and pass by props. It’s arguably simpler in many ways. It’s dependency injection in a different form.
You did not with that thumbnail! 🤣🤣🤣
Dependency injection: that makes sense!
Dependency injection libraries: that doesn't make sense!
WHICH LANGUAGE IS THIS???
Also, what's (c)=> {
}
The examples are in Typescript. `(c) => { /* logic */ }` is an arrow function expression (also known as a lambda or anonymous function depending on your language). In this case it is defining a function that accepts a parameter `c` and will execute some logic.
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
What I find annoying about DI is passing 12000 interfaces (with long-a$$ names no less) into so many constructors.
i dont use classes in general
This is what happens when the temptation to write more "object-oriented" code is strong and you make a bunch of interfaces and used metaprogramming to reduce boilerplate while all you needed was just a f*cking callback function.
Is this some computer science ASMR channel?
Some of the explanations in this are kinda poor... It just made this concept more confusing for me if anything.
{ belongs to a new line!
I guess I am the oddball that found your explanations awful.
But what do I know? I have only been developing software for 40 years, 32 of those in object oriented languages and environments.
Not hardcoding dependencies into your class is not Dependency Injection by any stretch of the imagination. That's just a basic programming concept you learn right after Hello World. Similarly, providing arguments to a constructor is not DI. Passing objects to a constructor is simply the way constructors are supposed to be used. If you think calling a non-default constructor is dependency injection, then you fundamentally don't understand dependency injection.
I agree that non-default constructors are, by themselves, not a form of dependency injection. However, I’d maintain that the pattern of providing dependent resources to a class to avoid the coupling caused by the class creating them itself is.
@@ScottABailey There is nothing special about "providing resources to a class." That's how object oriented programming works. The term Dependency Injection was not coined to describe how object-oriented programming has always been done.
This video does not describe dependency injection, and sadly, simply leads to more confusion in the industry.
the only concern is how we glue our code 😂😂😂
oh please do not use DI
People really underestimate how useful the testing aspect is. I work everyday with codebases which range from 10+ years old to just a few months old. The older stuff that didn't plan for DI is such a bitch to test because we can't pass in custom mock services, still trying to fight to let me rewrite these
FINALLY! Someone who knows this stuff and can explain it to people that are skeptical. I like the thorough coverage of IoC and DI and how they relate and their goals and purposes and ultimate practical implementation.
I like that you pointed out how the abstraction of DI frameworks merely converts code to data, not reducing the complexity much, while introducing some of its own.
Bookmarked this in case I have to deal with a fanatic. Thank you!
Amazing explanation🎉 The additional downside of using DI libraries is that these libraries have APIs that keep changing and one has to spend a large amount of time keeping the code current to keep up with the changing APIs and the annotations associated with them. Additionally, these libraries create a ton of generated code that is harder to debug and they also have defects which manifest in concurrency and race conditions
Your content is absolutely flawless. Please please please keep uploading.
The general approach of making more and more layers of code, with lots of glue code obscure the control flow and logic used in apps, and is a terrible idea behind so much of the lousy i see. Leave it to programmers to find a way to make their products obscure and complex. It always seems motivated by a quest for increased billable hours, and job protection. Every good idea is immediately abused and taken to extremes.
I think dependency injection is unfortunately named. First times i heard of it, my mind instantly related it to SQL injection, just because of the naming, and as such saw it as something negative. First when I sat down and investigated what it was i realized my mistake!
The inversion of control example you gave was really eye-opening for me. I never never thought to have a function that is just meant to gaurd clause or handle logic before executing an important function. Personally, I find that extracting that type of function to resolve to a boolean if the logic is passed or not is a lot simpler than taking in a callback.
It’s just a fancy name for “callbacks”.
I used callbacks as an example for inversion of control here because they make a nice self contained case. You’ll often see the pattern playing out in a bigger scale in frameworks or larger libraries where the frameworks are calling into your code to perform some action, then control flow goes back into the framework
An example would be something like a web server (like express.js) where you define custom handlers and tell it how it should process http requests. Or something like React/Angular where your components can have life-cycle hooks. They invert traditional control flow because the library is calling you instead of you calling the library.
@@ScottABailey That kind of pattern of ongoing sequence of actions is commonly handled nowadays by async code--i.e. coroutines.
@@lawrencedoliveiro9104 Coroutines are about concurrency. DI about giving the caller the power instead of the callee
@@NathanHedglin Maybe you should reread the response from @Scott Bailey above, talking about “inversion of control”.
I agree with Nathan. IOC is a pattern of having the callee defer to the caller, with one of the more common examples being frameworks (the callee) deferring to custom bits of logic being provided (by the caller). I do agree that coroutines and async code also impact control flow. However, I don’t see the two at odds with each other, rather as tools for different situations. You could design a library that uses IOC as a design pattern for customization while at the same time using coroutines for async work.
Gracias
Moving from Symfony to working on a chaotic legacy application with no framework... I so miss Symfony's "DI Container".