Dependency INVERSION vs Dependency INJECTION in Python

Поділитися
Вставка
  • Опубліковано 24 лис 2024

КОМЕНТАРІ • 226

  • @ArjanCodes
    @ArjanCodes  3 роки тому +80

    Finally upgraded to better microphones for this video!

    •  3 роки тому +5

      It makes a huge difference!

    • @jamie9926
      @jamie9926 3 роки тому +1

      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 😉

  • @ruszkait
    @ruszkait 3 роки тому +79

    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  3 роки тому +37

      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 3 роки тому +13

      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 3 роки тому +7

      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 роки тому +1

      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 роки тому +18

      @@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.

  • @HenockTesfaye
    @HenockTesfaye 3 роки тому +16

    I like the background sayings
    "It depends"
    "Solid advice"

  • @steventimberman9313
    @steventimberman9313 3 роки тому +31

    This is the first example I've ever seen that clearly shows the motivation behind an abstract class, great video!

    • @ArjanCodes
      @ArjanCodes  3 роки тому +2

      Glad you liked it, Steven!

    • @kayakMike1000
      @kayakMike1000 8 місяців тому

      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.

  • @susmitvengurlekar
    @susmitvengurlekar 3 роки тому +81

    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 роки тому +15

      Who cares about working code! 😄

    • @vekyll
      @vekyll 3 роки тому +4

      If you write your tests properly, these two should be the same!

    • @yuriysukhorukov391
      @yuriysukhorukov391 3 роки тому +8

      @@vekyll The testing can not prove that the code works properly, it can only prove that smth goes wrong )))

    • @vekyll
      @vekyll 3 роки тому +5

      @@yuriysukhorukov391 Of course. This does not contradict what I said.

    • @digitig
      @digitig 2 роки тому

      @@vekyll You can't fully test any non-trivial code. That's why for critical software there has to be analysis as well.

  • @SurajAdhikari
    @SurajAdhikari 2 роки тому +14

    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  2 роки тому

      Great suggestions, Thank you.

  • @ojosedirceu
    @ojosedirceu Місяць тому

    Finally clarified the differences between them, Thank You Arjan!

  • @vinnyt4398
    @vinnyt4398 2 роки тому +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

  • @cetilly
    @cetilly 3 роки тому +17

    Your videos are brilliant. Just love this content. I need to watch this video a couple times to catch everything going on.

  • @NilenduDasnilendudas
    @NilenduDasnilendudas 2 роки тому +1

    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 2 роки тому

      Are ABC classes really the only way to achieve this?

    • @janekschleicher9661
      @janekschleicher9661 2 роки тому

      @@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!

  • @raki1190-y7i
    @raki1190-y7i Рік тому

    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 UA-cam). And it's very easy to retain the knowledge because now you know why's behind the logic. Great job !!

    • @ArjanCodes
      @ArjanCodes  Рік тому

      Much appreciated! Thank you very much!

  • @AlexGb007
    @AlexGb007 3 роки тому +4

    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  3 роки тому +1

      Thank you Ali, and will do!

  • @WilliamBrumble
    @WilliamBrumble 3 роки тому +4

    Well structured thorough video that includes design pattern and unit testing. Thank for sharing!

  • @AlejandroLamKhoa
    @AlejandroLamKhoa 3 роки тому +1

    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!

  • @rolandovillcaarias5112
    @rolandovillcaarias5112 Рік тому

    Finally I can see an example to understand DI clearly. Thank you Arjan for your explanation :)

  • @davidzitzmann542
    @davidzitzmann542 3 роки тому

    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!

  • @felipealvarez1982
    @felipealvarez1982 2 роки тому +2

    I was delighted to see mock and testing! Every programmer should be doing this!

    • @DerekHohls
      @DerekHohls 2 роки тому

      I missed seeing mock objects here - where were they used?

    • @felipealvarez1982
      @felipealvarez1982 2 роки тому

      @@DerekHohls I think at 4:06 and 9:49

    • @DerekHohls
      @DerekHohls 2 роки тому

      @@felipealvarez1982 Those snippets refer to "patch" not mock?

    • @felipealvarez1982
      @felipealvarez1982 2 роки тому

      @@DerekHohls patch is a convenience method for mock. Same library.

    • @DerekHohls
      @DerekHohls 2 роки тому +1

      @@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.

  • @fazzah777
    @fazzah777 3 роки тому

    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  3 роки тому +1

      Thanks! And that's certainly something I'm going to cover soon on the channel!

  • @nithyanandhasubramanya
    @nithyanandhasubramanya 3 роки тому +1

    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.

  • @andyanderson222
    @andyanderson222 Рік тому

    I absolutely love this channel! Its pure joy to watch these tutorials! Thanks a lot!

  • @taylormonacelli
    @taylormonacelli 2 роки тому

    So clear, so concise, so awesome! Thank you Arjan

  • @DeKeL_BaYaZi
    @DeKeL_BaYaZi 6 місяців тому

    You are the coolest developer ever

    • @ArjanCodes
      @ArjanCodes  6 місяців тому +1

      Thank you so much for the kind words!

  • @TheBIKEDEALZ
    @TheBIKEDEALZ 7 місяців тому

    superb.
    what should be the guideline to splitting it properly?

  • @VladimirSuravtsov
    @VladimirSuravtsov 3 роки тому +1

    Thank you for really clear and helpful explanation. Code examples are very illustrative too. Nice work!

    • @ArjanCodes
      @ArjanCodes  3 роки тому +1

      Thank you - glad you like it!

  • @ChrisHalden007
    @ChrisHalden007 2 роки тому +1

    Great video. Would be nice to use bigger font. Very hard to watch full screen on mobile phone.

  • @RichardVodden1
    @RichardVodden1 2 роки тому

    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.

  • @dmytroparfeniuk2670
    @dmytroparfeniuk2670 3 роки тому

    Best video I have seen regarding DIs. Thanks!

    • @ArjanCodes
      @ArjanCodes  3 роки тому

      Glad it was helpful, Dmytro!

  • @theunknown2090
    @theunknown2090 3 роки тому

    Great video, more people should start teaching like you.

    • @ArjanCodes
      @ArjanCodes  3 роки тому

      Thank you, happy you liked the video!

  • @ATXAdventure
    @ATXAdventure 3 роки тому +2

    Best programming education videos out there.

    • @ArjanCodes
      @ArjanCodes  3 роки тому

      Thank you so much - glad you like them!

  • @paulkuhne3855
    @paulkuhne3855 3 роки тому +1

    Extremely clear explanation. Great! Thank you!

    • @ArjanCodes
      @ArjanCodes  3 роки тому +1

      Glad you enjoyed it, Paul!

  • @muralir8504
    @muralir8504 2 роки тому

    best tutorial for advance topics

  • @gcl2783
    @gcl2783 2 роки тому

    I like the tests over the driver scripts of previous videos.

  • @romulorff
    @romulorff 3 роки тому +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  3 роки тому +3

      Thank you! I’m working on new examples at the moment that rely on Protocol instead of ABCs.

  • @AR-scorp
    @AR-scorp 3 роки тому +1

    Excellent video. Thanks for making and sharing this.

  • @brennorris7061
    @brennorris7061 2 роки тому

    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 UA-cam :) 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 2 роки тому

      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.

  • @miquelvazquez4544
    @miquelvazquez4544 3 роки тому

    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 3 роки тому

      Are you talking about callbacks? How do you do DI in functions?

    • @miquelvazquez4544
      @miquelvazquez4544 3 роки тому

      @@koraytugay By passing the dependencies as parameters. `def notify_user_signed_up(user: User, email_service: EmailService, jwt_service: JwtService)`

  • @rjgonzalez8108
    @rjgonzalez8108 3 роки тому

    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.

  • @brianakong7644
    @brianakong7644 2 роки тому

    Awesome video, explanations, and examples! Thank you!

    • @ArjanCodes
      @ArjanCodes  Рік тому +1

      Thanks so much Brian, glad the content is helpful!

  • @Jacob011
    @Jacob011 3 роки тому +3

    Turns out, I considered this common sense and used it in my code without even knowing what it is called.

  • @edgeeffect
    @edgeeffect Рік тому

    As ever, an excellent video but could I just recommend that watchers follow this up with Code Aesthetic's equally excellent Dependency Injection video.

  • @davidlayton5054
    @davidlayton5054 3 роки тому +1

    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  3 роки тому

      Ha, well spotted. I did cut a few things out to keep it from becoming too long.

  • @enricoroselino7557
    @enricoroselino7557 Рік тому

    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

  • @geekyboytop
    @geekyboytop Рік тому

    Awesome explanation thank you took plenty of notes!

  • @JamesWolfisz
    @JamesWolfisz 3 роки тому

    Not sure if your patch question was answered but you can patch __call__ of the class and return whatever you like.

  • @sashacooper9326
    @sashacooper9326 3 роки тому

    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?

  • @WMRamadan
    @WMRamadan 2 роки тому

    Is there a blog post explaining dependency inversion in relevance to file structure?

  • @Hubert4515
    @Hubert4515 3 роки тому

    super useful information about inversion and injection, thanks

  • @Lodinn
    @Lodinn 3 роки тому +1

    Great CAPTCHA 10/10 would implement

  • @sebastianrodriguezcolina634
    @sebastianrodriguezcolina634 3 роки тому +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  3 роки тому +3

      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 3 роки тому

      @@ArjanCodes thank you! Great work 👌🏼

  • @k98killer
    @k98killer Рік тому

    Dependency inversion is then something like the maxim "couple to interfaces, not implementations".

  • @davidlayton5054
    @davidlayton5054 3 роки тому

    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  3 роки тому

      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.

  • @JabmarMusic
    @JabmarMusic 2 роки тому

    Thanks for the video. Can you tell me what Color Theme do you use?

  • @paulorugal
    @paulorugal 3 роки тому

    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  3 роки тому +5

      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.

  • @danspeed93
    @danspeed93 2 роки тому

    Thank you that is a nice video that goes directly in my favorites

  • @pinakadhara7650
    @pinakadhara7650 2 роки тому

    Excellent content. Thanks a lot for making this!

  • @LucasNaruto8107
    @LucasNaruto8107 3 роки тому +1

    Your content is amazing m8!

  • @MarkWernsdorfer
    @MarkWernsdorfer 3 роки тому

    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?

  • @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 роки тому +1

      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 :).

  • @dariuszspiewak5624
    @dariuszspiewak5624 2 роки тому

    Arjan, is it not more convenient to use pytest instead of unittest? Seems to be simpler and (maybe?) more flexible?

  • @davidlayton5054
    @davidlayton5054 3 роки тому

    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  3 роки тому +1

      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 3 роки тому

      @@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 3 роки тому

      @@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 3 роки тому

      @@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.

  • @johnrperry5897
    @johnrperry5897 3 роки тому

    I love your lighting!!

  • @agamemnonc
    @agamemnonc Рік тому

    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?

  • @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!

  • @rusbelbermudez238
    @rusbelbermudez238 2 роки тому

    Really nice videos I have learned a lot.

    • @ArjanCodes
      @ArjanCodes  2 роки тому

      Thanks so much, Rusbel, glad it was helpful!

  • @MrCucolea
    @MrCucolea 3 роки тому +1

    Amazing content! Creating a video about testing and mocking with pytest would be very interesting in my opinion.

    • @ArjanCodes
      @ArjanCodes  3 роки тому +1

      Glad you like it Robert - and thank you for the suggestion!

  • @MarcDunivan
    @MarcDunivan Рік тому

    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?

  • @grif.n
    @grif.n 5 місяців тому

    Is there a reason the PaymentProcessor needs to take an authorizer argument at all instead of there being another process_order method on the Order class which authorizes the user and then takes payment? Is it because payment shouldn't be possible without authorization every time, so the strict usage of authorize inside pay method is necessary?
    Would refactoring authorize and pay to happen separately but inside a process_order method also be dependency inversion?

  • @robertbrummayer4908
    @robertbrummayer4908 3 роки тому

    Great explanation

  • @douglaspearson5741
    @douglaspearson5741 3 роки тому

    Great Channel - Learning a lot

    • @ArjanCodes
      @ArjanCodes  3 роки тому

      Thank you Douglas, glad you are enjoying the videos.

  • @wing-keiwong9418
    @wing-keiwong9418 2 роки тому

    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 3 роки тому

    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?

  • @tokero5199
    @tokero5199 Рік тому

    I'm new to python, I'm wondering why use an Abstract class for the Authorizer, why not use an interface?

  • @ComputerScienceSimplified
    @ComputerScienceSimplified 3 роки тому

    Incredible video, keep up the awesome work! :)

  • @ZanarkandStarplayer
    @ZanarkandStarplayer Рік тому

    Is dependency inversion just Dependency Injection + Strategy Pattern?

  • @mpete0273
    @mpete0273 3 роки тому

    Amazing videos - keep it up!

  • @iliqnew
    @iliqnew 2 роки тому

    AMAZING VIDEOS! THANKS!

  • @Roman-kn7kt
    @Roman-kn7kt Рік тому

    Awesome!!!

  • @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?

  • @selimrbd
    @selimrbd 3 роки тому

    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  3 роки тому +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.

  • @_hello_5346
    @_hello_5346 2 роки тому

    This is great, thank you.

    • @ArjanCodes
      @ArjanCodes  2 роки тому

      Thank you, glad you liked the video!

  • @fjolublar
    @fjolublar 3 роки тому

    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 3 роки тому

      in my understanding generate_sms_code() should be called inside the authorize method

  • @TheDefirion
    @TheDefirion 3 місяці тому

    If I understood this correctly an extra layer of abstraction is created between the Authorizer subclasses and the PaymentProcessor, where do we define which Authorizer is used? Am I missing something

    • @TheDefirion
      @TheDefirion 3 місяці тому

      I think I got it, you pass this on the test by setting each auth on the various authorizers, something that would be the case should the code is implemented

  • @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.

  • @JonMartins
    @JonMartins 3 роки тому

    Do you think the initializer test is actually needed? Aren't you testing something that belongs to the python codebase? Instances of classes should be of the expected type

  • @nestorguemez4846
    @nestorguemez4846 2 роки тому

    Excellent video

  • @PawelOlas
    @PawelOlas 3 роки тому +1

    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  3 роки тому

      Indeed, in a production application I would definitely hide attributes behind properties or methods.

    • @PawelOlas
      @PawelOlas 3 роки тому

      @@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.

  • @programminginterviewsprepa7710

    But how do you inject objects deeper in call hierarchy??

  • @simonkufeld7903
    @simonkufeld7903 3 роки тому

    good explanation

  • @ice7mayu
    @ice7mayu 3 роки тому

    Thank you , ur vid is very helpful

    • @ArjanCodes
      @ArjanCodes  3 роки тому

      Thank you, glad it was helpful!

  • @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"?

  •  2 роки тому

    A suggestion: can you please increase the font size of your IDE a little bit. It's impossible for me to watch your videos on the phone.

    • @ArjanCodes
      @ArjanCodes  2 роки тому

      I've taken care of this in more recent videos.

  • @phaphiq
    @phaphiq 3 роки тому

    Very good video, I will check the other you have now :-)

  • @Sidorvm
    @Sidorvm Рік тому

    Nice!

  • @zdzichuWentyl
    @zdzichuWentyl 3 роки тому

    as always good work

  • @tadastadux
    @tadastadux 2 роки тому

    1:10 - Dependency Injection
    1:38 - Dependency Inversion

  • @sloan00
    @sloan00 Рік тому

    Can you check subtitle in video? It seems to not support English.

    • @ArjanCodes
      @ArjanCodes  Рік тому

      Hey! Thanks for this, indeed, there was a problem, but I just fixed it! :)

  • @alexbelov6287
    @alexbelov6287 2 роки тому

    Thank you!

  • @MrTulptuiz
    @MrTulptuiz 3 роки тому

    Man you are awesome!

    • @ArjanCodes
      @ArjanCodes  3 роки тому

      Happy you like the videos!

  • @hakimbhd9736
    @hakimbhd9736 2 роки тому

    You are the best 🤩

    • @ArjanCodes
      @ArjanCodes  2 роки тому +1

      Thanks so much Hakim, glad it was helpful!