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-horvat8 ай бұрын
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 :)
@tarsala19958 ай бұрын
That's actually a template method pattern. I've done it many times, unfortunately people find that confusing
@zoran-horvat8 ай бұрын
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.
@redcrafterlppa3038 ай бұрын
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#.
@zoran-horvat8 ай бұрын
Good point.
@okcharles78 ай бұрын
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-horvat8 ай бұрын
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.
@edoreemmanuel42503 ай бұрын
Will the video out.
@codingbloke8 ай бұрын
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.
@iron_spark8 ай бұрын
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
@williamliu89858 ай бұрын
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.
@MrPipav8 ай бұрын
Awesome. I already used them pretty similarly to this example but it's always great to have it all in one place !
@alex.nolasco7 ай бұрын
"a virtual method that returns a void is a liability..."
@alexhall8408 ай бұрын
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!
@Sindrijo8 ай бұрын
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_erimez8 ай бұрын
Great video! Clearly stated, interesting and informative
@Gaming7268 ай бұрын
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-horvat8 ай бұрын
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.
@muhamedkarajic8 ай бұрын
Well explained!
@hichaeretaqua8 ай бұрын
I think in other languages these extension points are called hooks, where you can hook up your own code
@janhendrikschreier8 ай бұрын
thanks for the video and the explanations :)
@rusektor8 ай бұрын
05:20 The StartEngine method in Vehicle can be easily overridden in Car class. Moreover, it can even be made as property.
@zoran-horvat8 ай бұрын
The derived class cannot override a non-virtual method. And what is that about property?
@rusektor8 ай бұрын
@@zoran-horvat It can if you use "new" keyword
@zoran-horvat8 ай бұрын
@@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.
@vonn97378 ай бұрын
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-horvat8 ай бұрын
It is a question whether you can do that in a particular design. What if deriving from that class is legitimate?
@vonn97378 ай бұрын
@@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.
@adambickford87208 ай бұрын
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-horvat8 ай бұрын
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.
@marcobaccaro2 ай бұрын
a.k.a Template Method design pattern. Also, they could be C# events instead of abstract method.
@ingvarvd58858 ай бұрын
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-horvat8 ай бұрын
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.
@ingvarvd58858 ай бұрын
@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-horvat8 ай бұрын
@@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.
@ingvarvd58858 ай бұрын
@@zoran-horvat yes, that is a good point. If the number of such methods is big, that is a better way to do it.
@auronedgevicks77398 ай бұрын
why would you override something if you don't know how it works? isn't that the point of overridding?
@zoran-horvat8 ай бұрын
Because "how" is part of a different class, maybe? Quite formally, all you can see when overriding a method is its signature.
@auronedgevicks77398 ай бұрын
@@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-horvat8 ай бұрын
@@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.
@auronedgevicks77398 ай бұрын
@@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-horvat8 ай бұрын
@@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.
@mendeleev_9H2PDsgXu7NmphCUEH8 ай бұрын
Go next one on topic of implicit and explicit interface implementation and where NoT tO uSe ThEm)