Hacker News new | past | comments | ask | show | jobs | submit login
The Gang of Four is Wrong and You Don't Understand Delegation (saturnflyer.com)
47 points by angelbob on Aug 14, 2012 | hide | past | favorite | 41 comments



From Design Patterns (first edition):

> Delegation is a way of making composition as powerful for reuse as inheritance [Lie86,JZ91]. In delegation, two objects are involved in handling a request: a receiving object delegates operations to its delegate. This is analogous to subclasses deferring requests to superclasses. But with inheritance, an inherited operation can always refer to the receiving object through the "this" member variable in C++ and "self" in Smalltalk. To achieve the same effect without delegation, the receiver passes itself to the delegate to let the delegated operation refer to the receiver.

Sounds like they're perfectly clear and correct to me. As the author of the post points out the GoF don't actually show examples of delegation in the book and I don't recall them using the term much, so I don't see how they're perpetrating any misinformation here.

> In JS we can assign a prototype: the equvalent of the parent slot in Self.

No, .prototype is not equivalent to a parent slot in Self. It's closer to a traits object, I think. The unstandardized __proto__ property is equivalent to a parent slot in JS.

> Yeah, Design Patterns showed examples in Java. And Java can’t do delegation. So is that a valid argument for rewriting the meaning of a term?

Design Patterns is older than Java. Maybe later editions use it, but the original version used C++ and Smalltalk.

Otherwise, good troll post, original author. I'm sure you'll get lots of traffic and people noticing your book. Well played!


Thanks for clarifying. I had most of it written before posting and had forgotten the code samples. My copy of Design Patterns is packed up for a move. I've update it to refer to C++.

Actually, people have visited, but few have stayed to read. My goal is to clarify the concept. I did plenty of research before writing this including asking Lieberman and others about it. I first wondered how everyone's notion could be wrong and doubted that my understanding was correct.

This is a term that others have attempted to clarify as well http://javalab.cs.uni-bonn.de/research/darwin/delegation.htm...


Clarifying the underlying concept is great. Self-style delegation gets to the heart of why "this" is dynamically bound in JavaScript, which is one of the language's most confusing features. Self-style delegation is also just generally cool and more people should know about it.

At the same time, getting hung up on terminology and trying to mandate a definition that goes against current usage just because it's older is a fool's errand and doesn't help.

Language is a social construct. It's very important for us to have consensus and agree on what words mean so that we can communicate efficiently. At the same time, there's nothing wrong about having definitions change over time.

"Car" used to mean a two-wheeled Celtic war chariot. It wouldn't be helpful to insist that it still mean that, and it's just mean to proclaim that everyone who uses "car" to mean "automobile" is wrong and doesn't understand the idea of war chariots.


If you agree with munificent, then perhaps you could soften your title and introduction to say that many people confuse what the GoF meant, not that the GoF are wrong.


good point. I'll verify the citation and update it.


Delegation is such a commonly-used English word that you don't get to have a monopoly on its definition. If I have two classes and one delegates to an instance of the other, then it's delegation.

Just because Lieberman tried to give it a more refined definition in the context of OOP doesn't mean that the less refined use is incorrect. You don't get to take away my English words.


Lieberman invented this term. It did not exist prior to his work. I have confirmed this with Lieberman himself as well as Jim Coplien and David Ungar.

The Design Patterns book sought to clarify our language yet it has this error. I'm seeking to clarify our language.


Sorry dude, language doesn't work that way. Just because Lieberman invented the term, doesn't mean he's right. Definitions of words are decided by use, not authorship.

The language doesn't need clarifying, because the term has a definition, which is perfectly clear. Through a quirk of history, this perfectly clear definition happens to be different than the other perfectly clear definition which preceded it. Due to this retcon, Leiberman's original definition ends up being incorrect. Wasn't the first time something like this happens, and it won't be the last. So it goes.


> Sorry dude, language doesn't work that way.

If his post persuades everyone and they start using it the way he wants them to, then language does work that way.


He did not invent the term. "Delegate" and "delegation" have been around a lot longer than computers. Here's a definition:

Delegate. Verb: Entrust (a task or responsibility) to another person, typically one who is less senior than oneself: "he delegates routine tasks".

It's not hard to see how that would be analogous to a variety of situations in computing.

If you want a term to be more pure, think of something more creative.

Edit: That's not to take away from your point that the GoF actually cited Lieberman in their use of delegation. If they misunderstood his intention, sure raise that point.


In programming terms, he did. I appreciate that it is an English language word and was initially what I thought it meant. But when he applied the term he meant it specifically. Otherwise, we already have a term for this: forwarding.

So why not argue about people using "delegation" when they just mean "forwarding"?


Alright, let's take it for a spin. What do you call the thing that you're forwarding to? The endpoint? The "nextLinkInChain"? Delegate seems pretty natural to me in most domains, but as you say, I've been poisoned by GoF.


I'm planning to follow up in another post, but Gunther Kniesel coined the term "consultation" (http://javalab.cs.uni-bonn.de/research/darwin/delegation.htm...) and I've used a generic "attendant" term to refer to the other object.

