From: Dirk Detering Date: 2002-07-08T20:28:10+09:00 Subject: Re: self_parent james@rubyxml.com schrieb: > How would an object know the methods of an arbitray parent? Doesn't this > completly couple the two objects? The parent (reasonably) expects the > object it creates to implement certain methods; the newly-created object > expects the parent to implement certain methods. Yes, indeed. But let me think aloud a bit: 1.) Sometimes you have this tight coupling between two classes/objects. Customer and Address perhaps is a bad example as you can Address imagine to belong to other containers too. OTOH a relationship between an Order and an Orderline or an Invoice and Invoiceline is much closer. 2.) Designing that relationship as bidirectional navigable (as expressible with the UML) is a possibility. You could hand around orderlines and they keep the relation to their container/master/whatever-term-you-want like with closures at the technical level. OTOH: Wouldn't it be a better design to always hand over the reference to the order or to the invoice instead of single lines, and access the parts of it via the order's/invoice's interface? (delegator). Otherwise the client of Order would have a deep inside, how an order is implemented inside. But: Wouldn't that mean, that an Order has to implement something like a Orderline interface? (As I could not easily return a reference to one of its orderlines ...) This tight coupling is an intimate knowledge between Order and Orderline, and is directly understood by people knowing the domain. But looking at this: Some people here stated *never* need to pass a self reference to a contained object. This would mean to have a strictly uni-directional navigation troughout the whole system. And that's IMHO not true, unless they make some design pull-ups to strictly avoid callback and delegation. > Perhaps I misunderstand what you need to accomplish or how self_parent > would be implemented, but it sounds like it would encourage fragile designs > without any real gains. Hum, not really. I've got the feeling that there should always be two kind of interfaces. First: The 'inner' one between two tightly coupled classes/objects. Why shouldn't be there a relation between a class/object and its close "environment"? (In comparision: Think of the effort of writing a shellscript which gots everything explicitly as CL-options instead of using the environmentvariables.) They would communicate with each other in a form of call and callback. Second: The 'outer' one between a component and it's environment. To be useful in many "environments", perhaps contexts, the component should never rely on specific behaviour or structure of its outer side. Here works the Law Of Demeter: "Don't talk to strangers". In this description a 'component' can be a single class or a combination of tightly coupled, co-relating classes. Looking into the real world, there *are* technical items which can be assembled into many environments by having a standardised "interface" (plug, switches ...) but having parts inside them which possibly never (hum I don't like this word) could be used outside in other combinations. Coming to the original subject: - Yes, indeed it is a design decision to couple classes So to be open, the language has to support all (hum, most of) the decisions I made. Not necessarily language inherent (when passing self) but it could simplify things, if it would be possible (when having a self_composite reference, to give another name for that ;o) ). This is the fact with Ruby. Your design decisions are supported. In this case by using self. - As we've seen in the discussion in this thread, this *is* a *design* decision and not a general feature of classes in OOP. So this reference pointer can not be considered an every-class feature requirement. It is the special case the UML calls: Composition, meaning a one-to-many aggregation. And it is the special case this asssociation is bidirectional. Perhaps it would be worth thinking about a keyword in the language declaring a class as 'bidirectional', which, when using it, would introduce this self_composite reference? - But it would not be enough to have this keyword. You should declare more of this relationship. So you would declare the class to which this composition refers, to give the system ability to proof the structure at runtime just *before* calling a self_composite's method. This would lead indirectly to a design language, where you would declare associations in another way than common today. The question then is: What about all the other kinds of associations, what about multiplicity? I resume: This feature would lead to a totally other PL concept, and leads outside of Ruby. > In your example, Address requires an object that implements pretty_name. Indeed. > It works with any parent if that parent passes in a pretty_name-compliant > object. Right. > Having Address use self_parent means it *only* works when the > parent responds (and in the right way) to pretty_name. Indeed, that's the problem with communication :-) . The called object has to implement a method for the message. > Changing the > Customer class can break the Address class, and vice versa. What you stated is a problem you *always* have when changing the interface of a class which is used by other parts of the system (like usual, as classes/objects *exist* to be used by other parts, or they will be killed by the GC). So changing the Customer class will have much more effect to objects not mentionted here in the current discussion: Its clients! Using the self_whatever reference would not break the rule of communication via interfaces. It would only simplify the definition of a very special kind of association. And as I told, Customer->Address is a bad example. Regarding to my examples: Changing a class without knowing the relating (domain) model (Order -> Orderline) is a foolish attempt. When knowing the (domain) model, changing the Order class without having a look at the Orderline class (or vice versa) should be considered a implementor's offence. BTW: Regarding the last post I read. This is indeed not a matter of OO "inheritance". But looking at the ways to construct systems there are *two* relation dimensions: inheritance and association. It is interesting, that OO languages directly support only the former one, but have no implicit mechanisms for the latter. This is why this relations must be explicitly 'generated' out of an UML diagram into code mechanisms (e.g by passing self). But these mechanisms just are flexible enough to support the very different kind of design decisions. JM2C Det