Depend on Abstractions not Concretions (Framework)

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

КОМЕНТАРІ • 154

  • @janvanwijk5979
    @janvanwijk5979 7 місяців тому +27

    Now THIS is how you teach a complex topic like DIP: energetic, clear, to the point, and with humor. Bravo 👏

  • @nullcheque
    @nullcheque 7 місяців тому +30

    Your teaching style is optimally concise. I have lightbulb moments with every video I watch from your channel. Bravo!

    • @ChristopherOkhravi
      @ChristopherOkhravi  7 місяців тому +1

      Wow. Thank you for the kind words. 😊🙏 I'm happy to hear that. Will try my best to keep improving.

  • @detaaditya6237
    @detaaditya6237 7 місяців тому +21

    Man, I think this video is the best explanation for DIP

    • @ChristopherOkhravi
      @ChristopherOkhravi  7 місяців тому +5

      Thank you very much for the kind words 😊🙏. To be fair, this video doesn't cover all the intricacies of DIP, but (imho) most of them 😊

  • @ungus
    @ungus 7 місяців тому +10

    Some of your videos are review for me, some are new ways to look at problems, but I always learn something new and become a better engineer.
    Thank you for your work.

    • @ChristopherOkhravi
      @ChristopherOkhravi  7 місяців тому +1

      I’m very glad to hear. Thank you very much. And thanks to you all for the things that you are teaching me along the way 😊🙏

  • @agzapiola
    @agzapiola 4 місяці тому +2

    Your return to YT is a blessing!

  • @EhsanIrshad
    @EhsanIrshad 7 місяців тому +18

    You are the legend.... many Pakistanis and indians are revamping your videos. and contributing to the society to make the object oriented inclusions at the grass root level to lift up naive programmers... You are Great sir.. hats off....

  • @Sheda_Vedne
    @Sheda_Vedne 29 днів тому

    I've probably said this before, but you're just THE BEST, I really appreciate what you do!

  • @FreeStyleKid777
    @FreeStyleKid777 7 місяців тому +1

    It's funny how I had no idea how all these frameworks are called, but I use them everyday. But I love it how well you presented them. And I finally get it why you would use interfaces :)). Thank you!

    • @ChristopherOkhravi
      @ChristopherOkhravi  7 місяців тому +2

      I'm very happy to hear that it resonates with the way you are thinking. Thank you for sharing and for watching! 😊🙏

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

    That understanding of change in behavior than data, made me get it very clear that the conditional for behavior change in Player is where a subtype polymorphism should be used. I now can read conditionals in a sane way than before where I used to worry about every switch and if statements.

  • @coolbrotherf127
    @coolbrotherf127 7 місяців тому +2

    Using abstraction in general great. People shouldn't feel like they should have to build everything from scratch. Using good code already out there will save people a lot of time and effort. I see people who feel like they are bad programmers because they have to use libraries and tools made by others to complete their projects, but there's nothing wrong with not knowing every detail of how the abstraction was created. No one knows everything about programming and everyone has weak spots and stuff we've never worked with before. Just trust that if you need to figure it out, you can, but don't worry about it unless you have to.

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

      Imho I think you are very right and I think that you are raising a very important point. Perhaps I should even make a video on this. Lemme think about it. It's important to me that I don't contribute to causing more stress in the world. Thank you for sharing 😊🙏

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

    Can't wait for you to finish your series on SOLID principles.

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

      Next video to drop is a video on LSP. Currently editing. Thank you for commenting and for watching 😊🙏

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

    This is so good. I can't stop watching.

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

    One of the best explanations of Dependency Injection I've ever come across. Thank you.

    • @ChristopherOkhravi
      @ChristopherOkhravi  7 місяців тому +1

      Glad it was helpful! Thank you for watching 😊🙏

  • @maccsguitar
    @maccsguitar 7 місяців тому +2

    Begin from top left and refactor towards bottom right as you need it, otherwise you end up with a lot of unnecessary boilerplate you ain't gonna need (YAGNI), and in some cases even might lift statically detectable errors into the runtime. This is a tooling problem but still happens a lot in real code.
    Also if it is the wrong abstraction in the beginning, which new code usually is, you'll end up reinforcing the wrong abstraction early on in the calling code. In the beginning we usually need to switch the big parts of the implementation a couple of times, in which the concretions win every time.

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

      I always start with concrete implementation. I rewrite to abstraction only if necessary. Furthermore I came to a point where I implement requirements driven and not framework driven. At the end it always fulfills a business need. Doesn't solve every problem but it makes some implementations less hard than thinking in patterns first.

  • @gergeswageh9453
    @gergeswageh9453 4 місяці тому

    Really very impressive!
    The way you explain and put things together helps me understand why and when everything exists. Thank you bro and keep up the good work👏👏

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

    As a self thought qa engineer I always struggled with truely understanding DIP. I knew it must be great since people put so much emphasis on it and in the case of Unit testing I could see its benefits. But now finally after watching this video I feel like it truelt clicked. My brain really needed to see these 4 quadrants together to truely understand the topic. Thanks

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

      Very happy to hear that. Thank you for sharing these details 😊🙏

  • @GamalElkomy
    @GamalElkomy 7 місяців тому +2

    Thanks for the video. Also, thank you for recommending these books. It really helps the viewer to get deeper in the topic when you mention the resources.

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

    This is absolute gold, you are really good at teaching ! Thanks

  • @sanjaycs89
    @sanjaycs89 7 місяців тому +1

    My favourite tech youtuber 😍

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

    Your teaching style and knowledge is exceptional. Please make some videos about functional programming design patterns.

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

    Fascinating!
    Please record a video of demonstrating this in JavaScript

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

    Fantastic demonstration of how these principles are implemented. Thank you!

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

    Great video. The book Dependency Injection: Principles, Practices, and Patterns is one I've recommended to colleagues. It really digs deep on the topics and helped me supercharge my engineering skills.

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

    As always you explain a tough concept in such an easy way. Thanks thanks thanks so much for contributing for a better software engineering world. Your videos should be a reference in all the CS colleges around the world.

  • @luckoor
    @luckoor 5 місяців тому

    i love this guy as a tutor :D

  • @kraxkrix135
    @kraxkrix135 7 місяців тому +1

    It's a really good video, but 2 question emerges:
    A: If its not Round who constructs Player 0 and 1, then who does?
    B: If there are multiple strategies to implement a Player then who decide what implementation is used?
    Abstraction looks good on paper, but if the base problem is complicated (ex: today's micro-services architecture), then it can only ease the process of creating something, that eventually has to be refactored, for reasons that was not part of the original architecture...
    So, sometimes messy is actually good because its easy to adjust, while organized is harder to update because new requirements go against the existing architecture.

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

      To create the objects you will need another pattern, creation pattern, You can use a factory or a builder, the idea now is that the creation of the objects goes to another class and you can abstract it from the code explained in the video., i was expecting him to mention that in the video.

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

      @@JuniorMoreiraC His video "WHY Waterfall Doesn't Work" and "They Knew Waterfall Didn't Work" describes what I mean. So as long as your problem is "Simple" or "Complicated" it's all good to use abstraction. Once the problem in question is more on the "Complex", and "Anarchy" side, I would use minimal or no abstraction. If u manage to tame your problem to "Simple" or "Complicated" that's the point where u can use all that is described above. I know it's a theory video, but I miss this important caveat.

  • @michaldivismusic
    @michaldivismusic 7 місяців тому +1

    If you're sure there will be no need for polymorphism as there's only one thing, staying in the upper right corner is fine (IMO).

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

    I am following and learning a lot from your lectures. It is absolutely great and a true joy to follow. Keep it up and thank you very much!

  • @smathlax
    @smathlax 5 місяців тому +1

    Great video!
    How would you handle this if you had more than one condition though? Suppose that, in a more complicated game, the moves that a player is allowed to do (and how they do them) are dictated by a multitude of variables. So first we again have the "bool isHuman" parameter. Maybe in an RPG game a barbarian moves slowly so they can only move up to 10ft per move, but a wizard is fast so they can move 20ft per move, so perhaps we have a paremeter for what "class" (barbarian, wizard, rogue, etc.) the player is. Also, maybe the player has a "bool canSwim" parameter, which will determine whether they can move through water.
    How would you balance all of these with this idea of abstracting to interfaces? Surely we wouldn't have a HumanBarbarianCanSwimPlayer class, as well as ComputerRogueCannotSwimPlayer, as well as all the other possible combinations.

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

    Nicely articulated, Great video.

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

    Absolutely. Around more than 10 years ago, inheritance used to be the way to go. Now, after almost 20 years, it is much too rigid and has massive overhead - and dependencies. Interfaces that are injected by the application engine offers simpler designs. It also allows for much simpler enhancements. Adding an operation that only takes minutes without needing to care much about hard dependencies offers so much more.

  • @yonishachar1887
    @yonishachar1887 7 місяців тому +5

    The goal is to achieve design that will be easy to modify and build other features upon.
    A "problem" with all the designs shown is that we always treat 2 players instead of a List which would be a pain to refactor if in the future we wanted to have 2v2 rounds for example.
    BUT, coding for such flexibility from the beginning might be overengineering! Such flexibility is not easy to work against, and nobody promises you that 2v2 rounds would ever be required.
    This is where YAGNI rule comes and the considerations are different in every situation.
    In summary: Great video, but beware of overengineering because you can waste weeks on something that... gained almost zero benefits from the abstraction layers you made (Personal Experience)

    • @khatdubell
      @khatdubell 7 місяців тому +2

      Yagni is one of my favorite principals.
      Everywhere I’ve worked pretty much, there is always too much trying to anticipate future ideas that never happen.

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

      @@khatdubell I know, especially when you are a solo developer working on a personal project. I never worked in the industry before, but I guess when you have a deadline... it will not be so easy to over abstract your code lol

  • @mathboy8188
    @mathboy8188 5 місяців тому

    Excellent description of the situation!

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

    Thanks a lot! This and the other videos are great. Nice to see more content coming up.
    Can be adopted to any OO-Language .... really well done.
    Passing lots of data around instead of objects is one of the top topics in ABAP Coding ....

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

    Loved this, it enlightened me with Dip.

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

    I'm so glad you are making videos again! Thanks

  • @ioanntza22dev
    @ioanntza22dev 2 місяці тому

    Great Tutorial!!! Just great! 👏👏👏👏👏👏

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

    Im glad you're back

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

    Great content and very neat and clear presentation, keep it up

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

    I have never thought these in this framework. Like it. thank you

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

    Great video and wonderfully explained!

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

    I set the speed at 0.75. But the previous videos about patterns I was consuming at 1.5-2 probably.
    I want to hear your thoughts fast as it is, but I need pauses to compare to my experience and digest. I suggest making fast speech and longer pauses between sentences, like, 1-2 sec at least

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

      Ah, good point. Thank you very much for the detailed feedback. Much appreciated 😊🙏

  • @Tynach
    @Tynach 5 місяців тому

    I really like your teaching style, and find your videos to be fairly good at getting the point across in a concise and easy to understand way.
    However, most of these seem to be very focused on object oriented programming, which is something I've started to move away from in favor of data-oriented programming. One of the core tenants of data-oriented programming is that data and behavior should be separated, rather than encapsulating the two together.
    While it makes less sense for Tic-Tac-Toe (which can only have 2 players, and the game board has such an extremely limited set of possible states), for more complex games my instinct would be to not have 'HumanPlayer' or 'ComputerPlayer' classes at all, but instead to have an array of all the names of the players (probably just called 'Players'), and two arrays with indices into that array.. One labeled as 'HumanPlayers' and the other 'ComputerPlayers'.
    Assuming game logic runs on the server and multiple clients connect to said server, sending their player's input, then there'd just be two 'for' loops. One would iterate over every player in 'HumanPlayers', passing the input from the clients into a function that calculates game logic. The other loop would iterate over every player in 'ComputerPlayers', but instead of receiving input from a client it would run a function that calculates what that input would be, and then feeds the output of that function into the game logic function.
    Of course, the game's state would be accessible from within said functions (both the function that calculates computer moves, and the function that calculates game logic). Maybe a global, or maybe both functions require another parameter for the state object. Or perhaps all of these are in the same 'Game' class and can see a 'Game.state' object that holds the internal state of the current game.
    Actually, thinking about it a bit more, perhaps it'd be even better if instead the first loop simply calculated what the 'input' from the computer players would be, and adds them to the same pile of inputs from the players that was collected from the connected clients... And then the second loop iterates over 'Players' (that is, the array with all the players) and processes all of their input all at one time.
    It's 3 AM and I should go to bed.

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

    as usual a great watch and awesome breakdowns

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

    great explanation!! expecting more videos like this❤️

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

    Absolutely amazing contact.
    Respect

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

    Good to see you doing your thing bro ❤

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

    Simply the best

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

    Well explained

  • @IsaacC20
    @IsaacC20 7 місяців тому +1

    I find material on DI and abstraction lacking. They never specify that at some point, there *must* be concretions and *something* must manage the concretion's lifetime.
    At some point, *something* needs to perform the object construction: of Rounds, Humans, and Computers, and *something* needs to determine which IPlayer concretions are paired with specific Round concretions.
    *Something* also needs to decide how to destroy those concretions.
    So follow-up question: is it objectively better to always push the responsibility of concretion creation and arrangement "downwards" towards the base of the call stack?

    • @ChristopherOkhravi
      @ChristopherOkhravi  7 місяців тому +1

      Great question. Thank you 🙏😊 I will try to address this issue in detail in a future video. But the gist of it is: push instantiation "outwards" (btw I would refer to this as "upwards" rather than "downwards" but I can see that we mean the same thing so the wording doesn't really matter here) AND use factories (Factory Method Pattern or Abstract Factory Method) to delay instantiation that need additional run-time information (such as a say a choice from the user about what kind of Round to start. See what I mean?

    • @NuclearBurntHam
      @NuclearBurntHam 4 місяці тому

      ​@@ChristopherOkhravi I was going to ask the same question. I would love to see a video from you on this topic!
      Thank you for all your efforts making A+ content!

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

    You are just so good at this! Thank you so much!

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

      Thank you for the kind words and for watching 😊🙏

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

    Awesome work. I love getting these notifications.

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

    whenever i do OOP I think it is the best to implement
    Dependency Injection+Dependency Inversion + factory design pattern

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

    Greetings from Germany. I love you!

  • @helloword3544
    @helloword3544 2 місяці тому

    Replace conditions with polymorphism definitely makes sense, but at the first glance I thought, let's encapsulate that code (if/else of object creation) and use factory method pattern to create Player objects and then inject those to Round class constructor. Would it be an acceptable design ? 🤔

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

    Awesome explanation! Thanks a lot

  • @IndeterminateMetal
    @IndeterminateMetal 5 місяців тому

    It’d be interesting to hear about the trade off, often times you don’t need unlimited reuse, so the right would offer the greatest ease of usability by end code consumer without them having to know anything about the architecture. Downside code alterations would be painful

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

    Great video.

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

    Awesome video. Perhaps you speak a bit too fast in the beginning and that may make it a bit difficult to understand the problem.
    Anyhow, these are things that I have learned through experience and pain, like having to maintain code which contains lots of conditionals depending on the class subtype, which are clearly bad design smells.
    Thanks for explaining these things so well so it's possible to understand and identify them.

  • @GB-nn2cx
    @GB-nn2cx 7 місяців тому

    Awesome 👍

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

    Amazing explanation! TicTacToe in it's elegant way. What are your thoughts about Golang?

    • @ChristopherOkhravi
      @ChristopherOkhravi  7 місяців тому +1

      I'm happy you find it useful. I have to look deeper into Go to have a proper opinion. Will try to make a video on it when I have explored it much deeper 😊. Thank you for asking 😊🙏.

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

    You are amazing, Thank you so much 😍

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

    Yess sir! ❤ Many thanks.

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

    This is super. Thank you!

    • @ChristopherOkhravi
      @ChristopherOkhravi  7 місяців тому +1

      And thank you for watching and commenting 😊🙏

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

    if IPlayer is generic class what changes we would need to make? Let’s say we have some methods that takes generic input and output types in IPlayer

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

    Wow you are amazing!!

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

      I'm happy it is useful. Thank you for watching 😊🙏

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

    ... woah 🤯 great stuff!

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

    Thank youg, great content. But then don't we simply move the instantiation to somewhere else? What if the instantiation logic is based on some calculation that is done deep in this chain?

    • @ChristopherOkhravi
      @ChristopherOkhravi  7 місяців тому +1

      Great question. Thank you 🙏😊. You are entirely right. We are simply moving the instantiation "outwards" ("upwards") towards the "main entry point" of the application. The point of this is to colocate as much of the instantiation as possible. I.e. in as few places as possible. You are also entirely right that sometimes instantiation requires logic that needs to be performed deeper in the chain at run-time. I will try to address this issue in detail in a future video but the gist of the solution is that we then use factories (Factory Method Pattern or Abstract Factory Method). That would allow us to delay instantiation that need additional run-time information (such as a say a choice from the user about what kind of Player to use in a Round). See what I mean?

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

      @@ChristopherOkhravi Thank you for the detailed answer!

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

    Great explanation indeed, but the remaining question is: When will you instantiate the objects? This has to happen somewhere, right? One cannot have infinite levels of abstraction...

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

      The short answer is: in Main and in Factories. The long answer is that i will try to address this in a future video 😊😊 Thank you very much for watching and for asking 😊🙏

  • @thales-maciel
    @thales-maciel 7 місяців тому

    each abstraction generates a need for someone to externally provide an implementation at the end of the day. so use them, but do know when to stop.

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

    So what If I want to instantiate classes with constructor based on user input?

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

    By the way love your teaching style though

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

    I still remember your snake 🐍game. You're cool.

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

    Is this video a programming lesson or a life lesson?

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

    Omg you engineers just love to put fancy names to everything.
    But really you're not reducing the complexity by applying those principles. You're just moving around where things get done and putting pretentious names to everything 😂
    Top left you have:
    Round
    Player
    Bottom right yoy have
    Round
    IPlayer
    HumanPlayer
    ComputerPlayer
    Injector
    Something to configure the game settings
    How is the second option simpler than the first one? Is, at best, different. Depending on the scope of such project it'll make more sense one approach or other IMO.
    Nonetheless is a very good explanation. I'm loving all your videos so far. Thank you for them!

  • @nashitmashkoor
    @nashitmashkoor 7 місяців тому +2

    But even after this type of architecture, there is still a place, where the objects have to be created. So instead of solving the problem. Are we in reality not just passing up the problem. In this example it seems as if it solves everything. But lets it was a much bigger system, with many more abstractions wouldn't the problem still exist ?

    • @ChristopherOkhravi
      @ChristopherOkhravi  7 місяців тому +4

      Yes. Sorry for not being clear enough. We are not removing instantiation. We are pushing it “outwards” so that all instantiation happens in as few places as possible. Thank you very much for watching and for the comment 😊🙏

    • @mortenbork6249
      @mortenbork6249 7 місяців тому +2

      If you think of a class, temporarily as a variable. It is clear that all variables required to complete a task, must be present and creating the instance of all variables is required.
      That said, how your code uses those variables is the "problem" we are examining here.
      All instances are likely needed. (Unless it's a mistake)
      If you don't tell your depending classes that the parameters they get are of a certain type, but of a "contract" that can do something, but whatever this contract says, is dependent on the actually implementation of said contract, you can pass down many different types of parameters, not just a specific type.
      Which is where for example he says player human, is a contract iPlayer and player computer is also.
      Now if you want to add player computer easy, player computer average, player computer hard.
      You would literally only have to write those concrete implementations. The rest of the system doesn't need to be touched at all.
      No tests required for the untouched code. (Only their original tests are required)
      You don't have to adapt existing code bases to have a switch for easy, medium or hard)
      It's whstever player you instantiated.
      Also. There is no duplication of logic. You don't need to revise all the code in your switch cases when you add "extreme" difficulty for example.
      your code requires less maintenance.
      It is much simpler to write automated tests for.
      Any concrete implementation, would use interfaces for dependencies. So no matter your implementation count on an interface, you would only ever need a single set of unit tests for that implementation.
      Because everywhere it's used, it's referenced by abstraction(interface)
      This means: when you introduce new classes, you only need to touch the "factory" object. Where it is instantiated, and the actual implementation itself. All other written code remains untouched.
      When you have low coupling, you have to modify all tests, and all coupled classes when you introduce a new instance.
      It's the difference between having to write a multiple of tests pr dependency, to an addition of tests pr dependency.
      Your code base becomes much smaller.

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

      You're right that in some sense we're only deferring the problem of instantiation to a different place. But doing this has many benefits. To mention a few:
      - the fewer places where your objects get instantiated, the fewer places you need to change when the constructor changes
      - when components accept their dependencies as abstract arguments to their constructor, it is easy to customize their behavior and reuse them across the system without having to change their code (or the code of their dependencies)
      - when a component has explicit dependencies that it doesn't instantiate itself, the tests for said component become simpler because you don't also have to cover the functionality of the dependencies in the test (you would need to do that if the component is responsible for creating the dependencies)
      - when you delegate responsibility for certain tasks to a dependency, your own behavior becomes simpler and more focused
      Dependency injection doesn't shield your system from the need to instantiate components, but it does shield your individual components from that need, which makes it much easier to design small, reliable, and reusable components that are easy to test and straightforward to reason about.

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

      I had this exact same question!

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

    ahhh shit now i have to refactor a bunch of code thank you (:

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

    What are the cons of "Depend on Abstractions, not Concretions" ?

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

      It can lead to overengineering if you take it too far.
      Think of projects where literary every class has a separate interface. Even if there will only be 1 implementation ever.

    • @Tynach
      @Tynach 5 місяців тому

      It's hiding implementation details. Whether or not you abstract away the implementation details, you still have to put them _somewhere_ in the end... And when you hide them in multiple layers of abstraction, it can become a huge mess to figure out what a codebase is actually doing in the background.

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

    Brilliant man, I just used Injection and build something with Quad 4, Just didn't know what is the term for the concept!

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

    Next up is abstraction of round and using a builder pattern to bring the two concepts together. A factory could build an abstract round (Round robin, randomised round) then assign players to that round ( two or more) that then gets returned to a game coordinator. Maybe even make a round slightly immutable so that after a play it's winner is recorded but never changed and forms part of a linked list to produce a history of rounds to document the game moves...

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

    Thank you very much for your videos! Can you please talk a little bit slower? I usually watch your videos at 0,75 speed to be able to keep up.

    • @ChristopherOkhravi
      @ChristopherOkhravi  7 місяців тому +1

      Thank you very much for letting me know. Will try to figure out a solution that keeps all sides happy. 😊🙏

  • @МухиддинМахмудов-б5щ
    @МухиддинМахмудов-б5щ 7 місяців тому

    hi 🤗

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

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

    dude, this is a banned commercial of rust programming language and why to use it. traits and trait bounds in a nutshell.

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

    Your final best solution should probably be using an array of IPlayer because some games can use more than two players. Also, this would allow reuse of some of the code in other applications. Lastly, the Round class is probably converting the players into an array anyway to use array methods to help with looping.

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

    to fast for me

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

    Meow

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

    as always with this oop bullshit, no real world examples, only contrived examples, no actual real code, no metrics to tel that this 'framework' is better than any other way of programming.
    ew

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

      Thank you very much for the feedback. I appreciate your alternative perspective. Which part of the example is it that you find contrived? I interact a lot with university students and this very much resembles code that I see in real life all the time.
      I certainly agree that I’m not presenting any metrics here. It’s merely a tool for those of us who find that organization of ideas is helpful when we’re trying to make sense of different ideas 😊
      Thank you for your comment again 😊🙏

    • @lorenzolimoli
      @lorenzolimoli 7 місяців тому +1

      This has nothing to do with 'frameworks'. These are concepts that every programmer should understand before using any kind of tools that automates these processes.
      Also, these principles are agnostic of every programming language or development platform.
      He clearly demonstrates what benefits we get by using Dependency Inversion and Dependency Injection principles. And these should be always taken in consideration when designing softwares, with or without external frameworks.
      I understand that watching an use case example written with real code on an IDE could have solved certain doubts like "Where the injection happens?", but I guess this wasn't the aim of the video, and also there isn't a valid answer for each case, but it depends on the use case you are trying to implement.
      I think these contents have a lot of value for the coding industry, cause I met too many developers focusing just on using the "right" technology, or framework, or library, without understanding that if you learn these stuffs, you are going to improve your analytic skills for matters of code design that can be used in every context.

    • @khatdubell
      @khatdubell 7 місяців тому +1

      Your lack of ability to see potential applications of theory to practice is not a failure of the teacher, its a failure of the student..
      You want practical application?
      Unit testing.
      Try unit testing _anything_ more serious than a wet fart without dependency injection and/or interfaces.

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

      @@khatdubell ah yes, the good old 'i dont have to prove my statements, you have to disprove them'... cause youre feeling entitled today i guess.
      and what can't you test without dependency injection ? can you give me an example ?

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

      ​@@ViolentFury1
      "ah yes, the good old 'i dont have to prove my statements, you have to disprove them'."
      Not what i said. Allow me to clarify.
      I said you don't have the intellect needed to see the benefit. Hope that's clearer. I was just trying to be nice.
      "Can you give me an example?"
      Yes, yes i can. But i've dealt with your type before. You'll find something to nitpick about it. Something to make a "no true scotsman fallacy".
      But here you go, baby bird:
      class NotificationManager {
      public:
      void notifyUser( std::string_view message) {
      EmailService emailService;
      emailService.sendEmail(userEmail, message);
      }
      }
      Please, explain how you'd test this with this hard-coded hidden dependency.
      Oh, wait, i almost forgot, you aren't going to. You're going to find something to nitpick about it to say its an invalid example. _sigh_ , so boring.