Live data from Hacker News

Inheritance Often Doesn't Make Sense

sicpers.info

81–90 of 255 posts

Re: Inheritance Often Doesn't Make Sense

#81

The programmer's perspective: The phrase 'object-oriented' means a lot of things. Half are obvious, and the other half are mistakes. - Paul Graham. Implementation inheritance causes the same intertwining and brittleness that have been observed when goto statements are overused. As a result, OO systems often suffer from complexity and lack of reuse. - John Ousterhout Scripting, IEEE Computer, March 1998. The problem w…

Another quote:

------------------

The No True Scotsman fallacy leads to arguments like this:

Person A: “No Scotsman ever steals.”

Person B: “I know of a Scotsman who stole.”

Person A: “No True Scotsman would ever steal.”

Person A is thus protected from the harmful effects of new information. New information is dangerous, as it might cause someone to change their mind. New information can be rendered safe simply by declaring it to be invalid. Person A believes all Scotsman are brave and honorable, and you can not convince them otherwise, for any counter-example you bring up is of some degraded Untrue Scotsman, which has no bearing on whatever they think of True Scotsman. And this is my experience whenever I argue against Object Oriented Programming (OOP): no matter what evidence I bring up for consideration, it is dismissed as irrelevant. If I complain that Java is verbose, I’m told that True OOP Programmers let the IDE take care of some of the boilerplate, or perhaps I am told that Scala is better. If I complain that Scala involves too much ceremony, I’m told that Ruby lacks ceremony. If I complain about the dangers of monkey-patching in Ruby, I’m told that True OOP Programmers know how to use the meta-programming to their advantage, and if I can’t do it then I am simply incompetent. I should use a language that is more pure, or a language that is more practical, I should use a language that has compile-time static data-type checking, or I should use a language that gives me the freedom of dynamic typing. If I complain about bugginess, I’m told that those specific bugs have been fixed in the new version, why haven’t I upgraded, or I’m told there is a common workaround, and I’m an idiot if I didn’t know about it. If I complain that the most popular framework is bloated, I’m told that no one uses that framework any more. No True OOP Programmer ever does whatever it is that I’m complaining about.

http://www.smashcompany.com/technology/object-oriented-progr...

Re: Inheritance Often Doesn't Make Sense

#82
> Abstract data type inheritance is about substitution: this thing behaves in all the ways that thing does and has this behaviour (this is the Liskov substitution principle)

