Live data from Hacker News

When did people favor composition over inheritance?

sicpers.info

171–180 of 218 posts

Re: When did people favor composition over inheritance?

#171
In Eiffel we have multiple inheritance. It's such a powerful tool. And a natural way to model the world. For example if you think of your typical OOP book You have Vehicles with engines * cars that move on roads * planes that move on air * and boats that move on water.

But then comes an aqua-plane and it breaks your inheritance tree!

But with multiple inheritance is the most natural thing to have a plane that is also a boat and a car.

In Eiffel we favor the appropriate tool that better represents the world.

Re: When did people favor composition over inheritance?

#172
post #70

Earlier quoted context omitted.

I dunno. It's easy to say, "there are trade-offs, it depends" any time two things are compared, and it's never entirely untrue. However, sometimes one option is just generally worse than the other. I'm not saying it's malpractice to use inheritance or anything, but it's a tool I definitely hesitate to reach for. Go and Rust removed inheritance entirely, and I'd say those languages are better-off without it.

Rust removed inheritance only for the Rust ecosystem to generate some kind of half-inheritance system by sticking macros on everything. For every `extends Serializable`, Rust has a `#[derive(Serializable)]`. Superclasses are replaced by gluing the same combinations of traits together in what would otherwise be subclasses, with generic type guards. The problems with bad design don't go away, they're just hidden out of…

But classes are a really crap way to share code, since you get the is-a relationship rather than the has-a relationship which is almost always what you want to express. Rust traits and derive macros are a much better abstraction for everything I've ever done when contrasted with classes.

Re: When did people favor composition over inheritance?

#173
post #79

Earlier quoted context omitted.

The problem in Rust is that if B is inside of A, struct A { name: String, owned: B } struct B { name: String, } you can't have a writeable reference to both A and B at the same time. This is alien to the way C/C++ programmers think. Yes, there are ways around it, but you spend a lot of time in Rust getting the ownership plumbing right to make this work.

It's kind of crazy that OOO is sold to people as 'thinking about the world as objects' and then people expect to have an object, randomly take out a part, do whatever they want with it and just stick it back in and voila This is honestly such an insane take when you think about what the physical analogue would be (which again, is how OOP is sold). The proper thing here is that, if A is the thing, then you really only…

It's not crazy at all, especially since majority of programming is about digitalization of real world things/processed.

eBay, Tinder, Youtube, Robinhood, etc, etc.

Those are all real world things that are now represented in digital world and adjusted for that.

Also "world" doesn't imply "physical", but that's different matter.

And at the end of the day that was not wildly crazy, but wildly successful!

Such school of thinking enabled generations of software engineers who created all this digital world.

Re: When did people favor composition over inheritance?

#174

In Eiffel we have multiple inheritance. It's such a powerful tool. And a natural way to model the world. For example if you think of your typical OOP book You have Vehicles with engines * cars that move on roads * planes that move on air * and boats that move on water. But then comes an aqua-plane and it breaks your inheritance tree! But with multiple inheritance is the most natural thing to have a plane that is also…

There's some OO design fallacy here but not sure what to call it.

The reason the aqua-plane broke the inheritance tree is because the modeling is being done backwards.

Objects should be defined by behaviour first and only incidentally contain whatever state is required to support that behaviour.

A well designed object is much more similar to a closure than it is to a data structure.

Re: When did people favor composition over inheritance?

#175
post #81

Earlier quoted context omitted.

> And that is not remotely the case here. Isn't it? People have written extensively about why we should prefer composition to inheritance, and you haven't mounted any defence of inheritance beyond the thought-terminating cliché that it "has its place."

- Wording uses “prefer”, not “forbid”. - (java) Least interesting example to rebuke “never”: exceptions, interfaces. - (java) inheritance is used by active and successful projects (e.g. junit5, spring framework). I would argue that success is a pragmatic vindication criteria of a tool/technology.

True; I suppose I could concede the idea that inheritance has its place if we recognize that that place is quite small and out-of-the-way. My problem is that "everything has its place," without any qualifications, is effectively a blank cheque to use inheritance anywhere and then just go, "well that was its place."

Interfaces are great; I wouldn't consider them inheritance.

Sure, good stuff has been written with inheritance, but good stuff has been written with C, and that doesn't make C unproblematic. If Postgres were being written today, the authors would probably choose something other than C—we just have better, safer languages for that kind of work now.

Re: When did people favor composition over inheritance?

#176

I've been building gui applications for the past 20 years and I couldn't imagine doing it without an inheritance model. There's so much scaffolding needed to build components and combine them into a working view. Sure inheritance can be bad in the data layer because you don't want to handcuff yourself to bad data expectations. But building out views and view controllers, there's a lot of logic you don't want to keep…

And yet somehow the Zed team managed to do it with gpui and rust.

https://github.com/zed-industries/zed/blob/main/crates/gpui/...

GPUI is a great example of the insane amount of boilerplate needed to create a component when you don't have inheritance.

