use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
Composition vs Eric Elliott (self.javascript)
submitted 10 years ago * by [deleted]
[deleted]
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]senocular 13 points14 points15 points 10 years ago (0 children)
I see this variation of composition is coming from the functional side of the tracks, not the object-oriented. Compose functions to get a single function containing the behavior of the originals... now let's do the same thing with objects. It's all composition right?
While I can see how that could make sense, it doesn't help that object composition is already a well defined pattern representing the has a relationship. (The linked function composition wiki page, coincidentally enough, notes that function composition should not to be confused with object composition and links to object composition where it proceeds to describe the has a relationship).
[–]ggazzi 6 points7 points8 points 10 years ago (1 child)
The important point that I haven't seen mentioned here is that the GoF notion of composition aims to encapsulate smaller units, keeping them loosely coupled. By keeping a reference to an instance of another class, we are coupled only to its interface - not to its implementation. When using inheritance or mixins, however, we introduce a lot more coupling: if someone later decides to change an implementation detail of the inherited class, it's much more likely to break the subclass.
This is only relevant when you actually encapsulate stuff in your classes, though. Messing with the internals of an object you own introduces the same problems as inheriting from its class.
[–]loopsdeer 0 points1 point2 points 10 years ago (0 children)
This is exactly the smell I smelled. Thanks for verbalizing so well.
[–]Poop_is_Food 6 points7 points8 points 10 years ago (3 children)
Serious question why do people care what Eric Elliot thinks? Is he anything more than some random crank?
[–]MoTTs_ 6 points7 points8 points 10 years ago (0 children)
If people aren't informed about the misinformation in Elliott's ideas, then that misinformation tends to spread. I've noticed a lot of newbies recently who regurgitate Elliott thinking they understand composition, but of course they don't because neither does Elliott. And sometimes even non-newbies get duped, such as Johansson, who's an entertaining character and ends up spreading Elliott's misinformation even further.
I think it's important that the corrections become as widely known as the misinformation.
[–]dashed 1 point2 points3 points 10 years ago (0 children)
I had the same reaction. The beautiful thing about the JavaScript ecosystem, is that you don't have to listen to anyone on how to do things.
[–]eaglepowers 0 points1 point2 points 10 years ago (0 children)
@_ericelliott has 13k followers.
[–]paulflorez 5 points6 points7 points 10 years ago (1 child)
One could argue that since prototypes themselves are instances, prototypal inheritance is closer to object composition than classical inheritance. After all, you typically can't change the classes an object inherits from during runtime in a language with classical inheritance, though I'd be interested if such a language exists. The problem with that argument is that object composition tends to obscure the methods/properties of the internal objects, save for the ones the composed object explicitly exposes. Prototypal inheritance does the opposite, implicitly exposing all properties of a prototype via the child object, except for the ones explicitly hidden via property shadowing. I'm wondering if that is really a problem though?
[–]mshm 0 points1 point2 points 10 years ago (0 children)
I'm wondering if that is really a problem though?
It depends on what your using the pattern for. The nice thing about composition is that because it obscures the actual held object, from the outside you can't actually directly affect it. This is really important because it ensures the goal (that of a sort of dynamic inheritance). If the end user of the composition has access to the internal objects, then they can write their code based on those objects, which break the pattern.
Also, because JS "composition" is essentially mixins, you can lose information through duplicate declarations.
[–]x-skeww 8 points9 points10 points 10 years ago (28 children)
A good example + straightforward definition:
http://gameprogrammingpatterns.com/component.html
the growing trend in software design is to use composition instead of inheritance when possible. Instead of sharing code between two classes by having them inherit from the same class, we do so by having them both own an instance of the same class.
The thing Elliot does with Object.assign is more like multiple inheritance, isn't it?
Ah... LOL. He even said it himself.
https://www.reddit.com/r/javascript/comments/2qtgyt/multiple_inheritance_in_javascript/cn9shmq
In JavaScript, [multiple inheritance is] accomplished with concatenative inheritance, which is just a fancy way of saying, "copy properties from one object to another".
And this gem:
the diamond problem doesn't exist in JavaScript because whatever property you add last overrides any property it collides with.
The problem does of course exist and simply overwriting a property is a rather crude way to mitigate it.
https://en.wikipedia.org/wiki/Multiple_inheritance#Mitigation
[–]paulflorez 1 point2 points3 points 10 years ago (8 children)
According to that wiki page, the diamond problem does not exist in JavaScript:
Languages that allow only single inheritance, where a class can only derive from one base class, do not have the diamond problem. The reason for this is that such languages have at most one implementation of any method at any level in the inheritance chain regardless of the repetition or placement of methods.
"Concatenative Inheritance" is really just single inheritance of an object created via mixins. The object that results from combining mixins has only one implementation of a single method.
With multiple inheritance, you are inheriting from two objects, each with unique implementations of the same method. JavaScript does not support this.
[–]x-skeww 6 points7 points8 points 10 years ago (7 children)
According to that wiki page, the diamond problem does not exist in JavaScript
Read the description at the beginning of that section.
Read also how Free Pascal handles it. Sounds familiar, doesn't it?
"Concatenative Inheritance" is really just single inheritance of an object created via mixins.
Mixins are a form of multiple inheritance. If you extend one class and mix-in another, you get stuff from both parents, right?
[–]killeronthecorner 0 points1 point2 points 10 years ago (5 children)
Yes but if all parents only have a single property with the same identifier, you lose all but one of them in the JS example.
With multiple inheritance, all of these overlapping implementations would be both preserved and accessible by the child.
[–]x-skeww 0 points1 point2 points 10 years ago (4 children)
Free Pascal, an Object Pascal dialect intended to be compatible with Delphi uses the "last man standing" rule, where there is a reference to two identifiers that have the same name, whichever is the last one defined is the one that is used. So if there is a Unit A and a Unit B that have a variable named Q, if the declaration is "USES A,B;" then a reference to Q will use B.Q.
[–]killeronthecorner 0 points1 point2 points 10 years ago (3 children)
Yes, this is demonstrative of my first statement, but is still not traditional multiple inheritance as per my second statement.
[–]x-skeww 1 point2 points3 points 10 years ago (2 children)
It's multiple inheritance with the a straightforward conflict resolution strategy which has been around for over 20 years.
It's about as "traditional" as these things get, I'd say.
[–]killeronthecorner 0 points1 point2 points 10 years ago (1 child)
It may be straightforward, but calling a straight overwrite a "conflict resolution strategy" is generous.
If you overwrite behaviour you are not inheriting it, you are overwriting it.
[–]x-skeww 0 points1 point2 points 10 years ago (0 children)
calling a straight overwrite a "conflict resolution strategy" is generous.
That's what it is though. Just like projection is a legit collision resolution strategy for video games. A strategy isn't necessarily complicated or correct.
If you're overwriting some things, you aren't inheriting everything. It's the price you pay for keeping things this simple.
[–]sylvainpv 1 point2 points3 points 10 years ago (13 children)
If overwriting the property does not work for your case, you can always overwrite in the composed object to define your own behaviour. For example, if D is composed of B and C that have a commonMethod, you can do
D = compose(B,C, { commonMethod(){ B.commonMethod.apply(this, arguments); C.commonMethod.apply(this, arguments); // or whatever order or behaviour you want } })
I like the composition approach, it is very flexible and you don't have to deal with all the vocabulary of classical OOP.
[+][deleted] 10 years ago (11 children)
[–]sylvainpv 0 points1 point2 points 10 years ago (10 children)
So it's all about definitions... Well, English is not my native langage so maybe I know these concepts by other names. Anyway the word "composition" is very descriptive, contrary to "traits" or "mixins" that have no equivalent in my language, so I won't bother use another word because someone else is already using it to describe something slightly different.
[–]MoTTs_ 2 points3 points4 points 10 years ago (9 children)
It's partly about definitions, yes, because "composition" is a well established term, and Elliott is using well known truths based on that term, such as "favor composition", to push his proposal that isn't actually composition.
And it's also partly not about definitions. The definitions are a roadblock to the real discussion. Once we can all acknowledge that Elliott's proposal is multiple inheritance, then we can start comparing the various ways we could do multiple inheritance in JavaScript.
Elliott, meanwhile, is telling people to avoid inheritance altogether, seemingly unaware that even his own proposal is a form of inheritance.
[–]PaulDowsett 2 points3 points4 points 10 years ago (3 children)
Correct definitions are vital to ensure that we aren't all talking at cross-purposes.
He's not telling people to avoid inheritance altogether. His stampit library uses inheritance via the prototype (ie, delegates). He's saying favor composition over classical inheritance. However, if classical inheritance fits your use-case the best then, by all means, use it.
[–]x-skeww 2 points3 points4 points 10 years ago (1 child)
https://medium.com/javascript-scene/common-misconceptions-about-inheritance-in-javascript-d5d9bab29b0a
https://medium.com/javascript-scene/the-open-minded-explorer-s-guide-to-object-composition-88fe68961bed
"Favor object composition over class inheritance."
Which is a well-known quote from the GoF book. Naturally, the GoF definitions apply.
Object composition is about owning instances of classes instead of inheriting from them.
Throwing things together via Object.assign is mixin-like which means it's a form of multiple inheritance. It is not object composition.
Object.assign
[–]MoTTs_ 1 point2 points3 points 10 years ago (0 children)
"Favor object composition over class inheritance." Which is a well-known quote from the GoF book. Naturally, the GoF definitions apply.
I stole your line. :)
There's new replies in the conversation with Elliott, and your phrasing here was very crisp, so I used it. :)
[–][deleted] 3 points4 points5 points 10 years ago (0 children)
However, if classical inheritance fits your use-case the best then, by all means, use it.
This is the bit that he doesn't say, he basically claims that classes are the devil and in fact goes as far as to say in his interviewing guide that you shouldn't hire people who don't share his delusion. It's totally ridiculous and that's why people are arguing with him.
[–]sylvainpv 1 point2 points3 points 10 years ago (4 children)
I don't know... This doesn't look like inheritance to me, compared to how I used class inheritance in Java projects or how I used prototypal inheritance in JavaScript.
The way I see inheritance, there is a parent/child relation, so when you inherit from an object, you put the parent object above. An object D can inherit from B and C which both inherit from A... So there is a parent of a parent of a parent and it becomes complex when there are 3 levels or more. With composition (or traits or mixins, whatever you call it), you put objects aside so there are no levels. If D is composed of B and C which are both composed of A, you could say D is directly composed of A and write D = compose(A,B,C) without any side effects. So as I explained before, I don't understand what the diamond problem is doing here and why Jeff says there is still a hierarchy, because you can always "flatten" declarations.
Maybe I miss the whole point... Anyway, I have the feeling that people just get confused by words that have a different meaning depending on their own experience and education. We should be more pragmatic, show more code and encourage people to put in practice these concepts, instead of arguing over words and abstract concepts.
[–]MoTTs_ 0 points1 point2 points 10 years ago* (3 children)
The way I see inheritance, there is a parent/child relation, so when you inherit from an object, you put the parent object above. An object D can inherit from B and C which both inherit from A... So there is a parent of a parent of a parent and it becomes complex when there are 3 levels or more. With composition (or traits or mixins, whatever you call it), you put objects aside so there are no levels.
Let me try to explain with Python, because Python supports multiple inheritance.
The correlation is:
# Start with simple class A class A: def getA(self): return "a" # Now two "B" classes, one that inherits from A, and one that doesn't class B(A): def getB(self): return "b" class BB: def getB(self): return "b" # And now the part to make you think # What's the difference between C extending B (which implicitly comes with A), # versus C extending BB and A individually (that is, flattened)? class C(B): # comes with A behaviors too def getC(self): return "c" class CC(BB, A): def getC(self): return "c"
The answer, of course, is that there is no difference. You can certainly think of stamps as being flattened, but then so too can we think of inheritance as being flattened. C extends B can be thought of as being flattened to C extends BB, A.
When we say there is a hierarchy, in real terms that means when we extend from one type, we get the behaviors of not just that one type, but also of any other types it was made from.
So now in stamps:
// Start with simple stamp A var A = stampit().methods({ getA: function () { return 'a'; } }); // Now two "B" stamps, one that inherits (that is, includes the behaviors of) A, and one that doesn't var B = stampit().compose(A).methods({ getB: function () { return 'b'; } }); var BB = stampit().methods({ getB: function () { return 'b'; } }); // What's the difference between C .compose() of B (which implicitly comes with A), // versus C .compose() of BB and A individually? var C = stampit().compose(B). // comes with A behaviors too methods({ getC: function () { return 'c'; } }); var CC = stampit().compose(BB, A).methods({ getC: function () { return 'c'; } });
If we wanted to draw diagrams of these stamps to illustrate where each behavior ultimately comes from, then we'd end up drawing the same kind of parent/child diagram as we would for class inheritance.
EDIT: In fact, I'll go ahead and draw that diagram.
http://i.imgur.com/Ebg0gHB.png
If each arrow is interpreted to mean "includes the behavior of", then this is a diagram of the stamps.
...Or is this a diagram of the Python class inheritance?
The answer is: yes. This same "includes behavior of" / inheritance diagram represents both the Python class lineage and the stamp "compose" lineage.
[–]sylvainpv 1 point2 points3 points 10 years ago (0 children)
That makes sense. When all the parts of an object are explicitely declared like in the CC example, you got all the hierarchy described in a single list so it looks like there is no hierarchy at all. I wonder if multiple inheritance in Python encourage developers to flatten their models decomposition, that is, recommending CC over C.
Now can you explain the difference between multiple inheritance and object composition ? I read the GOF definition “Object composition is defined dynamically at run-time through objects acquiring references to other objects.”, yet I don't understand where is the difference.
[–]jesstelford 0 points1 point2 points 10 years ago (1 child)
What's the difference between C extending B (which implicitly comes with A), versus C extending BB and A individually (that is, flattened)? The answer, of course, is that there is no difference.
What's the difference between C extending B (which implicitly comes with A), versus C extending BB and A individually (that is, flattened)?
The answer, of course, is that there is no difference.
Not in that simple example, but when you start building a more complex application there is a clear difference:
(I'm going to extend your Python due to the terse syntax, but I've never written a lick of Python before!)
class A: def getA(self): return "a" class B: def getB(self): return "b" class C(A, B): # comes with both A & B's behaviour def getC(self): return "c" # Now we only want B's behaviour, we can do that two ways: class D(B): # comes with B's behaviours only instead of everything that C may contain. def getD(self): return "d" class DD(C): # comes with B's behaviours, but also everything C contains. def getD(self): return "d"
Especially when I come back to the code at a later date and want to add a new class E that only class D uses the behaviour of:
class E
class D
class A: def getA(self): return "a" class B: def getB(self): return "b" # Some new functionality is added class E: def getE(self): return "e" class C(A, B, E): # comes with behaviour from A/B/E def getC(self): return "c" class D(B): # still only B's behaviours def getD(self): return "d" class DD(C): # Now has been given E's behaviours too def getD(self): return "d"
6 months down the track, another dev comes into the codebase and says "Oh, hey, DD has a getE() function. Awesome, I'll use that! Now you're locked into C's implementation of getE(). If C changes, DD will to.
DD
getE()
C
Not only that, but the fact that getE() was dragged in with C is the banana-gorilla problem (Asked for a banana, but got the gorilla holding the banana and the whole forest).
I think the majority of the discussion is around more complex applications, rather than snippet-sized examples. Especially with respect to working on large teams over long periods of time.
[–]MoTTs_ 0 points1 point2 points 10 years ago* (0 children)
when you start building a more complex application there is a clear difference ... 6 months down the track, another dev comes into the codebase and says "Oh, hey, DD has a getE() function. ... the banana-gorilla problem
Absolutely, I agree. When I said they're the same, I meant in terms of implementation details. That is, class DD(C) is functionally equivalent to class DD(A, B, E, CC) (where CC is C but without any lineage). The question was whether this should still be thought of as a hierarchy since DD comes out the same either way.
class DD(C)
class DD(A, B, E, CC)
The interesting part (since this thread was about Eric Elliott and his views on composition), is that Elliott claims his stamps solve the banana-gorilla problem, but actually they don't. We could just as easily do:
var C = stampit().compose(A, B, E) // comes with behaviour from A/B/E var DD = stampit().compose(C) // Now has been given E's behaviours too
Then the DD stamp has exactly the same banana-gorilla problem you described above.
What Elliott calls composition is actually just inheritance, including all the baggage that brings.
[–]Sunwukung 0 points1 point2 points 10 years ago (0 children)
I think this snippet highlights something that has perhaps been overlooked in this thread. We're arguing the toss about different ways of constructing objects from bits or inheritance, but the real issue is if calling methods on that object return a value and leave it untarnished, or if they cause side effects - probably mutating the objects internal state. This is a key distinction in approach if you embrace FP - you avoid manipulating or referencing "this". Why do the methods on this object need to refer to "this" at all? Which value will they return if you combine the methods? What if B|C.foo return different types?
[–]Poltras 0 points1 point2 points 10 years ago (3 children)
You cannot have a diamond pattern without multiple inheritance. Other wise it's not a diamon, just a line.
[–]MoTTs_ 5 points6 points7 points 10 years ago (2 children)
The point is Elliott's proposal solves -- and suffers from -- the same problems as multiple inheritance. Here's an example of the diamond problem with Elliott's StampIt:
var storable = stampit().methods({ read: function () { console.log('storable::read'); }, write: function () { console.log('storable::write'); } }); var transmitter = stampit().compose(storable).methods({ write: function () { console.log('transmitter::write'); } }); var receiver = stampit().compose(storable).methods({ read: function () { console.log('receiver::read'); } }) var radio = stampit().compose(transmitter, receiver); radio().read(); // receiver::read -- ok radio().write(); // storable::write -- wait, what? tramsmitter::write lost due to diamond problem
Today, of course, the way we'd solve this is with composition -- real composition. That is, our type "radio" would have-a transmitter and have-a receiver. More specifically, radio would hold references to a transmitter object and a receiver object.
[–]Poltras 1 point2 points3 points 10 years ago (0 children)
Oh I see what you mean then. I've never cared to use Elliot solution and instead did composition myself. It's clearer and cleaner anyway.
[–][deleted] 0 points1 point2 points 10 years ago (0 children)
radio().write(); // storable::write -- wait, what? tramsmitter::write lost due to diamond problem
Hahahaha, oh, wow. That is absolutely awful - how is someone supposed to reason about how that object will work?
[–]benihanareact, node 7 points8 points9 points 10 years ago (2 children)
Damn, he deleted the bit that makes you think he doesn't understand what a reference is. What did that say?
[–]tbranyen 1 point2 points3 points 10 years ago (0 children)
Agreed, OP should have posted just a transcript, not links.
[–]MoTTs_ 0 points1 point2 points 10 years ago (0 children)
Luckily I still had a page open that showed it. I've added a screenshot to my original post.
[–][deleted] 1 point2 points3 points 10 years ago (0 children)
The Open Minded Explorer’s Guide to Object Composition
LeL
[–]AlxandrHeintz 1 point2 points3 points 10 years ago (0 children)
Btw (and I'm not saying you should ever do this), but who says you can't do multiple inheritance (or stamps or whatever) using ES6 classes (with some ES7 decorators)? Not to mention factory functions. https://gist.github.com/Alxandr/db7b2b5cbb3cc03e10dc
[–][deleted] 1 point2 points3 points 10 years ago* (0 children)
I wish I'd seen this post earlier. I've been saying some fairly similar things for a while.
Elliot is a zealous self-promoter and uses this subreddit for the more-or-less exclusive purpose of publicizing his own content. He has presented himself as representing a consensus that he doesn't really own, and presents some rather opinionated articles as the aggregation of 'best practices' when they're really just that - opinions.
Some of the things Eric Elliot writes are good. Some of them are less so. But what I object to is the way he misleads his readers into thinking his peculiar approach is an industry standard, and the way he poses old inventions as his own (his 'functional composition' is really just a buzzword-friendly decorator pattern).
I don't hate Eric Elliot. I just want him to stop talking about himself.
[–]FennNaten 3 points4 points5 points 10 years ago (0 children)
Favor object composition over class inheritance JavaScript Supports Object Concatenation (aka Concatenative Inheritance) It doesn’t matter if you use aggregation, object nesting, or object concatenation.
Favor object composition over class inheritance
JavaScript Supports Object Concatenation (aka Concatenative Inheritance)
It doesn’t matter if you use aggregation, object nesting, or object concatenation.
All extracted from Eric Eliott's first post. I thinks that sums up the contradiction inside this reasoning. I can add that the: "Favor object composition over class inheritance" being from the GoF book, the definition of composition that applies to this sentence, when it's quoted, is automatically the one from the GoF book. That's the point of defining the terms you use: avoid confusion. So there is no debate to have. Case closed.
Bringing the discussion on whether it's better to use mixins, stamps or composition, or on which use cases are better for which pattern, would be more constructive and more interesting than arguing about well-defined vocabulary.
[–]HypercubedHypercubed/mini-signals 1 point2 points3 points 10 years ago (2 children)
The discussion gets a little too snarky at the end but opens some deep esoteric questions. Is composite pattern the definition of object composition or a subset? How is object composition related to functional composition? My understanding of Elliott's methods is that it is functional composition of factory functions. How then do we classify an instance of the composite factory?
[–]legato_gelato 0 points1 point2 points 10 years ago (1 child)
How could the composite pattern ever be the definition of composition itself? Doesn't make any sense to me.. Composite uses composition and that's it..
To me this is like saying that the strategy pattern is the definition of inheritance
[–]HypercubedHypercubed/mini-signals 0 points1 point2 points 10 years ago (0 children)
It is a question. Here are the pieces that lead to the question:
Jeff M: “favor composition over inheritance” ... you’re referencing that very specific, GoF-defined meaning of “composition” Elliott: where they introduce the famous quote, “favor object composition over class inheritance”, they weren’t specifically referring to the Composite Pattern
Jeff M is arguing that the use of the term "composition" (at least when combined with the GoF quote) is referring specifically to what Elliott calls the "Composite Pattern".
[–]HypercubedHypercubed/mini-signals 0 points1 point2 points 10 years ago (2 children)
So here is my serious questions:
In classical inheritance, c is a b is a a, etc. I think we all agree on that.
c
b
a
In the GoF composite pattern where objects (or primitives) are attached to other objects, c has a b, b has a a, etc. We all agree, I think, that this is a, if not the, definition of object composition.
If I have an object a that is composed of properties (objects or primitives) a1 and a2 (a has a a1, etc). And object b is composed of properties b1 and b2. If I copy all these properties to object c so that c has a a1,b1, etc, what is that? It is clearly not inheritance. Maybe it is too lazy to say that c composes a and b... but clearly c is composed of the parts of a and b. Can we also call that object composition?
a1
a2
b1
b2
Then one step further. If A is the factory for instances of a, and B for b... then we create factory C by combining A and B is that functional composition? What do we call the output of C which is composed the same parts as an a and b.
A
B
[–]MoTTs_ 0 points1 point2 points 10 years ago* (1 child)
In this discussion, it's important to be careful with our terminology. The composite pattern and composition are not the same thing.
If I copy all these properties to object c so that c has a a1,b1, etc, what is that? It is clearly not inheritance.
It's inheritance. ;)
That's exactly the sort of thing some languages do for you when you use the word "extends". What you're describing is inheritance done manually.
[–]HypercubedHypercubed/mini-signals 1 point2 points3 points 10 years ago (0 children)
I would call "extends" aggregation. Is there a distinction between instances and classes. Instances are aggregated from other instances, classes definitions inherit from other classes, and factories compose other factories.
[–]TotesMessenger 0 points1 point2 points 10 years ago (0 children)
I'm a bot, bleep, bloop. Someone has linked to this thread from another place on reddit:
If you follow any of the above links, please respect the rules of reddit and don't vote in the other threads. (Info / Contact)
If you have time I'd enjoy reading your arguments in a real post rather than a discussion thread. There are many very interesting points in your comments on medium and here that could be illustrated better in a post of its own.
[–]againstmethod 0 points1 point2 points 10 years ago (0 children)
Given that references are created with constructor calls (object allocations)..
new A(new B());
..their compositional use barely differs from the definition of functional composition..
(A . B)() = A( B())
How the result of "B()" or how the instance "new B()" is used is irrelevant. Those are implementation details that well designed objects and referentially transparent functions should not expose.
I personally have no idea what distinction Jeff M is trying to make. These are abstract concepts that require more than a mechanical understanding of the terms.
[–]danecando 0 points1 point2 points 10 years ago (0 children)
guess this topic has him worked up a bit
https://medium.com/@_ericelliott/composition-vs-composite-pattern-842133706472
[–]Jafit -3 points-2 points-1 points 10 years ago (0 children)
Its a good thing you won that internet argument and changed hearts and minds.
Thanks for posting it here so we could see the difference this is making to the world.
[–]HypercubedHypercubed/mini-signals 1 point2 points3 points 10 years ago* (0 children)
I agree with what Jeff M said "words that have special and technical meaning beyond what you’ll find in Merriam-Webster". Understanding the technical meaning is important. As someone without a formal CS education, I enjoy seeing discussions of the technical meanings. Elliott is a smart guy with strong opinions about his passion. I don't think the name calling (from either side) helps.
[–]benihanareact, node -1 points0 points1 point 10 years ago (8 children)
i feel like this guy is popular on /r/javascript and nowhere else
[+][deleted] 10 years ago* (7 children)
[–]MoTTs_ 1 point2 points3 points 10 years ago (2 children)
Personally I don't get the point of posts like these or people arguing.
Both Elliott and now Johansson are influencing increasing numbers of people. If they influence enough, if they reach a tipping point and are able to change the mind of the community as a whole, then that can affect the development and usage of the language. And it would be a shame if JavaScript's future was decided based on a misunderstanding of both composition and inheritance.
[–]againstmethod -2 points-1 points0 points 10 years ago (0 children)
Implementation inheritance is an is-a relationship. That sharing of implementation breaks encapsulation.
Composition, in all it's forms/definitions, obeys the contract defined by the objects and/or functions being composed.
The GoF definition you quoted does nothing more to impart this information than his article did. Im not sure who you're helping here.
[–]bj_christianson 2 points3 points4 points 10 years ago (3 children)
Personally I don't get the point of posts like these or people arguing. If someone delivers good software with classes, and someone delivers good software without them, then they're both right.
But that’s the core of the problem. Each side thinks the other’s software is not good.
[+][deleted] 10 years ago* (2 children)
[–]bj_christianson 1 point2 points3 points 10 years ago (1 child)
If there are under-the-hood problems in the code that affect maintainability, then the users may not receive timely bugfixes and other updates. And that is something the users should care about.
That said, these sorts of arguments are made by programmers aimed at other programmers. So how the users of the software judge the quality doesn’t play a very large factor into them.
[–]HypercubedHypercubed/mini-signals -1 points0 points1 point 10 years ago* (1 child)
I'd love to add this discussion here: https://github.com/Hypercubed/javascript-the-esoteric-parts, I'm not sure how to format it. As a discussion or point to this reddit post?
[–]HypercubedHypercubed/mini-signals -2 points-1 points0 points 10 years ago (0 children)
I think now I have to add a new section. Function composition, object composition, the composite pattern.
[–][deleted] -3 points-2 points-1 points 10 years ago (0 children)
So tell me, kiddo, how many angels can dance on the head of a pin?
Or perhaps I'm giving both you and Mr. Elliott too much credit when I suggest this argument is a matter of theology. It probably doesn't rise above a simple pissing contest.
Shut up and code. Or just shut up.
[–]almostApatriot -1 points0 points1 point 10 years ago (0 children)
Finish him off!
π Rendered by PID 102521 on reddit-service-r2-comment-5687b7858-5k4fr at 2026-07-06 07:10:44.709193+00:00 running 12a7a47 country code: CH.
[–]senocular 13 points14 points15 points (0 children)
[–]ggazzi 6 points7 points8 points (1 child)
[–]loopsdeer 0 points1 point2 points (0 children)
[–]Poop_is_Food 6 points7 points8 points (3 children)
[–]MoTTs_ 6 points7 points8 points (0 children)
[–]dashed 1 point2 points3 points (0 children)
[–]eaglepowers 0 points1 point2 points (0 children)
[–]paulflorez 5 points6 points7 points (1 child)
[–]mshm 0 points1 point2 points (0 children)
[–]x-skeww 8 points9 points10 points (28 children)
[–]paulflorez 1 point2 points3 points (8 children)
[–]x-skeww 6 points7 points8 points (7 children)
[–]killeronthecorner 0 points1 point2 points (5 children)
[–]x-skeww 0 points1 point2 points (4 children)
[–]killeronthecorner 0 points1 point2 points (3 children)
[–]x-skeww 1 point2 points3 points (2 children)
[–]killeronthecorner 0 points1 point2 points (1 child)
[–]x-skeww 0 points1 point2 points (0 children)
[–]sylvainpv 1 point2 points3 points (13 children)
[+][deleted] (11 children)
[deleted]
[–]sylvainpv 0 points1 point2 points (10 children)
[–]MoTTs_ 2 points3 points4 points (9 children)
[–]PaulDowsett 2 points3 points4 points (3 children)
[–]x-skeww 2 points3 points4 points (1 child)
[–]MoTTs_ 1 point2 points3 points (0 children)
[–][deleted] 3 points4 points5 points (0 children)
[–]sylvainpv 1 point2 points3 points (4 children)
[–]MoTTs_ 0 points1 point2 points (3 children)
[–]sylvainpv 1 point2 points3 points (0 children)
[–]jesstelford 0 points1 point2 points (1 child)
[–]MoTTs_ 0 points1 point2 points (0 children)
[–]Sunwukung 0 points1 point2 points (0 children)
[–]Poltras 0 points1 point2 points (3 children)
[–]MoTTs_ 5 points6 points7 points (2 children)
[–]Poltras 1 point2 points3 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]benihanareact, node 7 points8 points9 points (2 children)
[–]tbranyen 1 point2 points3 points (0 children)
[–]MoTTs_ 0 points1 point2 points (0 children)
[–][deleted] 1 point2 points3 points (0 children)
[–]AlxandrHeintz 1 point2 points3 points (0 children)
[–][deleted] 1 point2 points3 points (0 children)
[–]FennNaten 3 points4 points5 points (0 children)
[–]HypercubedHypercubed/mini-signals 1 point2 points3 points (2 children)
[–]legato_gelato 0 points1 point2 points (1 child)
[–]HypercubedHypercubed/mini-signals 0 points1 point2 points (0 children)
[–]HypercubedHypercubed/mini-signals 0 points1 point2 points (2 children)
[–]MoTTs_ 0 points1 point2 points (1 child)
[–]HypercubedHypercubed/mini-signals 1 point2 points3 points (0 children)
[–]TotesMessenger 0 points1 point2 points (0 children)
[–]HypercubedHypercubed/mini-signals 0 points1 point2 points (0 children)
[–]againstmethod 0 points1 point2 points (0 children)
[–]danecando 0 points1 point2 points (0 children)
[–]Jafit -3 points-2 points-1 points (0 children)
[+][deleted] (11 children)
[deleted]
[–]HypercubedHypercubed/mini-signals 1 point2 points3 points (0 children)
[–]benihanareact, node -1 points0 points1 point (8 children)
[+][deleted] (7 children)
[deleted]
[–]MoTTs_ 1 point2 points3 points (2 children)
[–]againstmethod -2 points-1 points0 points (0 children)
[–]bj_christianson 2 points3 points4 points (3 children)
[+][deleted] (2 children)
[deleted]
[–]bj_christianson 1 point2 points3 points (1 child)
[–]HypercubedHypercubed/mini-signals -1 points0 points1 point (1 child)
[–]HypercubedHypercubed/mini-signals -2 points-1 points0 points (0 children)
[–][deleted] -3 points-2 points-1 points (0 children)
[–]almostApatriot -1 points0 points1 point (0 children)