There is no such thing as “inheritance” for abstract data types, because inheritance is a syntactic relation between two definitions (which needn't be type defintions, by the way!). Abstract data types may be related by subtyping, although IMO this is hardly ever useful. What you actually want to refine is abstractions (of which abstract types are merely constituent parts).

> As a type, this relationship is reversed: you can use a rectangle everywhere you can use a square (by having a rectangle with the same width and height), but you cannot use a square everywhere you can use a rectangle (for example, you can’t give it a different width and height). Notice that this is incompatibility between the inheritance directions of the geometric properties and the abstract data type properties of squares and rectangles; two dimensions which are completely unrelated to each other and indeed to any form of software implementation.

There are valid arguments against inheritance, but this is not one. In fact, this argument has nothing to do with inheritance at all! All that this says is “if the type variable T only appears in contravariant position in F(T), and A is a subtype of B, then F(B) is a subtype of F(A)”. Moreover, this is not an argument against subtyping either. It's just the description of how to handle it correctly. It appears in any standard PL semantics or type theory textbook.

Here is a real argument against inheritance: “Try formalizing the semantics of a toy language with inheritance. Try proving things about a couple toy programs using this semantics. Note how the proofs about what your superclasses do often make a lot of unwarranted assumptions about how subclasses will use or override inherited functionality. These assumptions couple not only the interfaces (which is okay), but also the implementations (which is not okay) of superclasses and subclasses. This is the antithesis of modularity.”

Re: Inheritance Often Doesn't Make Sense

#83
post #72

Earlier quoted context omitted.

> if you ask me for any rectangle, and you reject a square, you are wrong No, no: "If you ask me for any object that can have independent width and height, and you reject a Square, you are..." right, of course. It depends on the properties that define what a Rectangle and a Square are in your code.

Which is another way of saying that the domain model is what determines the properties of polygons that actually matter. You may have two classes, Square and Rectangle, and they may be mutually incompatible because you need to represent the shape of a hole and the shape of a plug. In that case your square isn't compatible with a rectangular shape even though it's a type of rectangle. I think the author is saying that…

> Fancy type systems are not a substitute for understanding the thing you're reasoning about.

And now you got me wondering about all the times I wrote a Haskell type, some bugged code, mindlessly changed code until the compiler stopped complaining, and it worked flawlessly.

But I guess your comment was about that "writing the types" stage. There were a few times I mindlessly wrote them too based on where they would be used (I could have the compiler give me them, but I'm not used to it). I can remember a few times I did both on the same functions, mindlessly write the types and the implementation.

Re: Inheritance Often Doesn't Make Sense

#84

I took over the maintenance and enhancement of a customer's eCommerce site. It's written in Python, using an ancient framework - Pylons. The person who originally designed and wrote it, coded large super classes and then subclassed off those. And then somtimes subclassed off those subclasses. So now I'm lost in a maze of twisty classes/subclasses, which makes maintaining and enhancing this eCommerce site much, much m…

I agree. I never find myself with a scenario in which inheritance is useful. I actually started writing a lot of Go (which has no inheritance support) and haven't missed inheritance at all. It really seems like useless complexity.

Re: Inheritance Often Doesn't Make Sense

#85

Earlier quoted context omitted.

> and you can't just will it to have a different width and height and expect it to obey you through some force of nature I think you have let functional programming and immutable data-structures bias your world view. The real world is mutable and the wonder of the digital mutable world is that it is pretty much just will-alone that can set attributes as you describe. It is immutability that is a trendy but artificial…

> The real world is mutable Only if you ignore time. It's not possible to change the state of the world at some previous instant (as far as our understanding of physics is concerned). The mutable world model is an artificial construction that aligns with our human perception.

If you're modeling the world, you can do so immutably. If you're interacting with the world (I.e., I/O), then you cannot.

Re: Inheritance Often Doesn't Make Sense

#86
post #77
post #72

Earlier quoted context omitted.

> if you ask me for any rectangle, and you reject a square, you are wrong No, no: "If you ask me for any object that can have independent width and height, and you reject a Square, you are..." right, of course. It depends on the properties that define what a Rectangle and a Square are in your code.

This matches my experience: ontological inheritance gets in the way. What we actually want is traits . What can something do , not what it is .

This seems like structural subtyping? Are these synonyms?

Re: Inheritance Often Doesn't Make Sense

#87
post #42
post #18

Earlier quoted context omitted.

I didn't get that from the article at all. I actually like what the article is doing a lot, and I wish people would take the same approach more often. When arguments about high-level concepts like inheritance go poorly, it's usually because everyone involved is talking about something slightly different. Maybe a supporter of inheritance likes the way it lets them think about their program (ontological inheritance) wh…

The problem balancing implementation vs ontological inheritance while providing strong type safety is that your language needs to either support defining contravariant types (and you still likely end in a mess, see Scala's eternal discussion about "total" type safety), or you disallow ontological inheritance completely (like Golang, and therefore cannot support many modern programming features, for the better or wors…

> or you disallow ontological inheritance completely (like Golang, and therefore cannot support many modern programming features

Sincerely, what features does this preclude. I pretty much ignore ontological inheritance in any programming language because it never seems useful. Am I missing something?

Re: Inheritance Often Doesn't Make Sense

#88
post #9

A couple of other comments have argued that "ontological inheritance" and "abstract data type inheritance" are actually the same thing: > This is because Squares are Liskov substitutable for Rectangles... which is because Squares are, platonically, a kind of Rectangle. > If the type system is sound and expressive enough, ontological inheritance ( this thing is a specific variety of that thing) and abstract data type…

Yes! The thing that ends up breaking in the squares and rectangles examples is mutability. Remember that math things are immutable by default. This thing is a square, and by definition also a rectangle, and since its properties and identity are immutable, that will always be true.

However, programming takes those immutable concepts and tends to make them mutable. So now we have a rectangle, and we can change its identity by, say, scaling its width. And it's obvious that scaling just the width of a square will make it no longer a square. So now a square cannot support the same operations that a rectangle can. So now a square is no longer Liskov-substitutable for a rectangle.

Re: Inheritance Often Doesn't Make Sense

#89
post #21
post #9

A couple of other comments have argued that "ontological inheritance" and "abstract data type inheritance" are actually the same thing: > This is because Squares are Liskov substitutable for Rectangles... which is because Squares are, platonically, a kind of Rectangle. > If the type system is sound and expressive enough, ontological inheritance ( this thing is a specific variety of that thing) and abstract data type…

I always find that the common example of Rectangles and Squares leads me to a different conclusion. It assume that the best way to go about is to only have a single sideLength method, but from a data structure perspective it seems more obvious that the Squares class substitute instead the validation method by adding constraints that a valid square only exist when both sides are equal. Rectangle class must already hav…

But then both are just a kind of polygon, with an arbitrary number of sides of arbitrary length.

At which point you really want a variable length list of Sides, each with a length property.

Or you want a series of points with relative coordinates, making the sides implicit.

Or or or...

What I take from it is that there is no one true object model, there is no universally "correct" way of solving the problem. An evolving understanding of the problem leads to an evolving solution that places different priorities on different attributes.

Is there any value provided to the system by making Square a specialisation of Rectangle? Is there value in being able to express a Square without a redundant attribute value? What is the tradeoff? And so on.

Re: Inheritance Often Doesn't Make Sense

#90
post #38

Unless your program's goal is to ontologically categorize objects, #1 is a trap that will just bite you in the ass. In the physical world, if I have a rectangle shaped box I want to cover, I don't want a square, no matter how much "squares are rectangles". It's no different in a program. What really matters is the behavior and goals of your program. It's cute to say squares are rectangles but if your program needs to…

> Unless your program's goal is to ontologically categorize objects, #1 is a trap that will just bite you in the ass.

Strangely, ontological inheritance isn't even useful for that purpose. If you're organizing things ontologically, you certainly want to have runtime access to the relationships in your ontology, which means you should model things as data, not static class relationships (although reflection can turn static class relationships into data, it's a pretty hokey, indirect solution).

Post reply on HN