Learn C#: Abstract or Virtual Method, Which Fits Better Here?

Поділитися
Вставка
  • Опубліковано 19 лют 2024
  • Become a sponsor to access source code ► / zoranhorvat
    Join Discord server with topics on C# ► codinghelmet.com/go/discord
    Enroll course Beginning Object-Oriented Programming with C# ► codinghelmet.com/go/beginning...
    Subscribe ► / @zoran-horvat
    Do you know how to design a base class so no derived class can add a bug to it later? Does this sound like dark magic? Let it be so!
    It is a lesson that so many young programmers learn the wrong way: that of applying class inheritance. If you trust mainstream books, you should specialize a class by deriving from it and overriding virtual methods. Sure, but that will take you down the spiral of endless bugs. Welcome to the realm of real-world programming!
    Watch this video to learn a better way of doing inheritance - the way safe from bugs, misunderstandings, and confused calls.
    The class design technique you will learn from this video is based on abstract methods and virtual methods with empty bodies in the base class. The base class will stand responsible for the order and validation of specialized parts of its operation implemented in the derived class.
    Once you master this technique, you will never make a bug caused by overriding. Not because you will be smarter than you are now but because you will be designing classes with no place left to put a bug into them!
    ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
    👨 About Me 👨
    Hi, I’m Zoran, I have more than 20 years of experience as a software developer, architect, team lead, and more. I have been programming in C# since its inception in the early 2000s. Since 2017 I have started publishing professional video courses at Pluralsight and Udemy and by this point, there are over 100 hours of the highest-quality videos you can watch on those platforms. On my UA-cam channel, you can find shorter video forms focused on clarifying practical issues in coding, design, and architecture of .NET applications.❤️
    ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
    ⚡️RIGHT NOTICE:
    The Copyright Laws of the United States recognize a “fair use” of copyrighted content. Section 107 of the U.S. Copyright Act states: “Notwithstanding the provisions of sections 106 and 106A, the fair use of a copyrighted work, including such use by reproduction in copies or phono records or by any other means specified by that section, for purposes such as criticism, comment, news reporting, teaching (including multiple copies for classroom use), scholarship, or research, is not an infringement of copyright." This video and our youtube channel, in general, may contain certain copyrighted works that were not specifically authorized to be used by the copyright holder(s), but which we believe in good faith are protected by federal law and the Fair use doctrine for one or more of the reasons noted above.
    #csharp #dotnet #objectorientedprogramming
  • Наука та технологія

