Dependency INVERSION vs Dependency INJECTION in Python

  Рет қаралды 153,579

ArjanCodes

ArjanCodes

Күн бұрын

What's the difference between dependency inversion and dependency injection? Dependency injection is a design pattern that splits creation of objects from their usage. Dependency inversion is a design principle that promotes using abstract classes and interfaces to better separate code. Watch this video to see a few practical examples in Python, and how these concepts help you write nice code that's easy to test.
The code I worked on in this example is available here: github.com/ArjanCodes/2021-de....
💡 Here's my FREE 7-step guide to help you consistently design great software: arjancodes.com/designguide.
🎓 Courses:
The Software Designer Mindset: www.arjancodes.com/mindset
The Software Designer Mindset Team Packages: www.arjancodes.com/sas
The Software Architect Mindset: Pre-register now! www.arjancodes.com/architect
Next Level Python: Become a Python Expert: www.arjancodes.com/next-level...
The 30-Day Design Challenge: www.arjancodes.com/30ddc
🛒 GEAR & RECOMMENDED BOOKS: kit.co/arjancodes.
A few interesting links to articles and books:
- Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides: amzn.to/3jllgyH
- Principles of Package Design: Creating Reusable Software Components by Matthias Noback: amzn.to/2NETK3l
- Clean Code: A Handbook of Agile Software Craftsmanship by Robert Martin: amzn.to/3qVZgNs
- The original Design Principles and Design Patterns article by Robert Martin: fi.ort.edu.uy/innovaportal/fi...
👍 If you enjoyed this content, give this video a like. If you want to watch more of my upcoming videos, consider subscribing to my channel!
💬 Join my Discord server here: discord.arjan.codes
🐦Twitter: / arjancodes
🌍LinkedIn: / arjancodes
🕵Facebook: / arjancodes
🔖 Chapters:
0:00 Intro
0:20 What is a dependency?
1:10 Dependency injection
1:36 Dependency inversion
2:03 Example code
3:22 Example unit tests
5:32 Issues with testing
6:37 Applying dependency injection
8:35 Writing the unit tests
11:20 Applying dependency inversion
12:51 Coverage reports and abstract classes
14:16 The power of dependency inversion
14:49 Adding another authorizer
15:44 Adding tests for the Robot authorizer
17:10 Summary
#arjancodes #softwaredesign #python
DISCLAIMER - The links in this description might be affiliate links. If you purchase a product or service through one of those links, I may receive a small commission. There is no additional charge to you. Thanks for supporting my channel so I can continue to provide you with free content each week!