Here's an excerpt from my take on the 2 characteristics of consultation (or what is typically called "delegation") in my book

---- The first is the connascence of method names between collaborating objects. Connascence refers to the point and type of coupling between objects where a change in one object requires a change in the other. Consultation occurs when the message recipient forwards a message to another object which handles the response to the same message. A calculator would receive a balance message and forward that message to an account which responds to balance. Rails’ implementation of delegate does include a caveat that the message might be prefixed before it is forwarded, but the implementation is still connascent by method name. The second aspect of consultation is that the message recipient makes no modifications to the algorithm for handling the response. ----

I wrote to Lieberman to ask his opinion and he sided with NOT introducing the "consultation" term. But his reason was not because our misguided understanding of delegation is correct, his reason was because we already have a name for this: forwarding. The quote above is from my argument about why I think it is valuable to use the term "consultation".


> He did not invent the term. "Delegate" and "delegation" have been around a lot longer than computers.

So did "inheritance" but it means something very specific in programming parlance.


Sorry, you're wrong. Next you're going to try to tell me that gay means homosexual when we all know it means happy.


So he's redefining delegation in your own sense (implied by his strange titlebait "The Gang of Four is Wrong") and then criticizing everyone else post hoc?

I fail to see how this deserves any upvotes.


I'm the author. I'm not redefining delegation. I'm pointing out that the Gang of Four, who cited Henry Lieberman who created the term, described it incorrectly. You can read the citations in the Design Patterns book and see exactly what they got wrong. Here's a link to Lieberman's work http://web.media.mit.edu/~lieber/Lieberary/OOP/Delegation/De...


The td;lr of this post: this article is misguided according to usage, the history of the word "delegation", and the principles of good software design.

One of the points of design patterns is to define a common language. The benefit of this is that it helps people understand one another. The fact that delegation as discussed in GoF is what everyone understands delegation to be is good enough reason to continue using the word "delegation" that way and to force him to find a new word for what he wants to say. Even if his definition was first.

But his definition was NOT first. Sure, someone may have first used the term in OO programming in his sense of the word. But the word "delegation" has long-standing usage in the English language. It means, "Doing this is now your responsibility." In English there is no automatic implication that the person to whom things are delegated necessarily has access to the person who did the delegating. In practice, of course, there is. Which is why the software analogs include that. But in the real world it is clear when you intend to refer a question back to the original person, and when you do not. Therefore the long established and universally understood definition does NOT indicate that the person to whom you delegate has the option of choosing to intercept any and all questions you ask.

So which behavior is preferable?. If I delegate to you, and then need to be aware of all of the methods that you define, all of your methods, both public and private, become part of the surface of the API between us. However the whole point of modularity is to have limited APIs between you and your components. Enlarging the API may be easier and more convenient, but it entwines code into spaghetti and is bad for your code base. So good software design says that of the two possible definitions of "delegation" we are comparing, we should prefer the one that makes it clear in the delegated to method when exactly it intends to go back to the delegated object versus when it is trying to send messages to itself. And the version that does that is the version that the Gang of Four used.

Therefore he is wrong to say that delegation should be redefined to mean what he means. He is wrong to say that his definition is better grounded in the history of the word "delegation". And he's dead wrong that implementing his version of the word "delegation" is better software design than the current definition.


I never said delegation should be redefined. In fact I'm pointing out that the GoF did the redefining. In the history of Object-oriented programming "delegation" means what it was described to be. I never said that any particular implementation is "better software design". Please show me where you got these things that I supposedly said.


You admit that today in common usage and implementation in various languages, "delegation" means what the GoF described it as. Language is defined by usage, so that is the current definition.

You are insisting at this point that we should only use the first definition ever proposed for the word in software at this point. That would be redefining it. It would also create confusion.

I do not dispute that GoF already redefined the word. That's historical fact. However what they defined it as is a concept that is better software design than the thing defined in the historical definition that you want us to go back to. Thus what they are calling delegation is not just different, but better.

To reduce jargon, it is good that we try to limit how many words get special meanings in software. And it is therefore good to only give that treatment to particularly useful concepts. Which means to me that what GoF defined "delegation" to be is more deserving of having its own word than the original concept.

Hopefully that clarifies why I call your attempt to go back to the original definition "redefinition", and why principles of good software design make the GoF definition more compelling.