КОМЕНТАРІ • 49

  • @GiovanniCostagliola
    @GiovanniCostagliola 3 місяці тому +4

    This coding pattern, that personally advocate, empowers the Liskov Principle into the design of the base class: this is one of the most valuable aspect (IMHO)

    • @zoran-horvat
      @zoran-horvat  3 місяці тому +2

      I totally agree.
      It is funny that someone else tried to explain to me that this implementation is violating LSP. Luckily, the guy quoted something that has nothing to do with LSP in between repeatedly using the word "overwriting" for what was probably meant to be overriding :)

  • @tarsala1995
    @tarsala1995 3 місяці тому +5

    That's actually a template method pattern. I've done it many times, unfortunately people find that confusing

    • @zoran-horvat
      @zoran-horvat  3 місяці тому +4

      It is, but it is also an individual design principle, so I chose to do separate videos on abstract methods and the Template Method pattern.

  • @okcharles7
    @okcharles7 3 місяці тому +6

    That's what hit me on my head when I use life-cycle methods of UI frameworks; some of them require calling base method before and some don't. These days many of documents adds, "base does nothing".
    I though it was design mistake but didn't know what really went wrong.
    Thanks for great advice.
    By the way, I strongly recommend the Udemy course as top must for c# beginners and intermediates as well.

    • @zoran-horvat
      @zoran-horvat  3 місяці тому +4

      Many people have learned this lesson the hard way. I remember the days when libraries didn't follow this principle consistently and programmers who used them would make random bugs, sometimes the ones that are hard to diagnose. I believe that the situation is much better today and that library makers have learned this lesson well.

  • @redcrafterlppa303
    @redcrafterlppa303 3 місяці тому +4

    4:35 that statement is incorrect for Java. You can prevent overriding by marking the method final. It's just opt out instead of opt in like c#.

  • @alexhall840
    @alexhall840 3 місяці тому +2

    This is what I have always done, always felt wrong to have to call the base method to me. So easy not to realise it has to be called!

  • @codingbloke
    @codingbloke 3 місяці тому +3

    That was excellent. I thought I had a good handle on OOD but that was a revelation. Avoid virtual methods that have side-effects. I'm going to be looking at my existing code with new scrutiny.

  • @williamliu8985
    @williamliu8985 3 місяці тому +1

    Indeed, I often encounter the need to consider whether to call the implementation of the base class in the inherited class, and how to place it. Thanks for sharing this.

  • @iron_spark
    @iron_spark 3 місяці тому +1

    Great Video - I really like your points in the slides of 'safe inheritance'
    I feel this video really gets to the heart of the problem of bugs that are a pain to fix because it will require a re-write that may affect lots of other classes

  • @MrPipav
    @MrPipav 3 місяці тому +1

    Awesome. I already used them pretty similarly to this example but it's always great to have it all in one place !

  • @alex.nolasco
    @alex.nolasco 2 місяці тому +2

    "a virtual method that returns a void is a liability..."

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

    This is what a prefer, if a public method is overridable it should either be an abstract method or it should not and the pattern demonstrated here should be employed, as it retains control over its own side effects and designated order of state change.
    Unfortunately my teachers at uni all those years ago did not appreciate this, this is one reason that OOP is often controversial as many many people have been led down the wrong path.
    Most inheritance hierarchies rarely if ever need to be deeper than 3 or 4, at that point you should seriously consider composition instead.
    BaseAbstract/IBaseInterface
    BaseAbstract
    Concrete/Concrete
    ConcreteDerived
    WhatAreYouDoingAtThisPoint

  • @esra_erimez
    @esra_erimez 3 місяці тому +1

    Great video! Clearly stated, interesting and informative

  • @muhamedkarajic
    @muhamedkarajic 3 місяці тому +2

    Well explained!

  • @janhendrikschreier
    @janhendrikschreier 3 місяці тому +1

    thanks for the video and the explanations :)

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

    Good video. I think you should have made the Car class "sealed". Allowing someone to derive from Car will put you back to where you started.

    • @zoran-horvat
      @zoran-horvat  2 місяці тому

      It is a question whether you can do that in a particular design. What if deriving from that class is legitimate?

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

      @@zoran-horvat If Car is not sealed, then someone can create "class SportsCar : Car". Should they call base.AfterEngineStart() before or after their implementation, or never? There may be a legitimate case for deriving from Car, but doing so will lose the safeguards from your design pattern.
      Your video raises good points, which are easy to overlook. It shows some more pitfalls of inheritance.

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

    I think in other languages these extension points are called hooks, where you can hook up your own code

  • @Gaming726
    @Gaming726 3 місяці тому +1

    That is a great solution for a single level of inheritance. However as soon as I get to a second level of inheritance I'm back to the original problem. Which would then mean that in my Level 1 class I need to define another hook. Actually four hooks. Which leads to alot of clutter. So if you know that you'll only have one inheritance level go for it, otherwise there is not really a point.

    • @zoran-horvat
      @zoran-horvat  3 місяці тому +5

      That is true, but you will have other problems to deal with the very moment you introduce the second level of inheritance. This issue would be the minor one.
      Multiple levels of inheritance almost invariably mean that you have missed the opportunity to transform inheritance into composition when you should have, and now you are struggling to survive.

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

    05:20 The StartEngine method in Vehicle can be easily overridden in Car class. Moreover, it can even be made as property.

    • @zoran-horvat
      @zoran-horvat  3 місяці тому +2

      The derived class cannot override a non-virtual method. And what is that about property?

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

      @@zoran-horvat It can if you use "new" keyword

    • @zoran-horvat
      @zoran-horvat  3 місяці тому +3

      @@rusektor That is not overriding, that is shadowing - a very suspicious and generally useless practice.
      Definitely not polymorphic as virtual methods are. It is not possible to invoke a shadowed member through a base type reference, even though it references a derived type instance.

  • @adambickford8720
    @adambickford8720 3 місяці тому +1

    Feels like it needs more oop. Shouldn't the whole before/during/after 'hooks' be some kind of object that defines and enforces that behavior? Then the parent class is just a container of these 'lifecycle' aware state operations. Of course, now we need some kind of chain/factory to manage all those...

    • @zoran-horvat
      @zoran-horvat  3 місяці тому

      There should be a justification for that inspection. Of course, it is applicable to some problems, and even preferable. But again, there must be a justification.

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

    I would like to see how you would code something like the WPF framework using composition rather than inheritance. 🤔🤔 ... there is a lot of inheritance going on there

    • @zoran-horvat
      @zoran-horvat  3 місяці тому

      For that kind of analysis, I would strongly suggest you too see how ASP.NET For is implemented. By the time the team was ready to take that great task, their approach had already shifted towards composition.

  • @lucifer-look-
    @lucifer-look- 3 місяці тому +1

    If memory serves me, it is a template method pattern

    • @zoran-horvat
      @zoran-horvat  3 місяці тому +1

      Yes, it is, and this video is laying out the reasons behind its existence.
      You could accomplish anything the Template Method does without it, only relying on virtual methods, but at the expense of added complexity in the derived class and the ever present danger of making bugs.

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

    Leaving empty virtual methods in the base class is unsafe. It is a source of potential bugs if someone decides to add something there later. They should be abstract and the derived classes are guarded from such changes.

    • @zoran-horvat
      @zoran-horvat  3 місяці тому

      There is nothing to add later, that is the point. You design those methods to be empty and only implemented in derived classes. If you added stuff to such a method, that would mean you didn't understand your own plan.

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

      @zoran-horvat well, if it is a one man project... but in projects with dozens of programmers, that method can be changed by someone who did not write it initially, months later after it was written. Especially if this abstract class is deployed in a library for third party users

    • @zoran-horvat
      @zoran-horvat  3 місяці тому +2

      @@ingvarvd5885 Come on, you cannot possibly make such a blunder and point fingers to the class. I think I was very precise in the video that when the number of such hooks becomes unpleasantly large, then you can opt to turn them into empty virtual methods, hence reducing the size of the derived class.
      You will find that implementation in numerous libraries and almost invariably in UI libraries where it is common for UI controls to define dozens of extension points. Would you require a custom control to override 50, 60, 70 methods only to implement two of them, and justify it with a possibility of letting a clueless programmer create mess in the BCL at the unknown time in the future? Sometimes you need to use sense when making decisions.

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

      @@zoran-horvat yes, that is a good point. If the number of such methods is big, that is a better way to do it.

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

    Go next one on topic of implicit and explicit interface implementation and where NoT tO uSe ThEm)

    • @zoran-horvat
      @zoran-horvat  3 місяці тому

      Actually, some of those are already in the queue.

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

    why would you override something if you don't know how it works? isn't that the point of overridding?

    • @zoran-horvat
      @zoran-horvat  3 місяці тому +1

      Because "how" is part of a different class, maybe? Quite formally, all you can see when overriding a method is its signature.

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

      @@zoran-horvat then you shouldn't override it. This is how bugs are made because most people are sloppy programmers. The point of override is usually to provide a NEW implementation, but sloppy programmers use it to "piggyback" on the default implementation to add redundant things like BEFORE/AFTER processing. If you have to call the base class it's a sign you are being sloppy or lazy or both.

    • @zoran-horvat
      @zoran-horvat  3 місяці тому +1

      @@auronedgevicks7739 I think you are wasting your wisdom on the channel where there is nobody who makes decisions to listen to you - except me, of course, but I know your fallacy, so you are wasting ink, so to say. Why don't you go talk to the teams who designed large libraries with these principles built into their code and try to explain to them how sloppy, lazy, or both they are. That will show you down.

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

      @@zoran-horvat Don't be so shortsighted. Engagement is a good thing. The more discussions you get on your videos the quicker it will grow. Expecting everyone to accept and consume your ideas is a bit weird tho I must say... and you're not the only dev youtuber in my feed unfortunately.

    • @zoran-horvat
      @zoran-horvat  3 місяці тому +2

      @@auronedgevicks7739 Yeah, but are just wrong. Even the very definition of C# as component-based language, and the consequences on how C# code is compiled goes against your ideas. Calling me lazy, sloppy, short-sighted...will not make that right.

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

    2:45sec in almost fallen asleep