Пікірлер: 225
@ArjanCodes
@ArjanCodes 3 жыл бұрын
Finally upgraded to better microphones for this video!
3 жыл бұрын
It makes a huge difference!
@jamie9926
@jamie9926 2 жыл бұрын
You could record an audiobook about python now haha!
@metal571
@metal571 2 жыл бұрын
The RE20 is an excellent choice. Love this channel
@alira7296
@alira7296 2 жыл бұрын
I'm only a couple of minutes in so far, but I'm actually finding it hard to listen because of the music...
@raidensama1511
@raidensama1511 2 жыл бұрын
It’s about time 😉
@HenockTesfaye
@HenockTesfaye 2 жыл бұрын
I like the background sayings "It depends" "Solid advice"
@susmitvengurlekar
@susmitvengurlekar 3 жыл бұрын
After learning about testing, there is more happiness and more smiles when all tests are pass than the actual code working properly 😂
@ArjanCodes
@ArjanCodes 3 жыл бұрын
Who cares about working code! 😄
@vekyll
@vekyll 2 жыл бұрын
If you write your tests properly, these two should be the same!
@yuriysukhorukov391
@yuriysukhorukov391 2 жыл бұрын
@@vekyll The testing can not prove that the code works properly, it can only prove that smth goes wrong )))
@vekyll
@vekyll 2 жыл бұрын
@@yuriysukhorukov391 Of course. This does not contradict what I said.
@digitig
@digitig Жыл бұрын
@@vekyll You can't fully test any non-trivial code. That's why for critical software there has to be analysis as well.
@ruszkait
@ruszkait 2 жыл бұрын
Very nice video again! :-) Dependency injection is covered very well, but the dependency inversion was for me a bit incomplete. As I have seen you have just implemented a "strategy pattern". In my opinion dependency inversion is a bit more than that - though the machinery is the same. The essence of dep. inversion: We want to make that the peripheral details depend on our precious business logic and not the way around. In you example I see the Order and Payment Processor as the business logic, which we want to protect from peripheral details. Therefore we split the Order and Payment Processor into a separate module and there - beside the Payment process implementation - we define the Authorizer interface (ABC in python terms). So the business logic component is "virtualized", it runs on an abstract peripheral - as we have only an interface for the peripheral. Then in a Authorizer module we implement the Authorizer interface from the business logic module. If we do so, then we have flipped (inverted) the dependency. The business logic (Order, Payment Processor, abstract Authorizer interface) does not depend on the concrete peripheral implementation any more, it depends only on its internal interface (Autohrizer interface). On the other hand the Authorizer (peripheral) depends on the business logic as it implements the Authorizer interface. So just by shifting the interface from the peripheral component to he business logic component we have flipped (inverted) the direction of the dependency between the components. I think it is hard to demonstrate it well if all the logic is in one file - you do not see the component (module) boundaries. It would easier if you split up the code: the business logic component (python module) would contain the Order,Payment Processor, Authorizer interface and the peripheral component would contain the Authorizer implementation classes. So the "import" statements would reveal the real power of dep. inversion. You would have an "from business_logic import Authorizer" in the peripheral code, but in the business logic you would have no "from Authorizers import SMS_Authorizer" statement. Another improvement could be that the composition root is also in another component (this is what you have now in the main funcion). The composition root would wire everything together so, it would be dependent on everything (business logic and authorizer peripherals).
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thanks for your feedback! It's true that to get "real" dependency inversion, you'd split out the different classes into different files. I have not done that for these examples to keep things simple, but in this case it might have been helpful to do that. I'm trying to ride a careful balance between having practical examples that actually show how it works in "the real world" but still keeping things simple enough that my videos about them make sense :).
@Victorinoeng
@Victorinoeng 2 жыл бұрын
Thanks, Tamas. Your comment was polite and constructive! I am actually gaining twice the value: from the videos and the amazing constructive comments, such as this one! The idea of the importing statements made a lot of sense to me regarding the “inversion” part! Cheers!
@xtunasil0
@xtunasil0 2 жыл бұрын
I was just asking myself "ok but why is it an 'inversion'?" And your example is crystal clear! Thank you very much!
@magenertech9412
@magenertech9412 2 жыл бұрын
Great video and great comment, just to get things straight (correct me if I'm wrong): Dependency Inversion is injecting generic abstract dependencies rather than the actual dependencies. This makes the actual implementation of a said dependency irrelevant to the dependent class therefor making looser coupled code.
@ruszkait
@ruszkait 2 жыл бұрын
@@magenertech9412 What you describe is rather the dependency injection: where you want to consume a class, you consume an interface instead and the instance is given/injected to your class. For example if you want logging in your library, then you expect in your constructor arguments a logger interface. Then when the system starts-up it can decide what logging system will be injected. For your this detail is irrelevant, you just use the interface. The dependency inversion is a bit different topic: It helps you to place the interfaces (like the logging interface) into libraries. In the classical approach you have a logging library, which has a logger interface. If you want to use logging via that interface, then you become dependent on that specific logging library. So basically your flexibility is reduced to a certain level, that you do not have to know which exact logger from the logging library is injected into your code (say: network logger, file logger, console logger), but you are limited only to those loggers, which are coming from that specific logging library. If you do a step forward and you want to get rid of this restriction, too, then you apply the dependency inversion principle. In this case you do not use an interface from the logging library but you declare and interface in your library yourselves. Then in the system code (say the main function) the user of your library creates a small adapter class, which maps between your logging interface and the interface of the logging library. This way you became absolutely independent of any logging framework, your library is much more versatile. And where is the inversion? Now your library is not dependent on the logging library, so you do not have outgoing dependency, but the adapter becomes dependent on your library. So you have flipped the direction of the dependency just by pulling the interface into your library.
@SurajAdhikari
@SurajAdhikari Жыл бұрын
Nice video. One important detail you could add for tests is that instead of instantiating an actual object we normally create a mock object which inherits the abstract class. The mock implementation obviously will have dummy return values. But that will highlight the true power of dependency injection in lieu of unit testing.
@ArjanCodes
@ArjanCodes Жыл бұрын
Great suggestions, Thank you.
@steventimberman9313
@steventimberman9313 2 жыл бұрын
This is the first example I've ever seen that clearly shows the motivation behind an abstract class, great video!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Glad you liked it, Steven!
@kayakMike1000
@kayakMike1000 2 ай бұрын
I usually refer to databases when thinking about dependecies. Your project will likely be just fine if it uses mariadb or postgres or oracle or mssql.... Just provide an object that can run basic SQL queries, doesn't matter which.
@vinnyt4398
@vinnyt4398 2 жыл бұрын
I've also encountered similar pain when running tests where my function creates an object within, and I need that object to be in a certain state in order for my test to pass. The thing I had to do (not really recommended, but it works), is you use mock on the "__init__" method of the class for the object you create. In your example here, you would have to mock the "__init__" method of the class Authorizer_SMS
@AlejandroLamKhoa
@AlejandroLamKhoa 2 жыл бұрын
Thank you for having the videos in this series build on concepts of earlier videos. I have been binging your videos, and now while following your example of dependency inversion, I could already tell how you were going to apply that concept and the code you'd write. Thank you Arjan!
@WilliamBrumble
@WilliamBrumble 2 жыл бұрын
Well structured thorough video that includes design pattern and unit testing. Thank for sharing!
@cetilly
@cetilly 3 жыл бұрын
Your videos are brilliant. Just love this content. I need to watch this video a couple times to catch everything going on.
@ArjanCodes
@ArjanCodes 3 жыл бұрын
Glad you enjoy it, Chuck!
@NilenduDasnilendudas
@NilenduDasnilendudas 2 жыл бұрын
Dependency inversion is the process of introducing a new layer between objects in the form of abstract class to reduce dependancy between objects directly and also means that these can be replaced with their subtypes. - This is hands down the most simple definition I have ever heard. Thank you so much.
@DerekHohls
@DerekHohls Жыл бұрын
Are ABC classes really the only way to achieve this?
@janekschleicher9661
@janekschleicher9661 Жыл бұрын
@@DerekHohls In python certainly no. You can just duck type and just call the methods on the passed objects. As the method call is resolved dynamically at runtime, it works if you pass the right kind of object and most certainly fail if not. The only disadvantage of that approach is that it makes IDE/linting support harder, so less likely to have autocompletion or detection of completely wrongly passed objects before starting the program. (You can work that out by helping the linters with specific mypy or pylint or w/e header files for the objects or improving the IDEs. For several highly dynamic projects that uses dependency inversion/injection a lot like Django, that's indeed what's done there). And of course, what also can happen that for accident the passed object is the wrong one, but supports the called method, so your business logic is doing something completely wrong just because two different methods are called the same for different classes (this of cause concerns the purist, but is rarely a real problem). The main motivation for the abstract classes is coming from the static compiled languages that just need to know an interface to check it at compile time and prepare the calling in the compiled code already (internally they also reserve some at compile timed known locations like offsets where the address of the method is stored, so they can just say at assembly JUMP to that address). But even in those, big dependency inverse/injection systems are often implemented by (what is there called) reflection what is just dynamical lookup with a bit more type safetyness. The classical example for it would be Java Spring, but most other bigger Java systems use this kind of reflection a lot, too. The most negative example would be log4j where this resulted in a hazard security problem :-) - But indeed, the pattern can also be completely language agnostic. E.g. Kubernetes uses it also to a high degree and with just configuration in yaml files (again bypassing a very static language like Go with a very dynamic injection system). So, the abstract classes are the old school examples coming from old Java in the design patterns written in the 90s. They are still valid, as unless you want to write a big framework, in static languages, they are often enough choosen as path of least resistance and "most" control. But certainly, the dependency inversion/injection is not necessarily achieved by abstract classes and I guess (I don't have hard numbers on that), that most big system don't rely on it per se. (Usually they still have it, even though it's technical not necessary, but as a way to communicate the necessary interface and it's easier to write an abstract interface/class and have an auto documentation, auto linting, auto completion, etc.) - than to "just" write a good documentation and a good error handling if things are not done right :-)
@kukuruzayevhenii8764
@kukuruzayevhenii8764 Жыл бұрын
Thank you! I watched a dozen videos on the topic, but this one not only explained it in the best way, but also felt like a way more complete explanation!
@ArjanCodes
@ArjanCodes Жыл бұрын
Thank you!
@alilee4505
@alilee4505 2 жыл бұрын
Keep up the good work Arjan. These Python OOP topics are helping me understand a lot of new concepts! I also like how you demonstrated unittests and code coverage!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thank you Ali, and will do!
@taylormonacelli
@taylormonacelli 2 жыл бұрын
So clear, so concise, so awesome! Thank you Arjan
@davidzitzmann542
@davidzitzmann542 2 жыл бұрын
6:24 I'm glad that I'm not the only one having problems with this mock system. I had such huge problems with this, that I was forced to use dependency injection. Thank you python standard library to make me a better person!
@RichardVodden1
@RichardVodden1 Жыл бұрын
This is a wonderfully clear explanation of a potentially very complex topic. Thank you very much. I tend to prefi my instance variables with _ (e.g. self.autborizer) so that mypi will warn if I call it from outside the class. This avoids accidentally introducing coupling through injected components.
@nithyanandhasubramanya
@nithyanandhasubramanya 2 жыл бұрын
Wow !! Just one video and I subscribed . The content and quality is outstanding !!!! thank you so much for sharing the knowledge in such a easy way. I look forward to more such videos.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Welcome aboard! ;)
@fazzah777
@fazzah777 2 жыл бұрын
your test cases with repeat initialization of sms authorizer are a great starting point for a pytest fixtures tutorial, which are a powerful tool as well. Great video, as always!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thanks! And that's certainly something I'm going to cover soon on the channel!
@andyanderson222
@andyanderson222 Жыл бұрын
I absolutely love this channel! Its pure joy to watch these tutorials! Thanks a lot!
@ArjanCodes
@ArjanCodes Жыл бұрын
Thanks so much, Andy!
@rakeshkulkarni2125
@rakeshkulkarni2125 8 ай бұрын
Fantastic Tutorial, you explain why something needs to be done instead of just explaining how it's done(which are most of the tutorials in KZbin). And it's very easy to retain the knowledge because now you know why's behind the logic. Great job !!
@ArjanCodes
@ArjanCodes 8 ай бұрын
Much appreciated! Thank you very much!
@user-tq7xp6ev1y
@user-tq7xp6ev1y 2 жыл бұрын
Thank you for really clear and helpful explanation. Code examples are very illustrative too. Nice work!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thank you - glad you like it!
@DeKeL_BaYaZi
@DeKeL_BaYaZi 26 күн бұрын
You are the coolest developer ever
@ArjanCodes
@ArjanCodes 18 күн бұрын
Thank you so much for the kind words!
@rolandovillcaarias5112
@rolandovillcaarias5112 Жыл бұрын
Finally I can see an example to understand DI clearly. Thank you Arjan for your explanation :)
@ArjanCodes
@ArjanCodes Жыл бұрын
My pleasure 😊
@rjgonzalez8108
@rjgonzalez8108 2 жыл бұрын
Thanks for sharing this high quality content. Very clear explanations. I'm learning Python coming from an embedded systems background. I need to pickup the language asap. I'm currently debating on whether to pay for.a course or teach myself with books, videos and doing projects. Would be great to know how you or others reading this have learned Python.
@dmytroparfeniuk2670
@dmytroparfeniuk2670 2 жыл бұрын
Best video I have seen regarding DIs. Thanks!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Glad it was helpful, Dmytro!
@TheBIKEDEALZ
@TheBIKEDEALZ 2 ай бұрын
superb. what should be the guideline to splitting it properly?
@Hubert4515
@Hubert4515 2 жыл бұрын
super useful information about inversion and injection, thanks
@muralir8504
@muralir8504 2 жыл бұрын
best tutorial for advance topics
@paulkuhne3855
@paulkuhne3855 2 жыл бұрын
Extremely clear explanation. Great! Thank you!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Glad you enjoyed it, Paul!
@Lodinn
@Lodinn 2 жыл бұрын
Great CAPTCHA 10/10 would implement
@AR-scorp
@AR-scorp 2 жыл бұрын
Excellent video. Thanks for making and sharing this.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Glad you enjoyed it!
@Jacob011
@Jacob011 2 жыл бұрын
Turns out, I considered this common sense and used it in my code without even knowing what it is called.
@brianakong7644
@brianakong7644 Жыл бұрын
Awesome video, explanations, and examples! Thank you!
@ArjanCodes
@ArjanCodes Жыл бұрын
Thanks so much Brian, glad the content is helpful!
@MarkWernsdorfer
@MarkWernsdorfer 2 жыл бұрын
thanks for the video! instead of a docstring or a rc file, can't you also just raise notimoplementederror for coverage to ignore abstract classes? or decorate them as abstract?
@edgeeffect
@edgeeffect 8 ай бұрын
As ever, an excellent video but could I just recommend that watchers follow this up with Code Aesthetic's equally excellent Dependency Injection video.
@pinakadhara7650
@pinakadhara7650 2 жыл бұрын
Excellent content. Thanks a lot for making this!
@robertbrummayer4908
@robertbrummayer4908 2 жыл бұрын
Great explanation
@brennorris7061
@brennorris7061 Жыл бұрын
Coding Away, one of your video came up on in the background... 3 hours later, i think you're one of the best presenters on KZbin :) Very knowledgeable and not afraid of diving down deep. Thank you for all your time and effort! PS i totally hate the python module system of 3.7 (we have some legacy code and we cant get off the damn version) - are there notable improvements between 3.7 and say 3.9 or even 3.10?
@brennorris7061
@brennorris7061 Жыл бұрын
OH! and if you even see the above comment I have to ask: are you able to target bytecode (WHL/Eggs?) written in 3.9/3.10 so we can write modules in newer versions and know they'll work on the older 3.7 codebase? i'm pretty new to Py - sorry if its a stupid question.
@felipealvarez1982
@felipealvarez1982 2 жыл бұрын
I was delighted to see mock and testing! Every programmer should be doing this!
@DerekHohls
@DerekHohls Жыл бұрын
I missed seeing mock objects here - where were they used?
@felipealvarez1982
@felipealvarez1982 Жыл бұрын
@@DerekHohls I think at 4:06 and 9:49
@DerekHohls
@DerekHohls Жыл бұрын
@@felipealvarez1982 Those snippets refer to "patch" not mock?
@felipealvarez1982
@felipealvarez1982 Жыл бұрын
@@DerekHohls patch is a convenience method for mock. Same library.
@DerekHohls
@DerekHohls Жыл бұрын
@@felipealvarez1982 Thanks! I find mocking quite an obscure topic to understand; but Arjan's use of it here made perfect sense. Hope he tackles the topic in depth at some point.
@gcl2783
@gcl2783 2 жыл бұрын
I like the tests over the driver scripts of previous videos.
@ChrisHalden007
@ChrisHalden007 2 жыл бұрын
Great video. Would be nice to use bigger font. Very hard to watch full screen on mobile phone.
@JabmarMusic
@JabmarMusic 2 жыл бұрын
Thanks for the video. Can you tell me what Color Theme do you use?
@theunknown2090
@theunknown2090 2 жыл бұрын
Great video, more people should start teaching like you.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thank you, happy you liked the video!
@romulorff
@romulorff 2 жыл бұрын
Awesome video and very illustrative examples, love it! I noticed you were running Python 3.9 so I would have also consider to use Protocols instead of ABC, which was introduced in Python 3.8
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thank you! I’m working on new examples at the moment that rely on Protocol instead of ABCs.
@mpete0273
@mpete0273 2 жыл бұрын
Amazing videos - keep it up!
@ComputerScienceSimplified
@ComputerScienceSimplified 3 жыл бұрын
Incredible video, keep up the awesome work! :)
@ArjanCodes
@ArjanCodes 3 жыл бұрын
Thank you! Will do!
@danspeed93
@danspeed93 2 жыл бұрын
Thank you that is a nice video that goes directly in my favorites
@paulorugal
@paulorugal 2 жыл бұрын
Hey Arjan! Recently I've been diving into your videos, they're so amazing! Your knowledge is very SOLID and the references and arguments you use are very clarifying! Thank you for posting such amazing content! I started using python in 2011 and at that time people would frown when the subject was threads. Most of my peers would use Java saying the support for using threads was a lot better, do you think/plan on touching this subject? And/or even making some comments explaining if threads are helpful in the web development context or a microservices approach would be a better approach
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Hi Paulo, thank you - I'm glad you're enjoying the videos! I must admit I haven't used threads in many years. When I need asynchronous behavior, I'll generally use asyncio/Futures. But I can imagine there are still quite a few types of applications where threads are important (I just don't happen to work on those :) ). Async is a topic that's on my video list, so I'll surely cover that on the channel at some point.
@geekyboytop
@geekyboytop Жыл бұрын
Awesome explanation thank you took plenty of notes!
@ArjanCodes
@ArjanCodes Жыл бұрын
Glad you enjoyed it!
@dariuszspiewak5624
@dariuszspiewak5624 Жыл бұрын
Arjan, is it not more convenient to use pytest instead of unittest? Seems to be simpler and (maybe?) more flexible?
@Roman-kn7kt
@Roman-kn7kt 9 ай бұрын
Awesome!!!
@johnrperry5897
@johnrperry5897 3 жыл бұрын
I love your lighting!!
@ArjanCodes
@ArjanCodes 3 жыл бұрын
Thank you, John!
@vikingthedude
@vikingthedude 2 жыл бұрын
Hey Arjan, would you recomment injecting and mocking the builtin "input" function as well? How do you decide when to inject and when to just directly use an object/function?
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Hi @VikingTheDude, I'm going to release a video soon where I talk about unit testing and in particular patching and mocking. So stay tuned :).
@willz81
@willz81 Жыл бұрын
Is there a blog post explaining dependency inversion in relevance to file structure?
@LucasNaruto8107
@LucasNaruto8107 3 жыл бұрын
Your content is amazing m8!
@ArjanCodes
@ArjanCodes 3 жыл бұрын
Thanks a ton, Lucas!
@douglaspearson5741
@douglaspearson5741 3 жыл бұрын
Great Channel - Learning a lot
@ArjanCodes
@ArjanCodes 3 жыл бұрын
Thank you Douglas, glad you are enjoying the videos.
@iliqnew
@iliqnew 2 жыл бұрын
AMAZING VIDEOS! THANKS!
@agamemnonc
@agamemnonc 6 ай бұрын
Is this abstract class or "intermediate layer" as you call it an interface? If not, what's the difference between such an abstract class and an interface?
@JamesWolfisz
@JamesWolfisz 2 жыл бұрын
Not sure if your patch question was answered but you can patch __call__ of the class and return whatever you like.
@davidlayton5054
@davidlayton5054 2 жыл бұрын
Enjoyed the video. The patches are a smell for injection. It felt like you were going to inject input. Was that cut in the interest of time? It opens up so much extensibility.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Ha, well spotted. I did cut a few things out to keep it from becoming too long.
@rusbelbermudez238
@rusbelbermudez238 Жыл бұрын
Really nice videos I have learned a lot.
@ArjanCodes
@ArjanCodes Жыл бұрын
Thanks so much, Rusbel, glad it was helpful!
@simonkufeld7903
@simonkufeld7903 2 жыл бұрын
good explanation
@_hello_5346
@_hello_5346 Жыл бұрын
This is great, thank you.
@ArjanCodes
@ArjanCodes Жыл бұрын
Thank you, glad you liked the video!
@sebastianrodriguezcolina634
@sebastianrodriguezcolina634 2 жыл бұрын
Hey thanks for your videos, they are great. I have a question for this one. Is there any reason you use things like is_authorized and set_status instead of using the property decorator?
@ArjanCodes
@ArjanCodes 2 жыл бұрын
When I published this video I was not yet fully committed to Python-only on my channel, so I wanted to keep the more Python-specific things such as decorators out of the examples for simplicity. I've now moved to fully focus on Python in my channel, so you can expect to see these kinds of things appear more frequently in my upcoming videos.
@sebastianrodriguezcolina634
@sebastianrodriguezcolina634 2 жыл бұрын
@@ArjanCodes thank you! Great work 👌🏼
@ice7mayu
@ice7mayu 2 жыл бұрын
Thank you , ur vid is very helpful
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thank you, glad it was helpful!
@davidlayton5054
@davidlayton5054 2 жыл бұрын
In your unit test you use a real authorizer instance rather than a spec'd mock. I've always used mocks to reduce coupling in tests, but that often convolutes the test and sometimes the mock behavior diverges over time. So I can see the merits of using the real instance. What are your thoughts?
@ArjanCodes
@ArjanCodes 2 жыл бұрын
I didn’t use a mock for the authorizer since it is a really basic class (not much more than a mock actually). If a class is relatively simple and is more or less standalone, I don’t have any issues using instances of it directly in the test. But then I wrok at a startup where we have to move fast sometimes, so that means making sacrifices once in a while.
@enricoroselino7557
@enricoroselino7557 7 ай бұрын
so dependency injection is the way to pass a class and inversion is the interface / abstract so the passed class not tied to one specific class. noted, thank you mr arjan
@maikwiesmueller
@maikwiesmueller 2 жыл бұрын
When I saw the title i got instantly triggered by the "VS" just to find out that I love this video. So was it clickbait? Maybe, but i love it!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Glad you liked it!
@wing-keiwong9418
@wing-keiwong9418 Жыл бұрын
It looks like generate_sms() is not called as part of the new code. How will you retractor the codes so it is included when the class authorise_sms is used and excluded while authorise_robot is used?
@nocodenoblunder6672
@nocodenoblunder6672 2 жыл бұрын
I have a question. Composition is for example if a class Car has an attribute of another class ie Engine and if the outer and inner object have the same lifetime. Otherwise its an aggregate. So if each Car has the same engine by default(engine gets created in car) its not dependency injection only aggregation. If the engine is created outside of Car an is passed through init to assign to Car.engine it is both injection and aggregation. If Car has no attribute engine but uses the engine in one of its method that expects Engine it is only dependency injection. Is what I said correct?
@ATXAdventure
@ATXAdventure 2 жыл бұрын
Best programming education videos out there.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thank you so much - glad you like them!
@Sidorvm
@Sidorvm 9 ай бұрын
Nice!
@esatylmaz1476
@esatylmaz1476 2 жыл бұрын
hello, authorizer is abc and has common functions, but when I give the sms method to Payment Processor, and intellisense like authorizer.get_sms_code() does not appear, how can I provide this?
@nestorguemez4846
@nestorguemez4846 2 жыл бұрын
Excellent video
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thank you!
@k98killer
@k98killer 10 ай бұрын
Dependency inversion is then something like the maxim "couple to interfaces, not implementations".
@miquelvazquez4544
@miquelvazquez4544 2 жыл бұрын
This is really good! But a subtle point: DI/IOC is possible not only with classes but in functions. The theory is the same, the issues and benefeits are the same as well :)
@koraytugay
@koraytugay 2 жыл бұрын
Are you talking about callbacks? How do you do DI in functions?
@miquelvazquez4544
@miquelvazquez4544 2 жыл бұрын
@@koraytugay By passing the dependencies as parameters. `def notify_user_signed_up(user: User, email_service: EmailService, jwt_service: JwtService)`
@demidrek-heyward
@demidrek-heyward 3 жыл бұрын
great content thank you
@ArjanCodes
@ArjanCodes 3 жыл бұрын
Very welcome, Mathias!
@sashacooper9326
@sashacooper9326 2 жыл бұрын
As primarily a Rubyist, this feels like a halfway house to me between type checking and duck typing. I'm a big fan of duck typing wherever possible, and it seems like it would work perfectly well here - instead of creating the abstract class, I think you could just remove the assertion on PaymentProcessor that its authoriser has any particular class type? I realise that type checking is often valuable, but in cases such as this where you want something more flexible, why is dependency inversion better than just leaving the type fully open?
@alexbelov6287
@alexbelov6287 2 жыл бұрын
Thank you!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
You’re welcome!
@fmictsang8874
@fmictsang8874 Жыл бұрын
Thanks.
@dawid_dahl
@dawid_dahl 2 жыл бұрын
Thank you! 💙
@ArjanCodes
@ArjanCodes 2 жыл бұрын
You're welcome 😊
@zdzichuWentyl
@zdzichuWentyl 2 жыл бұрын
as always good work
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thank you!
@tokero5199
@tokero5199 Жыл бұрын
I'm new to python, I'm wondering why use an Abstract class for the Authorizer, why not use an interface?
@MrTulptuiz
@MrTulptuiz 2 жыл бұрын
Man you are awesome!
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Happy you like the videos!
@phaphiq
@phaphiq 2 жыл бұрын
Very good video, I will check the other you have now :-)
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Thank you Jakub!
@Korcari1
@Korcari1 Жыл бұрын
Thanks!
@ArjanCodes
@ArjanCodes Жыл бұрын
Thank you so much!
@fjolublar
@fjolublar 2 жыл бұрын
Great video but I am a bit confused. You removed the authorizer.generate_sms_code() from the actual code but you used it in the test case. You said you would go back to it but I seem to miss it. Isn’t that very important in the actual code? Where is it going to be run?
@fjolublar
@fjolublar 2 жыл бұрын
in my understanding generate_sms_code() should be called inside the authorize method
@nikolaikruglikov7358
@nikolaikruglikov7358 2 жыл бұрын
I’ve got a question: how do you decide where to put a low dash (_) in a class name? It seems that you use it as an indicator of inheritance, but it would be nice to know an exact heuristic. Thanks for your videos! I would not call myself a novice, but I am still picking something new from each video on this playlist :)
@TechLord79
@TechLord79 2 жыл бұрын
AFAIK Python is more in the "snake-case camp" ie. this is just pure convention regarding how to name things compounded of multiple words, eg. value_added_tax for a variable name in Python vs. valueAddedTax (camel-case) in C#. However, as I see from PEP8 Authorizer_SMS is not strictly to spec - it should be "CapWords", ie. AuthorizerSMS, also named Pascal-case, which eg. C# also uses for class names. (As an aside in the .NET/C# world there is also discussion about acronyms > 2 characters being cased, eg. FileIO but HttpContext not HTTPContext; though in Python, PEP8 takes a different stance: "When using acronyms in CapWords, capitalize all the letters of the acronym. Thus HTTPServerError is better than HttpServerError.") www.python.org/dev/peps/pep-0008/#naming-conventions To sum it up: Although Python has many aspects using conventions instead of language features (like leading _ or __ for internal/"private" names) in this case the class name has no special technical meaning, just personal preference/intuition of the author. HTH.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Great question, thanks. @TechLord79 already gives a pretty good overview of naming conventions in Python. I did this video already a while ago and I've since moved to a more strict following of Python's naming conventions. There is no particular reason to use the underscore here, you can just as well leave it out.
@pascalpfeiffer9088
@pascalpfeiffer9088 3 жыл бұрын
Another great video! Where can I get the picture from the background?
@ArjanCodes
@ArjanCodes 3 жыл бұрын
Thanks Pascal, that's just an image I created myself using a photo from Unsplash + added the two colors. If you send me an email at business@arjancodes.com, I'd be happy to share it with you.
@hakimbhd9736
@hakimbhd9736 Жыл бұрын
You are the best 🤩
@ArjanCodes
@ArjanCodes Жыл бұрын
Thanks so much Hakim, glad it was helpful!
@tadastadux
@tadastadux Жыл бұрын
1:10 - Dependency Injection 1:38 - Dependency Inversion
@cs-ope
@cs-ope 10 ай бұрын
You're too damn good
@davidlayton5054
@davidlayton5054 2 жыл бұрын
Great to see you solve the problem that you created by using the type system. It shows the cost of adding the type, but what is the marginal value (on top of unit tests)? The abstract class reduces the dependency to the interface the ABC defines, but if you'd not used types (and the interface was wrong) your test would just throw an attribute error that makes the issue just as clear. I honestly don't get it. Can you explain?
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Hi David, the Python interpreter completely ignores type hints - they don't have any effect whatsoever on what the code does when you run it. The main reason types are there is to provide help to the developer. Thus, types don't create problems, they make them explicit, and allow using tools like Pylance and Mypy to help you avoid mistakes while you're writing the software. I think it's a bad idea to use failing unit tests for establishing what the interface is between pieces of code. Do you really want to sift through a bunch of unit tests to figure out what kind of objects with attributes should be passed to a function as opposed to having that information clearly defined by types (which can then be automatically checked)? Finally, if you write code in a team of developers (which is probably true for many developers working on commercial software), types help establish what the interface is, and that + automatic type checking makes adding new code or refactoring existing code faster for the developers in your team.
@davidlayton5054
@davidlayton5054 2 жыл бұрын
@@ArjanCodes thanks for the response. By problem I meant the coupling. After the pendacy is injected, there's no longer any dependacy on the class beyond the annotation. I see how something like mypy is useful if you're not writing tests, but I fall to see what it adds if you are. Is there an example of a type of issue MyPy would catch that a good unit test wouldn't?
@9e7exkbzvwpf7c
@9e7exkbzvwpf7c 2 жыл бұрын
@@davidlayton5054 "Is there an example of a type of issue MyPy would catch that a good unit test wouldn't?" Yes, it is true that if you commit to having 100% test coverage static typing won't catch any errors your tests wouldn't. However, why sign up for 100% coverage and the time that entails when you can use static typing while being sure that the case of "are the types correct" is getting caught at build time?
@davidlayton5054
@davidlayton5054 2 жыл бұрын
@@9e7exkbzvwpf7c Thank you so much for your reply. I definitely see the value in what you are saying. I do TDD b/c I program a lot faster that way-- not b/c I think it is the one-true way. So I'm personally already signed up to 100% coverage. I certainly see the value in tool like MyPy.
@TheBboyism
@TheBboyism 9 ай бұрын
Is dependency inversion just Dependency Injection + Strategy Pattern?
@marcdunivan2436
@marcdunivan2436 6 ай бұрын
OOP brings a whole other level to programming. Much more than watching simple C language tutorials. I can't imaging Oracle bringing these OOP concepts to PL/SQL...or GNU Scheme...? Didn't the industry switch to Data Oriented Programming?
@selimrbd
@selimrbd 2 жыл бұрын
Is there a video where you explain the difference between a design "pattern" and "principle" ? It wouldn't shock me that dependency injection be called a "principle", same if dependency inversion was a "pattern". Is there a clear-cut difference between both or is it fuzzy ?
@ArjanCodes
@ArjanCodes 2 жыл бұрын
The way I view it is that a principle is more of a guideline, whereas a pattern is a specific solution to a design problem. In that sense, "dependency inversion" is a principle because you can apply it in many different ways, whereas the "strategy" is a design pattern, because it prescribes a specific organization of classes and methods. To draw a carpentry analogy: a design principle is "make your wooden construction such that it can support at least twice the weight of what's needed"; a design pattern is a dovetail joint.
@programminginterviewsprepa7710
@programminginterviewsprepa7710 Жыл бұрын
But how do you inject objects deeper in call hierarchy??
@Tekay37
@Tekay37 2 жыл бұрын
This might just be a minor detail, but why did you choose "1234567" as the wrong auth code. Having to know that a valid auth code has to have exactly 6 digits seems like a hurdle for understanding. Why not use an auth code like "wrong1" or "invalid"?
@MrCucolea
@MrCucolea 2 жыл бұрын
Amazing content! Creating a video about testing and mocking with pytest would be very interesting in my opinion.
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Glad you like it Robert - and thank you for the suggestion!
@PawelOlas
@PawelOlas 2 жыл бұрын
test_init couples your test to the implementation. if you decide to refactor and rename the variable to _authoriser, the test will break. IMHO you should test the public interface of the class to allow free refactoring of your implementation later. Technically "authoriser" variable is public in this example but maybe it shouldn't?
@ArjanCodes
@ArjanCodes 2 жыл бұрын
Indeed, in a production application I would definitely hide attributes behind properties or methods.
@PawelOlas
@PawelOlas 2 жыл бұрын
@@ArjanCodes I understand that you want to simplify the examples to demonstrate something but at the same time there are people learning from your code and they may think that this is what they need to do. They don't know that you do not do it in production code. I really like your lessons but as a learning resource I think the code should be perfect and production ready.
The Power Of The Plugin Architecture In Python
24:06
ArjanCodes
Рет қаралды 110 М.
顔面水槽をカラフルにしたらキモ過ぎたwwwww
00:59
はじめしゃちょー(hajime)
Рет қаралды 37 МЛН
Black Magic 🪄 by Petkit Pura Max #cat #cats
00:38
Sonyakisa8 TT
Рет қаралды 17 МЛН
Dynamic #gadgets for math genius! #maths
00:29
FLIP FLOP Hacks
Рет қаралды 18 МЛН
Dependency Injection | Prime Reacts
28:34
ThePrimeTime
Рет қаралды 284 М.
Dependency Injection простыми словами
18:17
devschacht
Рет қаралды 83 М.
Uncle Bob’s SOLID Principles Made Easy 🍀 - In Python!
19:09
ArjanCodes
Рет қаралды 282 М.
Should You Use Dependency Injection Frameworks?
14:43
ArjanCodes
Рет қаралды 39 М.
7 Python Code Smells: Olfactory Offenses To Avoid At All Costs
22:10
Do We Still Need Dataclasses? // PYDANTIC Tutorial
16:33
ArjanCodes
Рет қаралды 194 М.
Protocol Or ABC In Python - When to Use Which One?
23:45
ArjanCodes
Рет қаралды 195 М.
顔面水槽をカラフルにしたらキモ過ぎたwwwww
00:59
はじめしゃちょー(hajime)
Рет қаралды 37 МЛН