Many people agree on the words proposed by GoF, but not on the details of the meaning, and this is a frequent source of misunderstandings and useless debates. Over the years I have gone from fan of the book to considering it a net negative force in software engineering, a failed attempt that many people still believe in. (The other failure of the book is in educating people to blindly believe that applying a given pattern is always a good solution because, hey, it's a pattern)

If you look at the details of the patterns as examples rather than definitions, and treat on the book as a general description of common situations, problems and approaches, then all is well.


In my experience, GoF is most useful in that it says, "Patterns exist in software architecture as much as they do in physical architecture."

The rest is details.


If both definitions of 'delegation' end up having the same purpose, does it really matter? Why should I care that Rails' 'delegate' isn't exactly how some guy in 1970 would've written it?

This whole "object-orientation" bent in the Ruby community lately just feels like a crusade, with people thumping on old OO books, each proclaiming theirs is the "true way". And, usually, like in this example, it doesn't even matter because their code ends up doing exactly the same thing with little real-world gains in readability or ease of understanding.


One of the traits that allows us to be competent programmers is a pedantry about technical terminology. Why overload the concept of message forwarding with a second term if what that term was originally coined to describe is a useful paradigm?

I had never heard of this distinction, however it immediately made sense to me because I've run into this case in Ruby where using a ruby "delegate" object actually was much more verbose than I had envisioned because of all the context I had to bring over to the delegate object one way or another. In the event I decided "delegation" was not right because the implementation necessarily violated the Law of Demeter.

So yeah I think pragmatically it does matter.


I agree that there are cases where pedantry is necessary for programmers. That does not mean that pedantry is necessarily valuable.

In this case a distinction is being drawn that would make "delegation" mean something that is worse from the point of view of good software design, which would leave the thing that is better software design without its commonly understood name. Doing this would create negative value.


I'm not following your point. I'm saying that true delegation as defined by the article is in fact a useful tool for good software design. Maybe not as broadly useful as standard message forwarding, but something which deserves its own term.


Delegation as defined by the article makes every method call made by the delegated to class part of the programming interface that you need to be aware of when choosing to delegate. Delegation as defined by GoF makes only a specified set of callbacks be part of that interface.

That says that delegation as defined by GoF does more to promote modularity than the original definition, and therefore is more often going to be preferred in good software design over that defined by the article.

This is not to say that there aren't cases where what the article promotes is not convenient. Violating modularity is usually convenient. But that is a convenience that we should always be wary of.


> One of the traits that allows us to be competent programmers

I think we've failed then since we've totally overloaded and confused basic concepts such as weak/strong typing and dynamic/static typing.

To make matters worse, those are cases where we as programmers invented to terminology at hand and didn't just appropriate it into a programming context.


Since you brought up typing, you might enjoy this related confusion: http://stackoverflow.com/questions/9154388/does-untyped-also...


i don't know about you but i'm getting sick and tired of these "marketing" posts with sensational titles.

if you have a book to sell just say so, so we can directly skip your post.


I'm getting sick of them as well. Most of them follow the same formula by having a declarative statement pointing out that someone is either wrong or doesn't understand something or this that or the other will never work. They seem to be pretty popular on here though as many of them have lots of comments.


I ignored the book and learned about two different types of delegation today. I'm happy.


Terminology arguments aside, I remember at least one occassion where I really wanted this in a GoF pattern.

I had an interface Repo, with methods getA() and getB(). I wanted to overlay a transparent cache a la Proxy (http://en.wikipedia.org/wiki/Proxy_pattern, note its use of "delegate" in its description).

So I had implementations CachingRepo and DataStoreRepo, the first would cache recent calls and the latter would make real calls. CachingRepo would have an instance of Repo that it delegates to on a cache miss.

The issue was that DataStoreRepo.getA() relied on getB(). In a non-Lieberman delegation strategy, that B would always come from the data store, not my cache.

If I understand correctly, in Lieberman delegation getB() could return the cached values, because its "self" would point to the CachingRepo, not "this" in a Java sense.

It's not impossible to do this in Java, there's just not language support for it. The wiring would be cumbersome. Thanks for introducing me to Lieberman's work, but I'll stick with the de facto standard usage of "delegation".


Correct me if I am wrong, but it seems to me that (Lieberman) delegation is quite a dangerous concept when applied to the most popular object oriented languages. You're effectively calling another object's methods and masquerading yourself as that object, or to put it another way you're exposing all of your privates and implementation details to another object. Hence it is much more dangerous, and potentially quite incorrect, than just forwarding.

The only safe way I can see this being done is by adding a reference to object A when calling/forwarding a method on object B. But that's just forwarding with extra data.

Maybe I haven't worked enough with fully dynamic languages, but I don't really see much or any benefit to doing 'Lieberman' delegation, over and above other options.


Liberman deleation is fine-grained multiple inheritence. If I say I'm delegating the implementation of method foo to object bar, it sounds unsafe. If I say I'm inheriting the implementation of method foo from object bar, it seems safer, albeit not "classical OO."


Thanks, that makes far more sense to me.


In my experience most implementations either have a way of binding the context per method (JavaScript), or use a loose convention of passing the sender as the first argument (Objective-C).

It seems like the Ruby libraries cited are the real issue, rather than a fundamental misconception of the concept of delegates or indeed inversion of control as a whole.


God bless that OO dreamers!

Always witty, and always far away from their evading (and silver :)) target...


he's just selling a book, relax


Maybe the need of a Design Pattern means that the language is not powerful enough.

PaulGraham said "Peter Norvig found that 16 of the 23 patterns in Design Patterns were 'invisible or simpler' in Lisp." http://www.norvig.com/design-patterns/





Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: