Это видео недоступно.
Сожалеем об этом.
Dependency Inversion Principle Explained - SOLID Design Principles
HTML-код
- Опубликовано: 12 авг 2024
- Writing clean code is tough, and is one of the largest differences between junior and senior developers. One way that you can quickly improve your code and start writing well designed code now is to implement the dependency inversion principle. This principle is part of the SOLID design principles.
The main idea of the dependency inversion principle is that any class that uses a dependency should only ever use the dependency through a predefined interface/wrapper. This makes it so that your code will never directly depend on a low level API for its operations. The reason this is so important is because if you ever need to change or remove that dependency it becomes really difficult when it is used all over your code. By wrapping this dependency in an interface you can depend on the interface you created which will make changing out the dependency painless.
Most likely you have written tons of code in violation of this principle, I know I have, but hopefully this video will help introduce you to why this principle is so good at making your code clean and maintainable.
📚 Materials/References:
Facade Pattern Video: • Facade Pattern - Desig...
🧠 Concepts Covered:
- What the dependency inversion principle is
- Why the dependency inversion principle is important
- How to use the dependency inversion principle
- How to spot violations of the dependency inversion principle
🌎 Find Me Here:
My Blog: blog.webdevsimplified.com
My Courses: courses.webdevsimplified.com
Patreon: / webdevsimplified
Twitter: / devsimplified
Discord: / discord
GitHub: github.com/WebDevSimplified
CodePen: codepen.io/WebDevSimplified
#SOLID #WDS #DependencyInveresionPrinciple
Genius. This guy succeeds where other tutorials fail.
As soon as he said "adapter or façade pattern" it all clicked.
I studied the SOLID principles using Java, but these series in JavaScript are fantastic! Great work!
Another great video as always! I wish I learned SOLID earlier, so much pain and suffering could have been avoided.
I have mentored Jr. Developers and wanted to share my experience. Teaching SOLID too early doesn't work because the coder doesn't have the painful memories that mentally reinforce / accurately quantify the value of SOLID. The same goes for recognizing code smells. A Jr Developer is often just pleased with producing a result that works because that's what yielded a good mark in school. (CS degree is a joke IMO. Its like teaching just enough chemistry to make bombs without any safety training)
@@skewty ++. Let juniors be juniors so they can become good seniors
@@danielmcgrane8608I am happy to read your comments. If dependency inversion is not for juniors then I am leveling up. (:
I am addicted to this channel now. I was searching for something else but when I saw this clip in suggestion, I had to come here as another interesting topic was explained so easily yet again.
you made me understand in 2 min what others failed in hours, thank you so much , that example was very very good
That is crazy but solid understanding of OOP and SOLID nowadays is must to have even for junior job seekers! Thank you!
I am speechless on how well you explained this. Props to you
this clicks so well since it sounds like it's related to the open/closed principle earlier in the series :)
At first i didn't realy understand how the lower level modules change affect the main code, but when you showed the difference in arguments of Stripe and Paypal it just clicked for me. Great video, thanks!
This video has helped me in my GSoC '20 project
thanks a lot
I loved this series. I hope you make more of the code concept videos in the future.
Tnx, finally I understood all these SOLID principles.
Thanks for this explanation! I was watching another tutorial but got really lost on the explanation. Thanks a lot for this simplified explanation!
I really wish you'd remake these SOLID series with typescript
Does it really matter what language it is? Just gotta use your imagination to connect the dots and adapt it to your language of choice.
i think this is code language agnostic,
@@brianbitchballs3902 some guys need examples to understand.
@@zuzukouzina-original for concepts its better to learn UML which can help you disassociate your self from languages , and focus on understanding concrete ideas not examples
TS is just JS with types...
Sub earned. Honestly, I looked for an explanation for half an hour and they all just repeated each other. None of them could actually explain it in simple terms like you did.
Dude, you are really doing a great job out there!
Keep going :)
Thank you; this is a very good example of inheritance and polymorphism (under the hood)
Great video! I would like to see the SOLID principles using typescript. Thank you a lot!
Great tutorial, well delivered. Thank you!
Crystal clear explanation! I wish I knew this channel earlier to save tons of time wasted on uni lecture slides!
thanks! Note to self - pass individual implementations as object in the intermediate class (functionality resides within individual implementations and intermediary acts as a glue). this way code is losely coupled and is easy to switch rather than be tightly coupled. Facade pattern eg. is very similar to this. Also Dependency injection in angular / Nest feels similar to this where controller will offload functionality to services).
Thank you so much! You made it very simple to understand!
wow, the best explanation with real case scenario..
thank you very much..
what a great explanation and example, subscribed!
Thanx men for making such a difficult concept so obvious
Thanks so much for this, really well explained!
Very clear and understandable Thanks
These are great videos. Thank you!
Superbly explained, as always.
Thanks for the very clear explanation!
Depend upon abstraction sounds like a better name. Dependency inversion is a confusing name since store still depends on payment processor not payment processor depends on store.
Yeah the name is pretty bad, it implies Stripe/PayPal depends on store which doesn't make sense. The concept itself is brilliant though.
Thank you for this great tutorial!
Thank you for this good explanation!
Great video! Thanks for the explanation.
Very well explained! You got a subscriber.
You should do a video on TDD or Unit testing (DI comes in handy)
a goldmine of information... thank you a ton!
just a note... would be great if you can provide a source code for the samples in the video, thanks again
Crystal clear. Wow
Thank you, well explained
every video is well explained tysm
You are just awesome. Thanks again for a great video as always
Has anyone told you that you're awesome? No? Yes?
Who cares. Here it is again. You. Are. Awesome.
Thanks so much for these videos. You're also making me wanna learn more and more JavaScript.
Thank you so much!
Honestly fantastic.
Please never quit Kyle @webdevsimplified
Thank you very much
Awesome explanation, tnx :)
Thanks. I was struggling to digest the Dependency Injection and you clarified it very well. Great explanation.
This is dependency inversion principle
This is dependency inversion principle
Wouldn't you want just a single PaymentProcessor and have the logic for handling the different integrations within the class itself so you don't have to duplicate the entire class to change a method?
That violates OCP
No, you want some interface or set of interfaces for the payment processing, like an abstract class for the Payment Processor, and possibly using something like the Strategy Pattern, to make your concrete Payment Processors. Then you can use the Strategy Pattern to just swap out between different PaymentProcessors easily.
Really nice one! it reminds me of the BFF pattern.
This is interesting explanation.
Easy explained. Heads up
Why there is a single dislike? He is such good teacher.
Some people might legit not like this video. But also a lot of bots dislike videos to appear like real users. When you "buy likes" from an underground service they will spam likes to the video you want, but to appear like they are not bots they will also dislike random videos (to make it seem like it is just organic traffic).
Thank you
great example
Thanks, bro
love your videos
What a great explanation! Thanks a lot ^_^
You are very welcome!
This principle, is the most close to strategy pattern in my opinion...
Youur videos are really great. Please provide the code for all the principles
DI without typing is a lot of pain. So, if you're writing any serious app in JavaScript, I *strongly* suggest using *TypeScript* .
Thanks!
You are very welcome!
Imagine then that PayPal introduces coupons as a payment functionality that we can now use. Would we then put the extra functionality in the PayPalPaymentProcessor and let the PaymentProcessor API stay as is, or would we have to redefine the API(s)? I myself tend to like the idea of putting the incommon functionality in the implementations themselves and keep the common API for common functionality, but I am not sure whether or not that follows SOLID well enough.
Nice man, thanks a lot ! sometimes the solution is simple but me head is a mess and doesn't help. :)
Now this video is old but i dont get one part:
Shouldnt there be a Abstract Class or Interface that gets implemented/extended by both processors, so that you dont have to keep changing the payment method in the store?
I mean at the moment you still can not allow both methods at the same time and you still have to make changes in your highlevel class for a lower-level change, wich kinda still violates DIP...
Hi Kyle, good tutorial. thank you.
I am little bit confused to distinguish the OPEN/CLOSE and dependency injection based on your example. They are very similar. Can you explain more, please give example
SOLID is
Single responsibility
Open close principle
Liskov substitution principle
Interface
Dependency injection
Richard Martin's said that the S and the O can be join together and create a Dependency inversion principle.
So in shorter words, they are the same
@@nandomax3 dependency injection is not a principle. Dependency inversion is the fifth principle. Dependency injection is an implementation
@@vittoriomorellini1939 it's funny, because I posted this a year ago and just learned about spring DI implementation this month hahahaha
While this is a DI.. This is also strategy pattern
Hey, please cover all the 22 GOF design patterns.
For some who didn't know about the origin of DI.
It was implemented as "Adapter Pattern" as one of Design Patterns. It was only coined as DI because we don't want to depend our application to the framework. We want the framework to depend our application.
I don't know what is to depend anymore.
Or maybe it's that the word is ambiguous at times.
@@FG-qs8uj If you want to know more why DI is so important in large scale application. try to search up Clean Architecture by Uncle Bob. It's just the same as SOLID principle.
If you're not happy with OOP. then youi can always go back to Functional Programming.
If you read what you wrote:
We don't want to depend X to Y.
We want Y to depend X.
X is application, Y Is framework.
Wouldn't be better:
We don't want X to depend on Y.
We want Y to depend on X?
Or:
We don't want Y as a dependency of X
We want X as a dependency of Y.
In any case, my point is that saying X depends on Y is more intuitive to me. I.e. an application depends on a framework to work, i.e. if you see the application requirements file you would see the framework mentioned.
The other way, Y depends on X. Meaning the framework depending on the application is not intuitive to me, since the framework doesn't need the application to work.
I suppose then that the semantics of 'depend' and derivative words is what is confusing.
And even then, I don't see the point on discussing Y depending on X Vs X depending on Y. At the end I don't see what changes in the code.
your video helps me to become a good full stack developer
Only an interface is needed, which would be implemented by both Stripe and PayPal classes.
I guess Javascript doesn't have interfaces, right?
normal js doesn't but typescript do, and its almost the same as js but you can use int, float, etc..
Thanks!!!!
I have a question, how to make sure that both StripePaymentProcessor and the other one have pay method?
By implement Interface is good idea???
yes, you can make an interface class, then create classes that implement the methods
a base PaymentProfessor interface that enforces makePayment() method is a good idea, since it is reasonable to assume that all payment methods will make payment, so other the substitute principle is satisfied also.
Does this mean we need to create middleman classes/functions whenever we have dependencies on external third-party api's? Should we do the same if we have have dependencies on internal modules(if it is a big/long module) we ourselves created?
Coupling is only bad in one direction. Also don't couple high level business code / computation code with low level data storage / access code. Uncle Bob is probably the most famous SOLID guy. Checkout some of his videos if you are interested in further developing your understanding of SOLID.
Can we achieve interface segregation principle using DI?
Isn't the wrapper dependent on the payment API and not the other way around?
so you're just adding an intermediary class in-between to essentially normalize the differences between the different payment APIs?
Thank you so much for this great tutorial.
I think it would be better if you created an interface with function called pay and let the processors implement thisbfunction
JavaScript doesn’t support interfaces unfortunately. That’s why I kinda wish he would’ve made these videos in typescript
Is this not the example of Open/Closed Principle ?
In Java, StripeProcessor and PaypalProcessor implement PaymentInterface.
Why not make StripePaymentProcessor and PaypalPaymentProcessor implement an Interface PaymentProcessor to enforce the structure of the makePayment method? Optionally it could also extend a PaymentProcessor abstract class if there is some shared method.
There are no interfaces in Javascript? How can you be sure that each type of *PaymentProcessors has method 'pay'? Or should you check it manually in Store class?
Unless you use something like TypeScript you cannot guarantee this. It is just something you need to know when developing the code.
You could write unit tests that verify certain functions exist on both
Simple version:
Check that the pay method exists before setting this.paymentProcessor.
if (typeof paymentProcessor.pay !== "function") {
throw new Error('Store.paymentProcessor requires method pay ' )
}
Sophisticated version:
Create a NullPaymentProcessor class that contains the required methods, but they throw a descriptive error (or handle the exception some other way, depending on your implementation) , then make StripePaymentProcessor and PayPalPaymentProcessor extend the NullPaymentProcessor class.
class NullPaymentProcessor {
pay() {
throw new Error(`No pay method defined in ${this.constructor.name}. pay is a required method`)
}
otherMethod() {
throw new Error(`No otherMethod defined in ${this.constructor.name}. otherMethod is a required method`)
}
}
class StripePaymentProcessor extends NullPaymentProcessor {
constructor(user) {
super()
this.stripe = new Stripe(user)
}
}
class Store {
constructor(paymentProcessor) {
this.paymentProcessor = paymentProcessor
}
purchaseBike(quantity) {
this.paymentProcessor.pay(200 * quantity)
}
}
const store = new Store(new StripePaymentProcessor('John'))
store.purchaseBike(1)
output -> No pay method defined in StripePaymentProcessor. pay is a required method
More or less, use the null object design pattern to implement an interface in javascript. Kyle, would you agree with this approach?
Honestly i didn't catch the point of doing that in this example. For me it looks like instead of 2 store classes for each payment method we have just created 3 classes (1 store and 2 payment processors). I thought it should be one payment processor class for both cases which will react different depends on arguments we passed either paypal or stripe. So, a little bit confused by this lesson.
The point of this code is so that we can decouple the API we use and the store from each other. Now our store only depends on the processor wrapper we created so we can freely change our API of choice by just creating a new wrapper to wrap that API and our store stays exactly the same. If we tried to make one payment processor that handled all the APIs then we would be violating other SOLID principles such as Open/Closed.
@@WebDevSimplified i didn't hear yet about that open/closed principles. Thank you for explanation and for all your short but effective lessons 👍
Is SOLID applicable to React development or Express app?
Is it awkward?
yes, solid principles apply even to non-OOP paradigms like functional programming
How the simple UML in the video is made?
Please consider adding links to your code examples.
But what is the point of making two abstract classes instead of one? Make one, make a init function, a makepayment function and the paypal/stripe fully inherit that and you define what you want. The only thing that happened is that instead of defining a new entity Paypal and using the function, you added a new class which calls the subclass.
thats what I was thinking. The paymentProccesor could implement a strategy pattern right? Which keeps it all clean and simple
Is dependency inversion the same as abstraction?
Dependency Inversion is a form of abstraction, but not all forms of abstractions are Dependency Inversion. Basically, you use DI when you're implementing something that can be done in multiple different ways and you may need to change/support other ways in the future. Besides the Payment Processor example in the video, another example would be if your app had a "share to social media" feature. Say you only wanted to have an option to share to facebook now. You could make a facebook class & shareToFacebook() method that shares your content to only facebook. But now if you decide to add options to share to twitter or instagram later, you're going to have to edit multiple places in your code base to support this.
Now imagine if instead of creating a facebook class & shareToFacebook() method, you created a SocialMedia class and a generic share method that can be passed in a specific type of social media. Now you only have to extend the SocialMedia class to support twitter, instagram, etc and you don't have to go and edit your whole code base like you would in the facebook class example. Hope this makes sense, good luck!
Haha, I see you fixed your floor mat issue? :P
So this gives the same advantages that dependency injection gives in .net can make coupling loose
Hmmm not sure! Dependency inversion is a type of dependency injection. What is special about this kind of DI is that you do not declare in any moment what concretion will be used inside the high level classes, it leaves it to the client code in which the high level class will be instantiated. Not any dependency injection works like that, after all it's possible to design a dependency injection declaring a low level class inside a high level class, which violates the dependency injection principle, making the high level class get to meet the low level class, generating coupling.
So.... this thing "dependency inversion principle" with a very long name, just means using interface not concrete classes?
This kind of stuff screams for the use of interfaces (I know they are not supported in JS, one of the reasons I moved on to TS)
In this case it's the responsibility of the developer to make sure all paymentProcessors implement -correctly- the method pay
This is exactly what I was thinking. Programming without interfaces always looks so cumbersome. This could have been resolved in a much simpler way with an interface.
Do you have a masters degree in computer science? If not I do have one a piece of paper but you are smarter than me!
In practice these abstractions make code difficult to read and navigate: you keep getting to abstract interfaces and then having to back reference and sometimes guess which implementation is used. The whole idea is that we may easily swap out implementations but in practice this is surprisingly rare.
Depends on the kind of software you write, sometimes it's very useful. It also facilitates decoupling which can reduce build time in compiled languages and makes it easier to unit test your modules separately which is in my opinion the real reason to do this.
funny enough, we you experience pain in coding and slowly walk your way out for cleaner code, you might unconciously applied SOLID principle without knowing it
I was looking for the interface class then I realised it’s JavaScript 😂
You should write a book!
I have thought about it but I am a bad and slow writer my weekly blog posts already take me a really long time to write compared to most people.
@@WebDevSimplified Your videos are still awesome and "simplified" :) keep them coming.
Video suggestion: A JavaScript learning roadmap which gets more complex the more you advance (Junior, mid-level and senior). As most roadmaps out there focus more on the web-dev path in terms of tools and technologies, but non goes in depth in terms of the language itself and CS concepts.
@@WebDevSimplified Slow and steady wins the race........
Great idea. I will for sure add this to my list.
Isnt it looking same as dependency injection
9.41 He said oops in oops concept 😀😃
Why is it called inversion though?
Looks pretty similar to MVVM concept
👍
❤
Kinda funny. My company is currently implementing Stripe into our infrastructure. The project has taken 8 months.
I’m QA. No real visibility to the code. But it must be breaking multiple design principles to take this long.