3 ms·
>Why would we assume that? If the objects are entirely distinct, why are you combining them together into one class at all? That doesn't make any sense. Let dis
by ninetyninenine 1y ago
>Why would we assume that? If the objects are entirely distinct, why are you combining them together into one class at all? That doesn't make any sense. Let distinct types be distinct. Let consumers of those types combine them however they like.
Human = torso, legs, arms. Three distinct objects combine into one thing. A human by definition is the union of these things. It's fundamental. It's just your bias is trying to see it as something else.
>So now the objects have 90% of their properties shared. That's different from what you were saying earlier. But moving on...
So? I can talk about multiple things right? This is allowed in life right? Did i break the law here?
>The composition answer is similar to the inheritance answer. Take the common parts and extract them out into a self contained type. Use that type everywhere you need it - eg by including it in both A and B.
Composition is the same thing. But it's saying instead of overriding duplicate properties, Clone the duplicate property. That's it. And it uses nesting to achieve this. This arbitrary rule isn't more fundamental then overriding the duplicate property.
>Via composition, you do it like this:
Why don't you take a look at my examples again. You are either not able to comprehend or you didn't read it. I literally said the same thing:
B = {a: A, e}
The above a complete dupe of what I wrote.
B = {a, b, c , d, e}
Just nested. Which I brought up:
B = {{a, b, c, d}, e}
Is it not? Please read my response replying with stuff like this. Read it thoroughly.
>And that's an incredibly damning criticism, because complexity is an absolute killer.
Not exactly it's not that straightforward. Because inheritance minimizes code copying. It reuses code in the most efficient way possible. So actually lines of code and duplicate code actually goes down. So complexity in one area falls and rises in another area.
Our brains are biased towards handling complexity of duplicate code better then tightly coupled code.
- josephg 1y ago> Human = torso, legs, arms. Three distinct objects combine into one thing. A human by definition is the union of these things. It's fundamental. It's just your bias is trying to see it as something else. No, it’s not. If I put a torso, legs and arms (and perhaps a head) on a table, I don’t get a human being. I’d say a human composes all of those things (and more!). But a human doesn’t inherit from them. For example, each leg can kick(). But you can’t inherit from two legs! And if you did, which leg is the one that kicks when you call the function? Much better to have human class which contains two legs. Then human can have a kick(RIGHT_LEG) function which delegates its behaviour to right_leg.kick(). There’s lots more ways composition helps us model this. Let’s say we want to model blood temperature, which is tracked in every limb separately. Composition makes it more straightforward to have different behaviour (& state) in the Body class for blood temperature than in any of the limbs. (Eg maybe the blood temperature is the average of all limbs temperature. That is more straightforward to implement with composition.) > inheritance minimizes code copying. It reuses code in the most efficient way possible. On the surface, I agree with this claim. But it’s funny - programs which make heavy use of OO always seem unnecessary verbose. I wonder why that is? I’m thinking of Java where it’s common to see utility classes that just have 1 or 2 fields take up 100+ lines of code, due to class boilerplate, custom hashCode, toString and isEqual methods and all the rest. But in any case, as you say, we aren’t just trying to optimise for the fewest lines of code. We’re trying to optimize for how easy something is to read, write and maintain. Adding code to increase simplicity is often worth it. Inheritance increases complexity because it adds a layer of hidden control flow. When I’m reading a program, I need to do a lot of work to figure out if foo.bar() is calling a function in one of the base classes or in the derived class. As you say, humans don’t deal with that kind of complexity well. In general, explicit is better than implicit - this.leg.kick() is more explicit than this.kick() when kick() exists somewhere in one (or more?) of the base classes. Also let’s say I have 3 classes A, B extends A and C extends A. If there’s a bug in B that involves something in the base class A, fixing that bug may break implicit invariants in C. This kind of “spooky action at a distance” is horrible. Ironically, it violates the principle of encapsulation that OO claims as one of its core principles. I find this kind of problem is rarer in compositional systems. And when it happens, it’s usually much more straightforward to debug and fix. The reason is because classes are all self contained. You don’t have partially-specified base classes that only kinda sorta maintain their invariants. And derived classes don’t implicitly include their base class’s behaviour. As a result, there’s less implicit entanglement. B and C can much more easily change how they wrap A’s behaviour. At the end of the day, I think we more or less agree that inheritance makes code harder to reason about. I don’t write code to express a pure conceptual representation of the world. (And neither should you!). I write code to get stuff done. If inheritance makes it harder for humans to be productive with our software, then that’s reason enough to abandon it.
- ninetyninenine 1y agoI’m not gonna read the full thing. I’m just responding to the first part. Composes or inheritance is just vocabulary for two things that are the same with slight differences. Composes duplicates identical properties via nesting. Inheritance overrides properties that are identical. That’s it. I’m done.
- josephg 1y agoMaybe that's our ultimate disagreement. I think the difference between composition and inheritance matters a lot. It changes how we break our software into modules. It sounds like you think of inheritance as being fundamentally the same as composition "with slight differences". Although even you admit that "Our brains cannot handle the complexity [of inheritance]". If that's true (and I think it is), the difference is surely more than skin deep. I agree about nesting. But nesting matters, because it forces us to design components which make sense in isolation. As a result, composition encourages - and in many ways requires - better modularity in code. Inheritance does not. Base classes are often poorly conceived, poorly specified grab-bags of state and functions. They lead to hard to understand, hard to follow code. Earlier in this thread you insulted my intelligence. You said this: > Don't ever tell me that programming for 30 years is a reason for being correct. It's not. In fact you can be doing it for 30 years and be completely and utterly wrong. Then the 30 years of experience is more of a marker of your intelligence. I'm curious if you'll still back the argument you've made here after you've been programming for 30 years too. You're clearly already suspicious of how and why inheritance makes code harder to understand. I suspect in a few years, you'll come around to my point of view on this. But I'd love to know if I'm wrong.
- ninetyninenine 1y ago>I'm curious if you'll still back the argument you've made here after you've been programming for 30 years too. You're clearly already suspicious of how and why inheritance makes code harder to understand. I suspect in a few years, you'll come around to my point of view on this. But I'd love to know if I'm wrong. I did insult your intelligence. Because when you said you have 30 years of experience I hear total arrogance. It's like "I'm right and you're wrong because I have 30 years of experience" When I hear that I just want the other person to shut the hell up. >I agree about nesting. But nesting matters, because it forces us to design components which make sense in isolation. As a result, composition encourages - and in many ways requires - better modularity in code. Inheritance does not. Base classes are often poorly conceived, poorly specified grab-bags of state and functions. They lead to hard to understand, hard to follow code. Again, you resuse the same code if you don't use inheritance. A cat walks, so does an animal, do does a dog. You have to write walk() twice if you don't use inheritance. There's a trade off here. The difference is skin deep. It's the emergent complexity that is NOT skin deep. combining objects via "object composition" or "inheritance" is different. One way is not more right then the other. It's simply that you can't handle the hierarchical relationships. But think about it. If you have a deeply nested Object where you don't use inheritance. Then all the objects have multitudes of redundant properties, doesn't that result in complex code as well? And how does nesting objects make it less complex then inheriting objects? It's more of code navigation problem in the sense that when you use inheritance and you look at a child derived from generations of inheritance it's just hard to read and figure out what the final object is. With object composition the view is the same. You have an object that holds generations of nested objects. The difference is you can control click and follow the definition of the nested object so it's more visible. Thus it seems to me the issue with the complexity is that inheritance simply does not give you a widget you can control click into easily to follow the definition. This whole problem could be characterized by a user interface issue because it's not evident to me how an object with nested objects 1000000 layers deep is more complex then the same object derived from 100000 ancestors.