And functional programmers would argue that contravariance is the real meaning of Liskov’s substitution principle: https://apocalisp.wordpress.com/2010/10/06/liskov-substituti...
Liskov Substitution: The real meaning of inheritance
41–50 of 92 posts
Re: Liskov Substitution: The real meaning of inheritance
#42From the article: Again, kudos to Uncle Bob for reminding me about the importance of good software architecture in his classic Clean Architecture! That book is my primary inspiration for this series. Without clean architecture, we’ll all be building firmware (my paraphrased summary). What does clean architecture have to do with building firmware or not? Plenty of programmers make a living building firmware. Just beca…
I’m in the middle of reading Clean Architecture right now. The square/rectangle example is directly from the book. The firmware statement is an argument made (differently) in the book that software is called soft because it’s easy to change. Firmware is harder to change because of its tight coupling and dependencies (to the hardware). Software that is hard to change due to tight coupling and dependencies could almost…
Re: Liskov Substitution: The real meaning of inheritance
#43Re: Liskov Substitution: The real meaning of inheritance
#44Liskov substitution will not save you. One of the worst cases of inheritance I've ever seen was in a hierarchy that was a perfect Liskov fit -- an even better fit than traditional examples like "a JSON parser is a parser". See https://news.ycombinator.com/item?id=42512629 . The fundamental problem with inheritance, and one not shared by any other kind of polymorphism, is that you can make both upcalls and downcalls w…
Disagree with your first part. Inheritance used to express Subtyping is different from that used for Code-reuse and yet again different from that used for implementing Framework skeleton structure. You have to disambiguate them carefully when using it. See the article linked to by user "Fannon" here - https://news.ycombinator.com/item?id=42789466
As for tooling, you have to enforce the contract using pre/post/inv clauses following Meyer's DbC and also explicit documentation.
Re: Liskov Substitution: The real meaning of inheritance
#45Here to recommend this article, really helped me to understand inheritance better. Liskov Substitution is just one aspect / type of it and may conflict with others. https://www.sicpers.info/2018/03/why-inheritance-never-made-...
Quote: Inheritance was never a problem: trying to use the same tree for three different concepts was the problem.
Re: Liskov Substitution: The real meaning of inheritance
#46Earlier quoted context omitted.
Just because you see OO languages starting to favor composition over inheritance does not mean inheritance has no place, and indeed, interfaces as a form of composition have existed in many bog-standard OO languages for decades. Your example dosn't compute, at least in most languages, because derived objects would not have the same shape as one another, only the shape of the base class. I.e. functions expecting a Use…
Inheritance has no place in production codebases—unless there is strict discipline, enforced by tooling, ensuring calls only go in one direction. This Liskov stuff has zero bearing.
The Liskov principle basically defines when you want inheritance versus when you don't. If your classes don't respect the Liskov principle, then they must not use inheritance.
The problems from your story relate to the implementation of some classes that really needed inheritance. The spaghetti you allude to was not caused by inheritance itself, if was caused by people creating spaghetti. The fact that child classes were calling parent class methods and then the parent class would call child class methods and so on is symptomatic of code that does too much, and of people taking code reuse to the extreme.
I've seen the same things happen with procedural code - a bunch of functions calling each other with all sorts of control parameters, and people adding just one more bool and one more if, because an existing function already does most of what I want, it just needs to do it slightly different at the seventh step. And after a few rounds of this, you end up with a function that can technically do 32 different things to the same data, depending on the combination of flags you pass in. And everyone deeply suspects that only 7 of those things are really used, but they're still afraid to break any of the other 25 possible cases with a change.
People piggybacking on existing code and changing it just a little bit is the root of most spaghetti. Whether that happens through flags or unprincipled inheritance or a mass of callbacks, it will always happen if enough people are trying to do this and enough time passes.
Re: Liskov Substitution: The real meaning of inheritance
#47> class Square : Rectangle() { ... What if instead of Rectangle class we would have ReadonlyRectangle and Rectangle? Square could then inherit from ReadonlyRectangle, so code expecting only to read some properties and not write them could accept Square objects as ReadonlyRectangle. Alternatively if we really want to have only Square and Rectangle classes, there could be some language feature that whenever you want to…
Re: Liskov Substitution: The real meaning of inheritance
#48Liskov substitution will not save you. One of the worst cases of inheritance I've ever seen was in a hierarchy that was a perfect Liskov fit -- an even better fit than traditional examples like "a JSON parser is a parser". See https://news.ycombinator.com/item?id=42512629 . The fundamental problem with inheritance, and one not shared by any other kind of polymorphism, is that you can make both upcalls and downcalls w…
Re: Liskov Substitution: The real meaning of inheritance
#49Do yourself a favor and wear yourself off all this SOLID, Uncle Bob, Object Oriented, Clean Code crap. Don't ever use inheritance. Instead of things inheriting from other things, flip the relationship and make things HAVE other things. This is called composition and it has all the positives of inheritance but none of the negatives. Example: imagine you have a school system where there are student users and there are…
Never using inheritance is pushing the dogma to the other extreme imo. The whole prefer composition over inheritance is meant to help people avoid the typical OO over use of inheritance. It doesn't mean Is-A relation doesn't/shouldn't exist. It just means when there is data, prefer using composition to give access to that data. There will be times when you want to represent Is-A relationship - especially when you wan…
Re: Liskov Substitution: The real meaning of inheritance
#50Earlier quoted context omitted.
I see no need for inheritance there, that can and should be done using interfaces eg in the contrived example I gave, any of all three of the User, Student and Employee can implement the interface (and if needed Student could simply delegate to its internal User while Employee could "override" by providing its own, different implementation)
What difference do you see between implementing an interface and inheriting from a class, that makes one good and the other bad? I'm asking beyond the arbitrary distinctions that some languages like Java or C# bake in.