By Mutual Has-a relationship
, I mean one where two objects (often of very different classes) are expected to have pointers to each other; the two classes are symbiotic in the sense that an instance of either does not function properly without an instance of the other (even if it is a NullObject
sort of instance).
While this seems like a logical way to prevent CombinatorialExplosionOfClasses?
in certain circumstances, drawing on the power of CompositionInsteadOfInheritance
, I think that it is a CodeSmell
. If MergeObject
refactoring really isn't possible, then perhaps it is more appropriate to use ContextParameter
s. In any event, the reason it smells is because it produces difficulties in maintaining the integrity of references (especially if the instances are able to swap amongst themselves, but also at initial creation time) and obscures the idea that a reference as part of an object's data encodes a Has-a relationship. Mutual ownership seems intrinsically more difficult to understand. (Why yes, I am
single, why do you ask?) -- KarlKnechtel
In the Smalltalk-80 MVC framework the view and controller have references to each other and are tightly coupled. It seems to work. -- JasonArhart
(A,B) is true then is PartOf
(A,B) or PartOf
(B,A) also true? Yes, if PartOf(A,B) means HasA(B,A) (in which case it is technically a tautology)
If A and B have pointers to each other, that does not
automatically mean that A HasA B and vice versa. In general that is a false claim. One easy counter-example is a doubly linked list. The forward and back references don't mean that each node is in relationship HasA to what it points to. Now make odd numbered nodes of type A and even numbered nodes of type B, for some problem-domain reason. This still doesn't introduce HasA.
Terminology for HasA and IsA is inconsistent and often confused in the industry, in part because of underlying theoretical issues regarding categorization, classification, etc. Still, it stands to reason that HasA should have some resemblance to the definition of the English word "has", which means some kind of possession, whether physical or abstract, partitive or whatever.
HasA usually means containment, and usually it would be self-contradictory for two things to contain each other. Not always, but those exceptions might be nonintuitive. Concrete objects in the real world don't usually contain each other.
"A HasA B" sometimes means "A contains a relationship with B" instead of "A contains B". In the linked list example, each node of type A contains predecessor and successor relationships with instances of type B.
[And if devotee's WorldViews
evolve then is their previous religion still PartOf
A reasonable question; "has" and "part of" etc are often used to express abstractions like that. It can be made to work. It can also be made to work even better by having different labels rather than overloaded labels. To model beliefs as a part of a person is a kind of essentialism, which is a biologically innate mode of thinking, so it's intuitive. But it can run into practical difficulties.
[All this is why it is good to introspect about relations. They are highly ambiguous, we take them for granted, make assumptions about what each person is saying because we are focused on the noun phrases and skim over how we are saying they are juxtaposed]
If two objects contain references to each other, this could indicate they have a mutual UsesA relationship. A UsesA B, and B UsesA
n A. This isn't necessarily a CodeSmell
. It corresponds, in UnifiedModelingLanguage
terms, to a bidirectional association. The mutual HasA relationship would correspond to a mutual aggregation (or composition) relationship, which is illegal in UnifiedModelingLanguage
The doubly-linked list should probably be seen in this light. Each node has an association with the surrounding nodes, which also have an association with it.
A data-stream processing library I wrote in Perl (see FlowBasedProgramming) had a similar doubly-linked data structure. The two classes cooperated to assure construction went smoothly and all references were correct. Ironically, the problem came at the other end; since Perl uses a reference-counted garbage collector, there was a problem destroying objects that were no longer used. --TimKing
I'm not sure what that has to do with HasA, but that's interesting. I tried to clarify above and also extended the entry to make it more apropos of FlowBasedProgramming. The objects were doubly-linked, as per the definition at the top of the page.