My guess is that people don't create a lot of individual components in this framework to handle different business cases, and instead overload a single text input component with a million different options. I would hate to untangle a mature app written under those conditions.

Re: When did people favor composition over inheritance?

#177
post #89
post #81

Earlier quoted context omitted.

> And that is not remotely the case here. Isn't it? People have written extensively about why we should prefer composition to inheritance, and you haven't mounted any defence of inheritance beyond the thought-terminating cliché that it "has its place."

I use both where choosing what I believe is appropriate for particular case. Frankly I do not give rat's ass about what "People have written extensively". From what I read most of it sounds like spoken by politician: look Jimmy, someone can do a bad thing with it. Well fuckin don't do a bad thing. So much over very simple and primitive thing: John HAS a key vs dog IS an animal. Both are valid and proper. >"you haven'…

> So much over very simple and primitive thing: John HAS a key vs dog IS an animal. Both are valid and proper.

I don't think so. "Having" vs "being" are descended from an overly simulationist notion of program design. The fact that John has a key in real life does not suggest that this relationship should be represented by an object John which owns an object Key. I think this kind of ontological approach is behind a lot of bad object-oriented design.

> Architecture astronauts do it and I am not one of those

This is the same rationale used to defend memory-unsafe languages. I like that as a point of comparison because we can actually measure the relationship between the use of memory-unsafe languages and the number of dangerous memory vulnerabilities that show up even in highly-scrutinized code bases like the Linux kernel. "I write good code" doesn't fly; bad code is getting written, and the tools we have to correct that are our languages and paradigms.

> Why would I bother. It does not need a defense.

If we take our craft seriously, we need to be able to discuss the merits and drawbacks of our tools without getting defensive and refusing to engage. I'm not saying you have to defend it to me—I'm just some guy online—but if you're disinterested in defending it in general, I think that's a craft issue.

Re: When did people favor composition over inheritance?

#178
post #161

My personal preference for composition over inheritance is that it forces callers to call the owned-object’s methods directly rather than automatically through inheritance. There is more typing/boilerplate but when you read the class file you get a full picture of what’s happening rather than some parts happening automatically in a different file. I like to say that code should be written with a reader bias: the sing…

I call it "read-optimized code". Inheritance is biased toward conservative writing. Once your mind becomes so enmeshed with the code base that you can no longer fathom a future where you might fall out of sync with it, inheritance becomes extremely appealing. It's all in your head! You pull the Razzle parent, sprinkle a bit of Dazzle mixin, everything is alchemized into a Fizzle class and abracadabra. Meanwhile newbies in the team have their eyes welling up from having to deal with your declarative mess.

Re: When did people favor composition over inheritance?

#179
post #70

Earlier quoted context omitted.

I dunno. It's easy to say, "there are trade-offs, it depends" any time two things are compared, and it's never entirely untrue. However, sometimes one option is just generally worse than the other. I'm not saying it's malpractice to use inheritance or anything, but it's a tool I definitely hesitate to reach for. Go and Rust removed inheritance entirely, and I'd say those languages are better-off without it.

Rust removed inheritance only for the Rust ecosystem to generate some kind of half-inheritance system by sticking macros on everything. For every `extends Serializable`, Rust has a `#[derive(Serializable)]`. Superclasses are replaced by gluing the same combinations of traits together in what would otherwise be subclasses, with generic type guards. The problems with bad design don't go away, they're just hidden out of…

Java serialization is implemented with reflection, not inheritance. `extends Serializable` is just a marker which tells the serializer it's okay to serialize a class. Go serializes with reflection too, and there's no inheritance at all in that language.

> Rust's solution is more powerful, but also leads to more unreadably dense code.

Instead of reflection, Rust does serialization with code generation. Java does this too sometimes in libraries like Lombok. The generated code is probably quite dense, but I expect the Java standard library reflection-based serialization code is also quite dense. In both cases, you don't have to read it. `extends Serializable` and `#[derive(Serializable)]` are both equally short. And the generated code for protobuf serialization (which I have read) is pretty readable.

Re: When did people favor composition over inheritance?

#180

Earlier quoted context omitted.

It's kind of crazy that OOO is sold to people as 'thinking about the world as objects' and then people expect to have an object, randomly take out a part, do whatever they want with it and just stick it back in and voila This is honestly such an insane take when you think about what the physical analogue would be (which again, is how OOP is sold). The proper thing here is that, if A is the thing, then you really only…

It's not crazy at all, especially since majority of programming is about digitalization of real world things/processed. eBay, Tinder, Youtube, Robinhood, etc, etc. Those are all real world things that are now represented in digital world and adjusted for that. Also "world" doesn't imply "physical", but that's different matter. And at the end of the day that was not wildly crazy, but wildly successful! Such school of…

Wildy successful does not mean a good idea.

> Such school of thinking enabled generations of software engineers who created all this digital world.

Same could be said for imperative or functional programming for that matter.

Post reply on HN