Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Containment/Composition/Aggregation

177 views
Skip to first unread message

Tom Jones

unread,
Sep 11, 2002, 12:20:24 AM9/11/02
to
I have asked a number of OO developers the difference between these 3 terms.

This is my synthesized take on their meanings (correct me if I am wrong):

The consensus is that composition and containment are synonymous.

Composition infers a "has-a" relationship. A car "has-a" engine. A
lifetime is also inferred by composition. If the car goes away, the engine
goes away.

Almost everyone I talked to has a different definition for aggregation (or
they had no definition at all). Some people said that aggregation is just
like containment, in that the aggregator "contains" or holds the aggregatee.
The analogy I heard was that "an airport is a holding place for airplanes,
so the airport is said to 'aggregatee airplanes'". Also, the lifetimes of
the aggregator and agregatee are not tied as they are in composition.

Of course this contradicts my assertion above that composition and
containment are the same thing.

Is it only composition if the enclosing class actually creates the contained
object?

Ok OO gods... I would appreciate your thoughts on the definitions of:

- Containment
- Composition
- Aggregation

as they pertain to OOD.

Thanks,
Tom


Daniel T.

unread,
Sep 11, 2002, 8:29:53 AM9/11/02
to
"Tom Jones" <tomjo...@hotmail.com> wrote:

> Ok OO gods... I would appreciate your thoughts on the definitions of:
>
> - Containment
> - Composition
> - Aggregation
>
> as they pertain to OOD.

"The solution to these problems requires that designers understand that
there are three, and not two, relationships involving uses and
containment. The first is clearly a uses relationship and is never
confused with containment. A good example is "person uses an alarm
clock." There is no hint of containment here. Then there is the car and
its engine example. This is clearly containment (which implies uses).
However a third relationship lies between these two extremes. This is
the domain of the parking lot and its cars, the classroom and its
students, and the gas station and its cars. Some groups simply consider
this intermediate category as a uses relationships since it does not
exhibit the design-simplifying attribute of a true containment
relationship. This relationship does not guarantee that we can ignore
the contained objects at some high level of design. The important thing
is to understand the three concepts; what we call them is irrelevant.
Some groups with which I have dealt refer to them as composition,
containment, uses, respectively; others call them containment, uses,
uses; others call them containment, containment, uses; and still others
have called them strong containment, weak containment, and uses."

-- Arthur J. Riel "Object-Oriented Design Heuristics"

Jimmy Venema

unread,
Sep 11, 2002, 9:02:35 AM9/11/02
to
You can also look at it from a different point of view, forget the namings
and look at possible different concepts. Concepts have a direct impact on
implementation the naming not. One possible concept to look closely at is
the one of lifetime. When two objects are related they can have an impact on
each others lifetime. In my opinion you can distinguish 3 variations here.
Assume two objects A and B and there Lifetimes La & Lb and the Lifetime of
the relation itself Lr
1. The relation has no impact on the lifetime of the related objects La !=
Lb & Lr = La ^ Lb
2. The relation implies an onwership, the lifetime of object B is contained
in A e.g. La >= Lb & Lr = Lb
3. The lifetimes are equal La = Lb = Lr

This are 3 very distict concepts with a direct difference in implementation,
I think that this is more important then mind games of artificial
differences which can never be found back in the actual product. Most often
1. is called Association, 2 is called Composition, 3 is not named and
Aggregation is something between 1 and 2 and often rather vague. The naming
of the concepts varies with the person asked, but the above one is the one
most often used according to my knowledge. The fact if I agree with it is
another issue. I think we should reverse the discussion from defining what
the names are into define the different concepts first and then name them.
Perhaps we should not clasify relations to their difference in lifetime, but
on another concept. But first make the concepts clear on which we are to
clasify relations. If there are more variables make a multidimensional
matrix and fill it in.

Jimmy Venema

P.S. you forget association in your list

"Tom Jones" <tomjo...@hotmail.com> wrote in message
news:unth5j...@corp.supernews.com...

Shayne Wissler

unread,
Sep 11, 2002, 11:13:43 AM9/11/02
to
Those are good analogies. Does anyone know of a system that enforces the
implications of "weak" containment, i.e., the car can only be in one parking
lot at a time?


Shayne Wissler

"Daniel T." <a@b.c> wrote in message
news:a-5ACDF7.08...@nnrp04.earthlink.net...

HaimK

unread,
Sep 11, 2002, 1:07:06 PM9/11/02
to
"Jimmy Venema" jimmy....@philips.com said:

>You can also look at it from a different point of view, forget the namings
>and look at possible different concepts. Concepts have a direct impact on
>implementation the naming not.

This is the only correct approach. As Wittgenstein said, "only in the context
of a proposition has a name meaning", and these propositions in our environment
are the invariants that define relationship semantics.

I would only add that concepts have a direct impact on modeling and
specification, and then on implementation.

Both the "part-whole" relationship in general and its various subtypes were
defined in a precise and explicit manner. See, for example, various
international standards, such as the Reference Model of Open Distributed
Processing (RM-ODP) and the General Relationship Model (GRM), as well as
"Information modeling" by H.Kilov and J.Ross (Prentice-Hall, 1994), and, most
recently, "Business models" by H.Kilov. There were also many papers on these
issues, notably, in the UML context, the "black and white diamond" papers by
Brian Henderson-Sellers. Sorry for the marketing.

We have successfully used these concepts in business modeling for various happy
customers in finance, insurance, telecom, document management, etc. Some of
these customers wrote and published papers describing their experience.

-Haim Kilov
ha...@acm.org

H. S. Lahman

unread,
Sep 11, 2002, 1:23:06 PM9/11/02
to
Responding to Jones...


> Ok OO gods... I would appreciate your thoughts on the definitions of:
>
> - Containment
> - Composition
> - Aggregation


The problem is that they are not mutually exclusive. The only one of
those things that has a specific concrete interpretation is Composition
where the Part and Whole cannot exist independently within the scope of
referential integrity. UML has "fixed" the definitions in every release
with a remarkable lack of success at clarifying the intent (e.g., in
v1.4 it has weakened the interpretation of composition integrity).

As Daniel T.'s quote from Riel indicates, the boundaries are fuzzy
(e.g., contain/use is sort of orthogonal to aggregation/composition).
As a result the distinctions are more for the developer's ease of mind
in identifying relationships than they are for influencing the
implementation. IOW, they describe subtleties of problem space
description that are unlikely to affect the OOP implementation. (Except
for integrity constraints on Composition; most often it shows up as an
embedded class.)

So the bottom line is: don't worry about it. Select the view that seems
most consistent with the problem in hand and use that.

*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
h...@pathfindersol.com
Pathfinder Solutions -- We Make UML Work
http://www.pathfindersol.com
(888)-OOA-PATH


Uncle Bob (Robert C. Martin)

unread,
Sep 12, 2002, 12:26:43 AM9/12/02
to
This question cannot be answered in general. Unfortunately there is
no universally agreed standard for OO vocabulary. So, you must choose
a context in which to ask the question.

The context that many OO developers use is UML. In UML the words
Aggregation and Composition have meaning, but Containment does not.
In UML Aggregation is a "whole/part" relationship. Composition is
also a "whole/part" relationship with the whole having lifetime
responsibility for the part(s).

Robert C. Martin | "Uncle Bob"
Object Mentor Inc.| unclebob @ objectmentor . com
PO Box 5757 | Tel: (800) 338-6716
565 Lakeview Pkwy | Fax: (847) 573-1658 | www.objectmentor.com
Suite 135 | | www.XProgramming.com
Vernon Hills, IL, | Training and Mentoring | www.junit.org
60061 | OO, XP, Java, C++, Python |

You and I can enjoy the experience of not always seeing
eye-to-eye, but we can also respect each other, even when
you might find some idea of mine totally ludicrous.
-- Richard Riehle

Tom Jones

unread,
Sep 12, 2002, 9:23:50 PM9/12/02
to
I want to thank everyone for their articulate and coherent answers to my
question(s).

I most definitely now know that I knowing anything definitely pertaining to
OO vocabulary is definitely indefinite. :-)

I _think_ I have it now...

"Tom Jones" <tomjo...@hotmail.com> wrote in message
news:unth5j...@corp.supernews.com...

John Sheehy

unread,
Sep 13, 2002, 12:05:55 PM9/13/02
to
I'm with you Tom. I'm just as confused. As a means to helping me understand
Aggregation, could somebody show how aggregation would be implemented in
Java or C++. I'm using Embaradero Describe currently and have tried
generating Java code from three UML classes.

Let's say that the aggregate class was A with two Part (connected with the
aggregation relationship) classes P1 and P2.

I was expecting to see something like

class A
{
....
P1 _p1;
P2 _p2;
....
}

class P1
{
....
....
}

class P2
{
....
....
}

but no! There were no references in class A to the P1 or P2 classes.

How should these concepts be represented in an OO language assuming that
Describe may be wrong. If they can't be represented, what purpose do they
serve?

Thanks and Regards,
John.

"Tom Jones" <tomjo...@hotmail.com> wrote in message
news:unth5j...@corp.supernews.com...

Topmind

unread,
Sep 13, 2002, 2:02:06 PM9/13/02
to

Here is a table-fan's (relationalist's) view of this issue:

Relationships should be considered *relative*. The
relationships needed for one part/task/aspect/user
may not apply to another.

Procedural/relational tends to deal with relationships
at the *point of use*, rather than try to treat them
as a *global* design issue.

Take for example an invoice entity and invoice
line items. A code-centric construction may
resemble:

class line_item {.....}

class invoice_header {
private line_items is array of line_item
...
}

The problem with this is that you *must* go through
the parent object to get at the line items. Many
accesses to the the line items may have little or
*nothing* to do with the parent. For example, inventory
of items sold and sorted by item catalog number/description
(rather than invoice).

Thus, the above practice should be discouraged because
it tends to lock you into a single parent-centric
viewpoint. This also implies that "aggregation"
is generally frowned upon in a p/r view.
It is de-emphasized as a concept.

However, regarding "Life-time" (see Jimmy's text below),
there may be Referential Integrity rules that govern
life-times. For example, if you delete the invoice (parent),
then the line items also should be deleted in most
cases (either by actual enforcement or error messages).

But outside of ref. integr. rules, p/r's philosophy
tends to be different than OOP's in that the relationships
tend to be viewed as virtual, etherial, local, and as-needed
rather than hard-wired into the code structure and/or managed
via code. If you need to view things as nested parts, then
you simply issue relational formulas/commands that deliver
that view. The view is then purged when you are done with
it (except for any perm indexes, but the app developer
usually does not have to worry about those, and newer
DB's can do it automatically, at least according to the
brochures.)

Thus, those 3 terms are merely an instance-specific "viewpoint"
and not an absolute (global) modeling decision in p/r-thinking.

When OOP tries to deal with things in such a relativism-centric
way, it tends to try to recreate a hand-built database, and this is one
of the things that bothers me about OO modeling. I don't understand
how OO fans tolerate it. To me it is a mess to manage those in
code (using the structure of code). I don't get it.

-T-

Topmind

unread,
Sep 13, 2002, 2:11:07 PM9/13/02
to
>
> Those are good analogies. Does anyone know of a system that enforces the
> implications of "weak" containment, i.e., the car can only be in one parking
> lot at a time?
>

Relational databases with referential integrity rules and
regular association modeling (1-to-many, many-to-many, etc.)

In this case you could have something like:

Table: Car
-----------
CarID
OwnerFK
ModelFK
CurrentParkingSpotFK
...

(FK = foreign key, usually an ID)

There is only one slot for a parking lot ID, so
we can't put two or more in (unless we make another table
or keep our own list in app RAM for whatever reason).

(Note that "containment" may not be very meaningful in
relational land. See sister message.)

>
> Shayne Wissler
>

-T-

Uncle Bob (Robert C. Martin)

unread,
Sep 13, 2002, 6:05:42 PM9/13/02
to
It is remotely possible that on (or about) Fri, 13 Sep 2002 17:05:55
+0100, "John Sheehy" <spa...@pobox.com> might (or might not) have
written:

>I'm with you Tom. I'm just as confused. As a means to helping me understand
>Aggregation, could somebody show how aggregation would be implemented in
>Java or C++. I'm using Embaradero Describe currently and have tried
>generating Java code from three UML classes.
>
>Let's say that the aggregate class was A with two Part (connected with the
>aggregation relationship) classes P1 and P2.

---Association----

class A
{
private:
P1* itsP1;
P2* itsP2;
};


-----Aggregation-----
class A
{
private:
P1* itsP1;
P2* itsP2;
};

---Composition----
class A
{
public:
virtual ~A() {
delete itsP1;
delete itsP2;
}
private:
P1* itsP1;
P2* itsP2;
};

--or--

class A
{
private:
P1 itsP1;
P2 itsP2;
};

-------

In short, aggregation and association are indistinguishable at the
implementation level (except for one thing I'll mention below.)
Composition differs only in that the composite is responsible for the
lifetime of the parts. This responsibility is shown above with
deletes, but can be expressed in other ways too. For example, the
composite could pass the parts to some other responsible party.

The only real difference between association and aggregation is that
you cannot have a cycle of instances through aggregation relationships
(a part cannot be its own whole, either directly or transitively.
Thus:

class A
{
public:
void setA(A* a) {itsA = a;}
private:
A* itsA;
};

main()
{
A a1, a2;
a1.setA(&a2);
a2.setA(&a1); // illegal for aggregation.

Daniel T.

unread,
Sep 13, 2002, 8:07:25 PM9/13/02
to
In article <Cbog9.15451$zX3....@news.indigo.ie>,
"John Sheehy" <spa...@pobox.com> wrote:

> I'm with you Tom. I'm just as confused. As a means to helping me understand
> Aggregation, could somebody show how aggregation would be implemented in
> Java or C++. I'm using Embaradero Describe currently and have tried
> generating Java code from three UML classes.
>
> Let's say that the aggregate class was A with two Part (connected with the
> aggregation relationship) classes P1 and P2.
>
> I was expecting to see something like
>
> class A
> {
> ....
> P1 _p1;
> P2 _p2;
> ....
> }
>
> class P1
> {
> ....
> ....
> }
>
> class P2
> {
> ....
> ....
> }
>
> but no! There were no references in class A to the P1 or P2 classes.
>
> How should these concepts be represented in an OO language assuming that
> Describe may be wrong. If they can't be represented, what purpose do they
> serve?

There are different types of object relationships:

1) objects of class A create objects of class B.

2) objects of class A send messages to objects of class B.

3) Objects of class A have non-exclusive control over objects of class B.

4) (2) and objects of class A have exclusive control over objects of
class B.

What sort of relationship did you want between A, P1 and P2? Some people
consider Aggregate to mean (3) and some consider it to mean (4).

In Java both (3) and (4) would look the same. Namely:

class A {
private P1 _p1;
private P2 _p2;
}

The difference would be that in (4) the instances held by _p1 and _p2
would not be held or accessed by any other instance of any class (though
some other instance may have created them.)

In C++ things are a little more complicated, but only because of the
machinery needed to delete the objects when they are no longer needed.
Usually you end up with a situation such that in (4), A would be in
charge of deleting the P1 and P2 instances, whereas in (3) that job
would lie with some other class (a smart pointer, or parent of A, for
example.

These concepts are important precisely because they are not represented
in most/all OO languages, yet they are important to know at the design
level. It is hard to tell, when looking at code, how two objects might
relate to each other, but when writing the code, it is important to know
how they relate in order to write the code properly.

Uncle Bob (Robert C. Martin)

unread,
Sep 13, 2002, 10:07:05 PM9/13/02
to
It is remotely possible that on (or about) Sat, 14 Sep 2002 00:07:25
GMT, "Daniel T." <a@b.c> might (or might not) have written:

Just for some extra information, I'll describe each of Daniel's
relationships in terms of their UML equivalents.

>There are different types of object relationships:
>
>1) objects of class A create objects of class B.

In UML this is a <<creates>> association:

|A|-------------->|B|
<<creates>>


>
>2) objects of class A send messages to objects of class B.

In UML this is a navigable association:

|A|---------------->|B|


>
>3) Objects of class A have non-exclusive control over objects of class B.

I don't know what this means.

>4) (2) and objects of class A have exclusive control over objects of
>class B.

Or this. It sounds like you mean lifetime responsibility, but I'm not
sure. What kind of "control" are you referring to?

>What sort of relationship did you want between A, P1 and P2? Some people
>consider Aggregate to mean (3) and some consider it to mean (4).

In UML Aggregation is a special form of association that connotes
whole/part. UML does not define whole/part other than to say that an
instance of a part cannot be its own whole.


>In Java both (3) and (4) would look the same. Namely:
>
>class A {
> private P1 _p1;
> private P2 _p2;
>}

That's pretty much what (2) might look like too -- though (2) could
also be implemented with an argument.

public class A
{
public void f(B b) {b.f();}
}

In UML this is a <<parameter>> association between A and B:

|A|------------------>|B|
<<parameter>>

>The difference would be that in (4) the instances held by _p1 and _p2
>would not be held or accessed by any other instance of any class (though
>some other instance may have created them.)

UML doesn't make this kind of distinction between relationships. The
closest it comes is a relationship called Composition in which the
holding object is the only object with rights to delete the held
object. Other objects may, however, hold references to the object.

>In C++ things are a little more complicated, but only because of the
>machinery needed to delete the objects when they are no longer needed.
>Usually you end up with a situation such that in (4), A would be in
>charge of deleting the P1 and P2 instances, whereas in (3) that job
>would lie with some other class (a smart pointer, or parent of A, for
>example.

UML uses Composition to denote the relationship between the deleter
and the deleted.

>These concepts are important precisely because they are not represented
>in most/all OO languages, yet they are important to know at the design
>level. It is hard to tell, when looking at code, how two objects might
>relate to each other, but when writing the code, it is important to know
>how they relate in order to write the code properly.

This sounds like a contradiction. If the "proper" code depends upon
the type of relationship, then why can't you infer the relationship
from the "proper" code?

This particular contradiction leads me to the conclusion that if you
can't tell the difference in the code, then there is no worthwhile
difference in the relationship. A good example of this is the
difference between UML association and UML aggregation. You can't
usually look at a piece of source code and tell which of the two
relationships was present in the diagram. Therefore there is no
*practical* difference between the relationships.

I often see this contradiction manifest in people's diagrams. UML's
definition of aggregation is so weak that people can't believe it's as
similar as it is to association. So they make up new meanings for it.
As a result of that, I don't use aggregation in diagrams.

Daniel T.

unread,
Sep 14, 2002, 10:18:09 AM9/14/02
to
"Uncle Bob (Robert C. Martin)"
<u.n.c.l.e.b.o.b.@.o.b.j.e.c.t.m.e.n.t.o.r.d.o.t.c.o.m> wrote:

> It is remotely possible that on (or about) Sat, 14 Sep 2002 00:07:25
> GMT, "Daniel T." <a@b.c> might (or might not) have written:
>
> Just for some extra information, I'll describe each of Daniel's
> relationships in terms of their UML equivalents.

The notation I use most is on the inside back cover of "Design
Patterns". It's a variation of OMT.


> >There are different types of object relationships:
> >
> >1) objects of class A create objects of class B.
>
> In UML this is a <<creates>> association:
>
> |A|-------------->|B|
> <<creates>>

[A]- - - ->[B]

> >
> >2) objects of class A send messages to objects of class B.
>
> In UML this is a navigable association:
>
> |A|---------------->|B|

[A]------->[B]

> >
> >3) Objects of class A have non-exclusive control over objects of class B.
>
> I don't know what this means.

It means that object A holds a reference to object(s) of type B, but
other objects also may hold references or send messages to the B objects
being held.

[A]------->[B]

Yes the same notation as (2). I personally don't feel that there is a
useful distinction between the two. When using UML I denote this with
[A]<>---->[B]


> >4) (2) and objects of class A have exclusive control over objects of
> >class B.
>
> Or this. It sounds like you mean lifetime responsibility, but I'm not
> sure. What kind of "control" are you referring to?

It means that object A holds a reference to object(s) of type B, and no
other object is allowed to send messages or hold references to the B
objects being held. (Including other A objects)

[A]<>----->[B]

When using UML I denote this [A]<#>---->[B]. It doesn't quite map
correctly, but one must admit that a containment relationship generally
means no other object can hold a reference to the B object in question.


> >What sort of relationship did you want between A, P1 and P2? Some people
> >consider Aggregate to mean (3) and some consider it to mean (4).
>
> In UML Aggregation is a special form of association that connotes
> whole/part. UML does not define whole/part other than to say that an
> instance of a part cannot be its own whole.
>
>
> >In Java both (3) and (4) would look the same. Namely:
> >
> >class A {
> > private P1 _p1;
> > private P2 _p2;
> >}
>
> That's pretty much what (2) might look like too -- though (2) could
> also be implemented with an argument.

This would promote the relationship to (3). A holds a reference to a P1
and a P2 object. But as I said before, (2) and (3) are enough alike as
to not matter.


> >The difference would be that in (4) the instances held by _p1 and _p2
> >would not be held or accessed by any other instance of any class (though
> >some other instance may have created them.)
>
> UML doesn't make this kind of distinction between relationships. The
> closest it comes is a relationship called Composition in which the
> holding object is the only object with rights to delete the held
> object. Other objects may, however, hold references to the object.

I disagree with your last sentence. In Java if two objects both hold a
reference to a third, how can you say that only one of them has
"lifetime responsibility"?

Otherwise I agree with you, and this is a problem with UML. When we see
[A]<#>--->[B] in a UML diagram, we cannot make the design simplifying
assumption that [B] can be ignored at some higher level of design.


> >These concepts are important precisely because they are not represented
> >in most/all OO languages, yet they are important to know at the design
> >level. It is hard to tell, when looking at code, how two objects might
> >relate to each other, but when writing the code, it is important to know
> >how they relate in order to write the code properly.
>
> This sounds like a contradiction. If the "proper" code depends upon
> the type of relationship, then why can't you infer the relationship
> from the "proper" code?

I wasn't clear enough. You can infer the relationship from the "proper"
code, it's just not an easy thing to do. For example:

//Java
class A {
private B b;
public A(B aB) {
b = aB;
}
}

The above could be (using Riel's definition) a weak containment or a
strong containment. We can't tell without examining all the places where
an A object is created to determine if the B object is also being held
by some other object.

Uncle Bob (Robert C. Martin)

unread,
Sep 14, 2002, 3:31:55 PM9/14/02
to
It is remotely possible that on (or about) Sat, 14 Sep 2002 14:18:09

I'm sure you realize that is your personal convention and not the
official meaning of that particular notation in UML.

>> >4) (2) and objects of class A have exclusive control over objects of
>> >class B.
>>
>> Or this. It sounds like you mean lifetime responsibility, but I'm not
>> sure. What kind of "control" are you referring to?
>
>It means that object A holds a reference to object(s) of type B, and no
>other object is allowed to send messages or hold references to the B
>objects being held. (Including other A objects)
>
> [A]<>----->[B]
>
>When using UML I denote this [A]<#>---->[B]. It doesn't quite map
>correctly, but one must admit that a containment relationship generally
>means no other object can hold a reference to the B object in question.

In the UML concept of containment, other objects *are* in fact allowed
to hold reference to the contained objects, and to send message to
them, they just aren't allowed to delete them.


>
>
>> >What sort of relationship did you want between A, P1 and P2? Some people
>> >consider Aggregate to mean (3) and some consider it to mean (4).
>>
>> In UML Aggregation is a special form of association that connotes
>> whole/part. UML does not define whole/part other than to say that an
>> instance of a part cannot be its own whole.
>>
>>
>> >In Java both (3) and (4) would look the same. Namely:
>> >
>> >class A {
>> > private P1 _p1;
>> > private P2 _p2;
>> >}
>>
>> That's pretty much what (2) might look like too -- though (2) could
>> also be implemented with an argument.
>
>This would promote the relationship to (3). A holds a reference to a P1
>and a P2 object. But as I said before, (2) and (3) are enough alike as
>to not matter.
>
>
>> >The difference would be that in (4) the instances held by _p1 and _p2
>> >would not be held or accessed by any other instance of any class (though
>> >some other instance may have created them.)
>>
>> UML doesn't make this kind of distinction between relationships. The
>> closest it comes is a relationship called Composition in which the
>> holding object is the only object with rights to delete the held
>> object. Other objects may, however, hold references to the object.
>
>I disagree with your last sentence. In Java if two objects both hold a
>reference to a third, how can you say that only one of them has
>"lifetime responsibility"?

Lifetime responsibility in Java is an inverted concept. In C++ you
overtly destroy object. In Java you overtly prevent an object from
being destroyed. Some references in Java are not used for sending
messages and are intended to keep an object from being collected.
This is lifetime responsibility. Other objects hold references in
order to send messages, and then drop the references. This is not
lifetime *responsibility*, though there is certainly an element of
lifetime *control*.


>
>Otherwise I agree with you, and this is a problem with UML. When we see
>[A]<#>--->[B] in a UML diagram, we cannot make the design simplifying
>assumption that [B] can be ignored at some higher level of design.

True. It requires an interface to provide that kind of isolation in
UML -- and in source code.

|IA|
A
|
|A|----->|B|

Users use IA instead of A, and therefore never know about B.

Daniel T.

unread,
Sep 14, 2002, 4:27:07 PM9/14/02
to
"Uncle Bob (Robert C. Martin)"
<u.n.c.l.e.b.o.b.@.o.b.j.e.c.t.m.e.n.t.o.r.d.o.t.c.o.m> wrote:

> It is remotely possible that on (or about) Sat, 14 Sep 2002 14:18:09
> GMT, "Daniel T." <a@b.c> might (or might not) have written:
>

> >It means that object A holds a reference to object(s) of type B, but
> >other objects also may hold references or send messages to the B objects
> >being held.
> >
> > [A]------->[B]
> >
> >Yes the same notation as (2). I personally don't feel that there is a
> >useful distinction between the two. When using UML I denote this with
> >[A]<>---->[B]
>
> I'm sure you realize that is your personal convention and not the
> official meaning of that particular notation in UML.

Yes, I do. It is a convention I use, and I dare say it is a common
convention.


> >Otherwise I agree with you, and this is a problem with UML. When we see
> >[A]<#>--->[B] in a UML diagram, we cannot make the design simplifying
> >assumption that [B] can be ignored at some higher level of design.
>
> True. It requires an interface to provide that kind of isolation in
> UML -- and in source code.
>
> |IA|
> A
> |
> |A|----->|B|
>
> Users use IA instead of A, and therefore never know about B.

It may require an interface in UML but not in source code.

// C++
class A {
B b;
};

Because no member-functions of A allow external access to 'b', clients
of A have no logical coupling to the object held in 'b'. And if we use
the pimpl idiom, then there would be no physical coupling either.

In the Gamma's OMT, this would be represented as:

[A]<>--->[B]

This important concept cannot be properly represented in UML.

Uncle Bob (Robert C. Martin)

unread,
Sep 14, 2002, 5:53:39 PM9/14/02
to
It is remotely possible that on (or about) Sat, 14 Sep 2002 20:27:07

GMT, "Daniel T." <a@b.c> might (or might not) have written:

>> >It means that object A holds a reference to object(s) of type B, but
>> >other objects also may hold references or send messages to the B objects
>> >being held.
>> >
>> > [A]------->[B]
>> >
>> >Yes the same notation as (2). I personally don't feel that there is a
>> >useful distinction between the two. When using UML I denote this with
>> >[A]<>---->[B]
>>
>> I'm sure you realize that is your personal convention and not the
>> official meaning of that particular notation in UML.
>
>Yes, I do. It is a convention I use, and I dare say it is a common
>convention.

Frankly I haven't seen a regular pattern to the various usages of the
white diamond. I don't use it.

Uncle Bob (Robert C. Martin)

unread,
Sep 14, 2002, 5:55:13 PM9/14/02
to
It is remotely possible that on (or about) Sat, 14 Sep 2002 20:27:07

GMT, "Daniel T." <a@b.c> might (or might not) have written:

>> >Otherwise I agree with you, and this is a problem with UML. When we see

>> >[A]<#>--->[B] in a UML diagram, we cannot make the design simplifying
>> >assumption that [B] can be ignored at some higher level of design.
>>
>> True. It requires an interface to provide that kind of isolation in
>> UML -- and in source code.
>>
>> |IA|
>> A
>> |
>> |A|----->|B|
>>
>> Users use IA instead of A, and therefore never know about B.
>
>It may require an interface in UML but not in source code.
>
>// C++
>class A {
> B b;
>};
>
>Because no member-functions of A allow external access to 'b', clients
>of A have no logical coupling to the object held in 'b'. And if we use
>the pimpl idiom, then there would be no physical coupling either.

Logical coupling and physical coupling are different beasts. In C++,
anybody who wanted to use A would be physically coupled to B. And,
unfortunately, in C++ it's the physical couplings that count.

Daniel T.

unread,
Sep 14, 2002, 7:00:07 PM9/14/02
to
"Uncle Bob (Robert C. Martin)"
<u.n.c.l.e.b.o.b.@.o.b.j.e.c.t.m.e.n.t.o.r.d.o.t.c.o.m> wrote:

> It is remotely possible that on (or about) Sat, 14 Sep 2002 20:27:07
> GMT, "Daniel T." <a@b.c> might (or might not) have written:
>
> >> >Otherwise I agree with you, and this is a problem with UML. When we see
> >> >[A]<#>--->[B] in a UML diagram, we cannot make the design simplifying
> >> >assumption that [B] can be ignored at some higher level of design.
> >>
> >> True. It requires an interface to provide that kind of isolation in
> >> UML -- and in source code.
> >>
> >> |IA|
> >> A
> >> |
> >> |A|----->|B|
> >>
> >> Users use IA instead of A, and therefore never know about B.
> >
> >It may require an interface in UML but not in source code.
> >
> >// C++
> >class A {
> > B b;
> >};
> >
> >Because no member-functions of A allow external access to 'b', clients
> >of A have no logical coupling to the object held in 'b'. And if we use
> >the pimpl idiom, then there would be no physical coupling either.
>
> Logical coupling and physical coupling are different beasts. In C++,
> anybody who wanted to use A would be physically coupled to B. And,
> unfortunately, in C++ it's the physical couplings that count.

That is simply not true. As I said, using the pimpl idiom, there would
be no physical coupling. If you disagree with this, then I can only
assume that we mean different things when we say "physical coupling".

Phlip

unread,
Sep 14, 2002, 7:33:06 PM9/14/02
to
Daniel T. wrote:

> That is simply not true. As I said, using the pimpl idiom, there would
> be no physical coupling. If you disagree with this, then I can only
> assume that we mean different things when we say "physical coupling".

Daniel, I could have sworn I have unloaded my "pimpl is not a design
technique" lecture on you, but Google sez I haven't.

Here it is - excuse the prolixity, it targets a novice:

----8<------------------------------

Pimpl idiom is an emergency hack applied after-the-fact to rescue code
from a deadly long compile.

Properly factored code that follows good OO design principles can
naturally also follow good C++ construction principles.

Investigate this:

http://www.c2.com/cgi/wiki?DependencyInversionPrinciple

It sez (translated to C++) that if object A needs object B, then A should
have a pointer to an Abstract Base Class that B inherits. ABCs are classes
with only pure virtual functions. Therefor they can declare by name...

class Foo; // no body

class ABC {
virtual void doFoo (Foo);
};

...anything they need except their parent classes, which must also be
ABCs.

Doing it like this decouples the OO design and decouples the compile time
and #include file depth at the same time.

--
Phlip
http://www.greencheese.org/LucidScheming
-- Why is the "Cheesy Horror Movie Channel" called "SciFi"?? --

Uncle Bob (Robert C. Martin)

unread,
Sep 14, 2002, 8:08:48 PM9/14/02
to
It is remotely possible that on (or about) Sat, 14 Sep 2002 20:27:07

GMT, "Daniel T." <a@b.c> might (or might not) have written:

>In the Gamma's OMT, this would be represented as:


>
>[A]<>--->[B]
>
>This important concept cannot be properly represented in UML.

To represent it you'd use a stereotype.

|A|---------------->|B|
<<hides>>

And since, in UML, a stereotype allows you to use an icon, you can
replace the stereotyped relationship with your own icon:

|A|(X)----------------->|B|

Uncle Bob (Robert C. Martin)

unread,
Sep 14, 2002, 8:36:48 PM9/14/02
to
It is remotely possible that on (or about) Sat, 14 Sep 2002 23:00:07

Sorry, I missed the part about pImpl. You are correct that using
pImpl breaks the physical coupling. Of course the point is that in
C++ you have to do something extra, e.g. an interface or a pImpl, or
something. You can't simply have |A|--->|B| if you want clients of A
to be independent of B.

Daniel T.

unread,
Sep 15, 2002, 10:09:47 AM9/15/02
to
Phlip <phli...@yahoo.com> wrote:

> Daniel T. wrote:
>
> > That is simply not true. As I said, using the pimpl idiom, there would
> > be no physical coupling. If you disagree with this, then I can only
> > assume that we mean different things when we say "physical coupling".
>
> Daniel, I could have sworn I have unloaded my "pimpl is not a design
> technique" lecture on you, but Google sez I haven't.
>
> Here it is - excuse the prolixity, it targets a novice:
>
> ----8<------------------------------
>
> Pimpl idiom is an emergency hack applied after-the-fact to rescue code
> from a deadly long compile.
>
> Properly factored code that follows good OO design principles can
> naturally also follow good C++ construction principles.

Properly factored code that follows good OO (logical) design principles
do not necessarily also follow good C++ construction principles. An OO
design doesn't and shouldn't consider physical dependencies. OO designs
represent logical flow and coupling only. It is up to the programmer (or
translation engine in Mr. Lahmans case) to examine and reduce physical
dependencies.

>
> Investigate this:
>
> http://www.c2.com/cgi/wiki?DependencyInversionPrinciple

Philip,

Funny you "educating" me about the Dependency Inversion Principle. You
should know better than that. :-) I understand though, we are both
speaking to the masses here, not just to each other.

I'm kind of surprised though that you would advocate a more complex
design when there is a simpler thing that works. How un-XP of you. :-)

I just edited out a bunch of C++ code showing examples of what I mean.
If you want to get into it, maybe we can move this to a C++ forum or to
e-mail?

Uncle Bob (Robert C. Martin)

unread,
Sep 16, 2002, 12:00:41 AM9/16/02
to
It is remotely possible that on (or about) Sun, 15 Sep 2002 14:09:47

GMT, "Daniel T." <a@b.c> might (or might not) have written:

>An OO

>design doesn't and shouldn't consider physical dependencies. OO designs
>represent logical flow and coupling only. It is up to the programmer (or
>translation engine in Mr. Lahmans case) to examine and reduce physical
>dependencies.

I disagree with this, rather strongly. It's rather like saying that
an artist should not consider the texture of his paints. We use
physical tools to express logical systems. Those physical tools *all*
have limitations, and those limitation will have an effect upon the
logical design of the system. Even UML has an effect upon the design
of a system.

Consider the different role that inheritance plays in C++ vs
Smalltalk. The relationship has the same name, and roughly the same
definition. Yet it is used for remarkably different reasons. In C++
(or any statically typed language) inheritance is the mechanism of
polymorphism. In Smalltalk (or any dynamically typed language)
inheritance has nothing whatever to do with polymorphism.

These are physical issues. And yet they have a profound effect upon
the design of a system. Imagine trying to design a system and not
knowing the use to which inheritance will be put. You'd have to
eliminate inheritance from your design vocabulary because it would be
too ambiguous to use.

Now, clearly, you could invent a language like UML that defines
inheritance in its own terms (which just happen to align nicely with
the popular statically typed languages of the day) and then claim that
your UML designs are logical and are unaffected by physical issues.
But I think such claims are naive.

Daniel T.

unread,
Sep 16, 2002, 8:51:35 AM9/16/02
to
"Uncle Bob (Robert C. Martin)"
<u.n.c.l.e.b.o.b.@.o.b.j.e.c.t.m.e.n.t.o.r.d.o.t.c.o.m> wrote:

> It is remotely possible that on (or about) Sun, 15 Sep 2002 14:09:47
> GMT, "Daniel T." <a@b.c> might (or might not) have written:
>
> >An OO
> >design doesn't and shouldn't consider physical dependencies. OO designs
> >represent logical flow and coupling only. It is up to the programmer (or
> >translation engine in Mr. Lahmans case) to examine and reduce physical
> >dependencies.
>
> I disagree with this, rather strongly. It's rather like saying that
> an artist should not consider the texture of his paints. We use
> physical tools to express logical systems. Those physical tools *all*
> have limitations, and those limitation will have an effect upon the
> logical design of the system. Even UML has an effect upon the design
> of a system.

I think we are talking at two different levels. How about if I change my
comment to "An OO analysis doesn't and shouldn't consider physical
dependencies." Better? One man's high level is another man's low. :-)

> Consider the different role that inheritance plays in C++ vs
> Smalltalk. The relationship has the same name, and roughly the same
> definition. Yet it is used for remarkably different reasons. In C++
> (or any statically typed language) inheritance is the mechanism of
> polymorphism. In Smalltalk (or any dynamically typed language)
> inheritance has nothing whatever to do with polymorphism.
>
> These are physical issues. And yet they have a profound effect upon
> the design of a system. Imagine trying to design a system and not
> knowing the use to which inheritance will be put. You'd have to
> eliminate inheritance from your design vocabulary because it would be
> too ambiguous to use.

Let's think about this for a minute. As you rightly point out the word
"inheritance" means different things in SmallTalk and C++. I agree that
it affects the physical layout of the code, but what does it have to do
with logical flow?

If a UML shows us:

[A]<*>--->[<<abstract>>B]
A
|
[C]

It makes sense that the code would look different between SmallTalk and
C++, but does that change the meaning of the diagram? Do you really
think we must change the diagram above to account for the language
choice? I think not.

Uncle Bob (Robert C. Martin)

unread,
Sep 16, 2002, 6:29:18 PM9/16/02
to
It is remotely possible that on (or about) Mon, 16 Sep 2002 12:51:35

GMT, "Daniel T." <a@b.c> might (or might not) have written:

>"Uncle Bob (Robert C. Martin)"
> <u.n.c.l.e.b.o.b.@.o.b.j.e.c.t.m.e.n.t.o.r.d.o.t.c.o.m> wrote:
>
>> It is remotely possible that on (or about) Sun, 15 Sep 2002 14:09:47
>> GMT, "Daniel T." <a@b.c> might (or might not) have written:
>>
>> >An OO
>> >design doesn't and shouldn't consider physical dependencies. OO designs
>> >represent logical flow and coupling only. It is up to the programmer (or
>> >translation engine in Mr. Lahmans case) to examine and reduce physical
>> >dependencies.
>>
>> I disagree with this, rather strongly. It's rather like saying that
>> an artist should not consider the texture of his paints. We use
>> physical tools to express logical systems. Those physical tools *all*
>> have limitations, and those limitation will have an effect upon the
>> logical design of the system. Even UML has an effect upon the design
>> of a system.
>
>I think we are talking at two different levels. How about if I change my
>comment to "An OO analysis doesn't and shouldn't consider physical
>dependencies." Better? One man's high level is another man's low. :-)

I don't know what an OO analysis is. I've seen demonstrations of OO
analysis, each one different from the next. Some use UML as a kind of
natural language with classes as the nouns and "isa" and "hasa" as the
verbs. Others create ER diagrams suffused with state machines. Still
others draw use case diagrams augmented with sequence diagrams or
activity diagrams. Still others (I being one of them) don't think
that the terms OO and analysis are a good fit with each other.

>> Consider the different role that inheritance plays in C++ vs
>> Smalltalk. The relationship has the same name, and roughly the same
>> definition. Yet it is used for remarkably different reasons. In C++
>> (or any statically typed language) inheritance is the mechanism of
>> polymorphism. In Smalltalk (or any dynamically typed language)
>> inheritance has nothing whatever to do with polymorphism.
>>
>> These are physical issues. And yet they have a profound effect upon
>> the design of a system. Imagine trying to design a system and not
>> knowing the use to which inheritance will be put. You'd have to
>> eliminate inheritance from your design vocabulary because it would be
>> too ambiguous to use.
>
>Let's think about this for a minute. As you rightly point out the word
>"inheritance" means different things in SmallTalk and C++. I agree that
>it affects the physical layout of the code, but what does it have to do
>with logical flow?
>
>If a UML shows us:
>
>[A]<*>--->[<<abstract>>B]
> A
> |
> [C]
>
>It makes sense that the code would look different between SmallTalk and
>C++, but does that change the meaning of the diagram? Do you really
>think we must change the diagram above to account for the language
>choice? I think not.

If the diagram does not represent code, then what does the diagram
mean?

Daniel T.

unread,
Sep 16, 2002, 8:15:51 PM9/16/02
to

Robert, I get the feeling I'm being baited now... Are you asserting that
the meaning of the diagram does, in fact, change depending on what
language we are using?

Uncle Bob (Robert C. Martin)

unread,
Sep 17, 2002, 9:46:09 AM9/17/02
to
It is remotely possible that on (or about) Tue, 17 Sep 2002 00:15:51

GMT, "Daniel T." <a@b.c> might (or might not) have written:

>"Uncle Bob (Robert C. Martin)"
> <u.n.c.l.e.b.o.b.@.o.b.j.e.c.t.m.e.n.t.o.r.d.o.t.c.o.m> wrote:
>
>> It is remotely possible that on (or about) Mon, 16 Sep 2002 12:51:35
>> GMT, "Daniel T." <a@b.c> might (or might not) have written:
>> >

>> >If a UML shows us:
>> >
>> >[A]<*>--->[<<abstract>>B]
>> > A
>> > |
>> > [C]
>> >
>> >It makes sense that the code would look different between SmallTalk and
>> >C++, but does that change the meaning of the diagram? Do you really
>> >think we must change the diagram above to account for the language
>> >choice? I think not.
>>
>> If the diagram does not represent code, then what does the diagram
>> mean?
>
>Robert, I get the feeling I'm being baited now... Are you asserting that
>the meaning of the diagram does, in fact, change depending on what
>language we are using?

Let's back up. Your original assertion was that an OOD should not
consider physical couplings:

> "An OO design doesn't and shouldn't consider physical dependencies.
> OO designs represent logical flow and coupling only."

Now examine the diagram above. What is the logical flow of this
diagram? I find it difficult to express without considering physical
issues. What the diagram says is: "instances of class A send messages
to instances that conform to the interface of abstract class B."
Sending a message is a physical act that requires a physical coupling
between to physical objects. Indeed the very word "object" implies
something physical. The diagram also says: "instances of A control
the lifetime of the instances of B that they send messages to."
Again, this is a reference to the existence and management of physical
things.

How can I word the above diagram so as to remove all physical
concepts? I'm not sure it's possible. Indeed, I'm not at all sure
there is a meaningful definition of "logical flow" that is separate
from "physical dependency".

Now, some folks interpret the above diagram as:

A contains a B, and C is a B.

This statement contains nothing but physical dependencies. There is
no logical flow left it in at all.

Daniel T.

unread,
Sep 17, 2002, 12:17:48 PM9/17/02
to
In article <i0beou4eva7eru8qi...@4ax.com>,

"Uncle Bob (Robert C. Martin)"
<u.n.c.l.e.b.o.b.@.o.b.j.e.c.t.m.e.n.t.o.r.d.o.t.c.o.m> wrote:

> It is remotely possible that on (or about) Tue, 17 Sep 2002 00:15:51
> GMT, "Daniel T." <a@b.c> might (or might not) have written:
>
> >"Uncle Bob (Robert C. Martin)"
> > <u.n.c.l.e.b.o.b.@.o.b.j.e.c.t.m.e.n.t.o.r.d.o.t.c.o.m> wrote:
> >
> >> It is remotely possible that on (or about) Mon, 16 Sep 2002 12:51:35
> >> GMT, "Daniel T." <a@b.c> might (or might not) have written:
> >> >
> >> >If a UML shows us:
> >> >
> >> >[A]<*>--->[<<abstract>>B]
> >> > A
> >> > |
> >> > [C]
> >> >
> >> >It makes sense that the code would look different between SmallTalk and
> >> >C++, but does that change the meaning of the diagram? Do you really
> >> >think we must change the diagram above to account for the language
> >> >choice? I think not.
> >>
> >> If the diagram does not represent code, then what does the diagram
> >> mean?
> >
> >Robert, I get the feeling I'm being baited now... Are you asserting that
> >the meaning of the diagram does, in fact, change depending on what
> >language we are using?
>
> Let's back up. Your original assertion was that an OOD should not
> consider physical couplings:

I'm left without an answer to the question I asked. Do you believe that
the language used to implement the diagram above would change its
meaning? If yes, please explain.

A UML diagram does not, and should not deal with physical issues of C++
(such as which header files must be included in which source files) or
any other language. Are you challenging this assertion?

> > "An OO design doesn't and shouldn't consider physical dependencies.
> > OO designs represent logical flow and coupling only."
>
> Now examine the diagram above. What is the logical flow of this
> diagram? I find it difficult to express without considering physical
> issues. What the diagram says is: "instances of class A send messages
> to instances that conform to the interface of abstract class B."
> Sending a message is a physical act that requires a physical coupling
> between to physical objects.

Nothing in the diagram says that A must hold an instance of B, or that A
must call a member function of B. It simply says that A objects can
influence B objects state and/or extract information from the B object
in question. The B class shows what state may be influenced and what
information may be extracted. Nothing in the diagram says how these
objects know about each other, how the information is stored, or where
the objects exist. In fact, there could be a whole plethora of objects
between A and B that implement the message passing. For example, the A
object and B object may not even be in the same computer, the message
sending could be implemented using a TCP socket.

The diagram says there is a *logical* coupling between A and B, not a
physical one. IE A cannot do its job without access to a B object in
some form.

Nothing in the diagram says that we must have a B class or interface in
the code or that we must have a C class that extends or implements B, or
any other physical issues involved in Java or any other language's
inheritance hierarchy.

The diagram above says that a C object is fully substitutable for a B
object in any context where a B object is needed. This is a logical and
not physical concept.

Uncle Bob (Robert C. Martin)

unread,
Sep 17, 2002, 11:55:30 PM9/17/02
to
It is remotely possible that on (or about) Tue, 17 Sep 2002 16:17:48

Yes. In C++ the meaning of lifetime responsibility is completely
different than in Java, Ruby, or Python, etc. So the composition
relationship has a different meaning. In a C++ context A is
responsible for destroying B. In a Java context, A is responsible for
keeping B alive.

I'm not sure what to make of the <<abstract>> stereotype if my
language of implementation is python or ruby. Indeed, I may not need
class B at all. Class B may not really exist in those languages. It
might just be an artifact of the diagram that has no implementation.
In C++ or Java, however, B is definitely a physical entity.

If this is what Martin Fowler calls a "conceptual" diagram, and what
some people refer to as an OOA diagram, then the true implementation
language is English. A OwnsA B and C IsA B. This maps very nicely
to: Bob owns a dog and a pug is a dog. The meaning has almost nothing
to do with software whatever. (sadly enough, this last is probably
the primary use of UML in the industry.)

>
>A UML diagram does not, and should not deal with physical issues of C++
>(such as which header files must be included in which source files) or
>any other language. Are you challenging this assertion?

Of course I am. I completely disagree with it. In his book, "UML
Distilled" Martin Fowler identified three perspectives of UML diagram.
Conceptual, Specification, and Implementation. Conceptual diagram
have an implementation language similar to English. They are very
high level diagrams that have little to do with software and lots to
do with concepts. Specification diagrams are diagrams that describe
software at a high-ish level. They tend to describe the shape of
software without over-constraining the implementation. Implementation
diagrams are the kinds of diagrams that Rose would generate from code.
They are very detailed, and every item in them corresponds to
something in the code.

I think you are trying to make the argument that the specification
perspective should be implementation free. I don't feel that need,
nor do I think it's possible. The implementation language constrains
the design in ways that cannot be avoided IMHO.

>> > "An OO design doesn't and shouldn't consider physical dependencies.
>> > OO designs represent logical flow and coupling only."
>>
>> Now examine the diagram above. What is the logical flow of this
>> diagram? I find it difficult to express without considering physical
>> issues. What the diagram says is: "instances of class A send messages
>> to instances that conform to the interface of abstract class B."
>> Sending a message is a physical act that requires a physical coupling
>> between to physical objects.
>
>Nothing in the diagram says that A must hold an instance of B, or that A
>must call a member function of B. It simply says that A objects can
>influence B objects state and/or extract information from the B object
>in question.

At the conceptual level, this is true. However, at a conceptual level
we aren't really talking about software. (And, indeed, we have to
ignore most of the semantics of UML at this level).

At the Specification and Implementation perspective, I think the rules
of UML win out. UML says that an association between classes is
implemented by a "link" between objects; and a link is the channel
over which messages flow. Thus, if there is a composition association
from A to B, then A must send messages to B.

>The B class shows what state may be influenced and what
>information may be extracted. Nothing in the diagram says how these
>objects know about each other, how the information is stored, or where
>the objects exist.

True enough. However, the diagram does say that each instance of A
holds onto some kind of reference (be it a pointer, a java reference,
or a database key) to B. This is inescapable. There is some piece of
data that A holds on to that allows it to refer to B.

>In fact, there could be a whole plethora of objects
>between A and B that implement the message passing.

At the conceptual level, sure. Even at the specification level this
might be possible, though it would be odd. At the implementation
level it cannot be.

Even at the specification level, UML is pretty specific about how
relationships. If those relationships are going to be implemented by
other classes, then an association class is the appropriate notation.

|A|--------------------->|B|
.
.
|associationClass|

>For example, the A
>object and B object may not even be in the same computer, the message
>sending could be implemented using a TCP socket.

Sure. On the other hand, if you are going to use an ORB, or J2EE, or
some other infrastructure that allows this, you'll find the design
constrained by the physical realities of these infrastructures.

>The diagram says there is a *logical* coupling between A and B, not a
>physical one. IE A cannot do its job without access to a B object in
>some form.

That sounds physical to me. These objects must exist, and there must
be a relationship between them. And the designer must understand
physical realities like if there is a high cost of sending messages
(as in RMI) or a low cost.

>Nothing in the diagram says that we must have a B class or interface in
>the code or that we must have a C class that extends or implements B, or
>any other physical issues involved in Java or any other language's
>inheritance hierarchy.

This is true only at the conceptual level which, again, is not really
about software.

>The diagram above says that a C object is fully substitutable for a B
>object in any context where a B object is needed. This is a logical and
>not physical concept.

Slight correction. In your diagram, there is no such thing as a B
object. There are only objects that conform to B's interface.

Yes, the diagram says that C is substitutable for any function that
uses the B interface. What does that mean if you don't express it in
code?

Daniel T.

unread,
Sep 18, 2002, 7:58:56 AM9/18/02
to
"Uncle Bob (Robert C. Martin)"
<u.n.c.l.e.b.o.b.@.o.b.j.e.c.t.m.e.n.t.o.r.d.o.t.c.o.m> wrote:

> It is remotely possible that on (or about) Tue, 17 Sep 2002 16:17:48
> GMT, "Daniel T." <a@b.c> might (or might not) have written:

> >A UML diagram does not, and should not deal with physical issues of C++

> >(such as which header files must be included in which source files) or
> >any other language. Are you challenging this assertion?
>
> Of course I am. I completely disagree with it. In his book, "UML
> Distilled" Martin Fowler identified three perspectives of UML diagram.
> Conceptual, Specification, and Implementation. Conceptual diagram
> have an implementation language similar to English. They are very
> high level diagrams that have little to do with software and lots to
> do with concepts. Specification diagrams are diagrams that describe
> software at a high-ish level. They tend to describe the shape of
> software without over-constraining the implementation. Implementation
> diagrams are the kinds of diagrams that Rose would generate from code.
> They are very detailed, and every item in them corresponds to
> something in the code.
>
> I think you are trying to make the argument that the specification
> perspective should be implementation free. I don't feel that need,
> nor do I think it's possible. The implementation language constrains
> the design in ways that cannot be avoided IMHO.

OK, I see our disconnect. It is my belief that UML diagrams are
primaraly a tool for communication between people. As such when one
starts putting information in it that becomes programming language
spicific, one would be better off just communicating in that programming
language. Based on your XP tendencies, I think you could agree with that
yes? How about if I take the "does not" out of my origional assertion?

H. S. Lahman

unread,
Sep 18, 2002, 11:01:18 AM9/18/02
to
Responding to Martin...


>>>>If a UML shows us:
>>>>
>>>>[A]<*>--->[<<abstract>>B]
>>>> A
>>>> |
>>>> [C]
>>>>
>>>>It makes sense that the code would look different between SmallTalk and
>>>>C++, but does that change the meaning of the diagram? Do you really
>>>>think we must change the diagram above to account for the language
>>>>choice? I think not.
>>>>
>>>If the diagram does not represent code, then what does the diagram
>>>mean?
>>>
>>Robert, I get the feeling I'm being baited now... Are you asserting that
>>the meaning of the diagram does, in fact, change depending on what
>>language we are using?
>>
>
> Let's back up. Your original assertion was that an OOD should not
> consider physical couplings:
>
>
>>"An OO design doesn't and shouldn't consider physical dependencies.
>>OO designs represent logical flow and coupling only."
>>


First, let me say that I agree with you here. An OOD can consider
physical dependencies, as UML demonstrates with most of the explicit
relationship types being dependencies rather than association. However,
in an OOA model dependencies are irrelevant; dependency and composition
relationships are not included in the Executable UML profile for PIMs.

[FWIW, I think the dependency relationship in the OOD is an anachronism.
If the OOD is so detailed that it deals with dependencies explicitly
it is usurping the prerogatives of OOP (i.e., it assumes one does OOP
with a reasonably intelligent Orangutan and a large bag of bananas).
But let's not go there.]


>
> Now examine the diagram above. What is the logical flow of this
> diagram? I find it difficult to express without considering physical
> issues. What the diagram says is: "instances of class A send messages
> to instances that conform to the interface of abstract class B."
> Sending a message is a physical act that requires a physical coupling
> between to physical objects. Indeed the very word "object" implies
> something physical. The diagram also says: "instances of A control
> the lifetime of the instances of B that they send messages to."
> Again, this is a reference to the existence and management of physical
> things.


I also agree that there are two implied dependencies here. One is the
composition itself, which implies a dependence in lifecycles between A
and B. The second is the directionality of the relationship. But both
of these notions are OOD notions, not OOA notions.

The problem I have is with your interpretation of the relationship
itself. Even a Composition relationship is strictly logical in the
sense that it describes the structure of set members' logical connection
across different sets. As such it describes a join of sets and is
completely orthogonal to message passing.

While it is true one usually uses that structure to constrain addressing
messages and the modeling idiom is "relationship navigation", that
addressing and navigation is just a *use* of the existing logical
relationship between the sets. (Note that your downcasting example
demonstrates that one needn't navigate a constrained relationship to
address a message.)

Nor does it say anything about interfaces and coupling. In fact, it
says nothing even about which specific members of the sets are logically
related.

Nor does the diagram say that A controls the lifecycle of B instances.
All it says is that an A instance cannot exist without a logically
related B instance and a B instance cannot exist without a logically
related A instance. How that is ensured is not necessarily up to A;
anyone could do it.

More importantly, this constraint is a good example of the difference
between a logical relationship and a physical one. For example, in a
language supporting garbage collection, both A and B instances may
survive physically for an arbitrarily long time after the logical
relationship is dissolved. IOW, the constraint is about logical
accessibility and referential integrity, not physical existence.

Finally, I find the notion of an object being a physical entity
disturbing. For one thing, an object can be purely conceptual (e.g.,
Marriage, Arbitration, etc.). A member of a class abstracted from a
concept is still a concept.

But even if the underlying problem space entity is something concrete,
the OO software object is still an abstraction that just represents it.
Abstractions are, by their nature, not physical. Ultimately the
abstraction will be manifested as an organized collection of 1s and 0s,
but until then there is nothing physical about it. Because abstraction
is the core of OT I think it is dangerous not to keep that in mind.


*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
h...@pathfindersol.com
Pathfinder Solutions -- We Make UML Work
http://www.pathfindersol.com
(888)-OOA-PATH


Uncle Bob (Robert C. Martin)

unread,
Sep 18, 2002, 1:33:50 PM9/18/02
to
It is remotely possible that on (or about) Wed, 18 Sep 2002 11:58:56

GMT, "Daniel T." <a@b.c> might (or might not) have written:

>OK, I see our disconnect. It is my belief that UML diagrams are

>primaraly a tool for communication between people. As such when one
>starts putting information in it that becomes programming language
>spicific, one would be better off just communicating in that programming
>language. Based on your XP tendencies, I think you could agree with that
>yes? How about if I take the "does not" out of my origional assertion?

My XP tendencies do not lead me away from UML. I use UML a lot. I
use it to communicate with other developers about the structure of the
code I am thinking of writing. I use it to brainstorm by myself. I
use it to explain previously written code to others. When I use UML
it is almost always as a model of code.

Uncle Bob (Robert C. Martin)

unread,
Sep 18, 2002, 2:00:45 PM9/18/02
to
It is remotely possible that on (or about) Wed, 18 Sep 2002 15:01:18
GMT, "H. S. Lahman" <vze2...@verizon.net> might (or might not) have
written:

>Responding to Martin...


>
>
>>>>>If a UML shows us:
>>>>>
>>>>>[A]<*>--->[<<abstract>>B]
>>>>> A
>>>>> |
>>>>> [C]
>>>>>

>


>The problem I have is with your interpretation of the relationship
>itself. Even a Composition relationship is strictly logical in the
>sense that it describes the structure of set members' logical connection
>across different sets. As such it describes a join of sets and is
>completely orthogonal to message passing.

According to the UML docs, an association represents a link between
instances, and a link between instances is used for sending messages.

>Nor does it say anything about interfaces and coupling. In fact, it
>says nothing even about which specific members of the sets are logically
>related.

I think the <<abstract>> stereotype (which is not a standard UML
stereotype BTW) suggests that B has an interface that is usable by A
and implemented by C.

>Nor does the diagram say that A controls the lifecycle of B instances.

According to the UML docs, lifetime responsibility is the definition
of the composition relationship used in the diagram above.

>All it says is that an A instance cannot exist without a logically
>related B instance and a B instance cannot exist without a logically
>related A instance.

It does say that (well not quite, but I'll get to that), but that has
nothing to do with composition. That simply has to do with the fact
that the default multiplicity on an association end is 1. I could
express the same concept without composition as:

|A|-------->|B|
1 1

Actually the diagram says nothing about B requiring the existence of
A. The presence of the arrowhead indicates that A instances can
navigate to B instances, but that B instances cannot navigate back to
A instances. Thus, B instances do not require the existence of A
instances.

>Finally, I find the notion of an object being a physical entity
>disturbing. For one thing, an object can be purely conceptual (e.g.,
>Marriage, Arbitration, etc.). A member of a class abstracted from a
>concept is still a concept.

An object is something that takes physical space in a computer. It
consumes physical execution cycles. And it is represented by physical
source code. It is *this* kind of physicality that needs to be
managed and considered by the designers, an constrains the use of UML
to describe the design.

Universe

unread,
Sep 18, 2002, 6:31:08 PM9/18/02
to
RCMartin wrote:

> Now examine the diagram above. What is the logical flow of this
> diagram? I find it difficult to express without considering physical
> issues. What the diagram says is: "instances of class A send messages
> to instances that conform to the interface of abstract class B."
> Sending a message is a physical act that requires a physical coupling
> between to physical objects. Indeed the very word "object" implies
> something physical.

"Implies" to you perhaps, but it's not true.

Objects may be partial or complete units of thought, ideas, concepts, etc.

Elliott
--
http://www.radix.net/~universe ~*~ Enjoy! ~*~
Hail OO Modelling! * Hail the Wireless Web!
@Elliott 2002 my comments ~ newsgroups+bitnet OK

H. S. Lahman

unread,
Sep 19, 2002, 12:11:06 PM9/19/02
to
Responding to Martin...


>>The problem I have is with your interpretation of the relationship
>>itself. Even a Composition relationship is strictly logical in the
>>sense that it describes the structure of set members' logical connection
>>across different sets. As such it describes a join of sets and is
>>completely orthogonal to message passing.
>>
>
> According to the UML docs, an association represents a link between
> instances, and a link between instances is used for sending messages.


And the operative phrase is "used for". The relationship or logical
link exists on its own merits; it simply provides constraints for
addressing messages.


>
>
>>Nor does it say anything about interfaces and coupling. In fact, it
>>says nothing even about which specific members of the sets are logically
>>related.
>>
>
> I think the <<abstract>> stereotype (which is not a standard UML
> stereotype BTW) suggests that B has an interface that is usable by A
> and implemented by C.


I have no idea what the <<abstract>> stereotype is. I did a word search
on the v1.4 spec and could not find it. [I also did a word search on
'composition' and Acrobat didn't find that either, though there were a
couple. Evidently Acrobat has a problem with italics.]


>
>
>>Nor does the diagram say that A controls the lifecycle of B instances.
>>
>
> According to the UML docs, lifetime responsibility is the definition
> of the composition relationship used in the diagram above.


The actual quote (3.48.1) is:

"Composite aggregation is a strong form of aggregation which [sic]
requires that a part instance be included in at most one composite at a
time and that the composite object has sole responsibility for
disposition of the parts. The multiplicity of the aggregate end may not
exceed one (it is unshared)."

Note that this is where UML has loosened the definition in v1.4 by
including the "at a time" phrase. If a Part can be a participant in a
different composite aggregation at some other time, then clearly the
'disposition' cannot include deletion in that situation. (Personally I
think UML dropped the ball here by raising more issues than they
clarified -- see below.)

But however one interprets 'disposition', UML seems to be giving the
aggregate responsibility for at least instantiating and deinstantiating
the relationship. So you get points here vis a vis UML's view.

However, I don't like that at all because it overly constrains the
relationship semantics to a particular situation (i.e., where the part
has no relationships to an object except the aggregate) without any
compensation. For example:

* 1 *
A <*>--------- B ---------- C

could easily arise if B is not tied to A's lifecycle. But it is rather
unlikely that A would have responsibility for managing any of the
relationships. Those relationships provide complex constraints for a
complicated collaboration and it is unlikely that any one of those
objects should have that sort of Big Picture view. The instantiation
responsibility would most likely reside in some third party object with
responsibility for understanding that sort of semantics (e.g., a
Factory). So one could not usually use composition in the very cases
they seem to have loosened the definition to address.


>
>
>>All it says is that an A instance cannot exist without a logically
>>related B instance and a B instance cannot exist without a logically
>>related A instance.
>>
>
> It does say that (well not quite, but I'll get to that), but that has
> nothing to do with composition. That simply has to do with the fact
> that the default multiplicity on an association end is 1. I could
> express the same concept without composition as:
>
> |A|-------->|B|
> 1 1


But that doesn't convey the "strong form of aggregation" that
composition is supposed to convey, which means...


>
> Actually the diagram says nothing about B requiring the existence of
> A. The presence of the arrowhead indicates that A instances can
> navigate to B instances, but that B instances cannot navigate back to
> A instances. Thus, B instances do not require the existence of A
> instances.


...this is where "at a time" has screwed things up. By eliminating the
constraint that the lifecycles of both participants are tied together it
is no longer very strong. One is only left with the fact that the
multiplicity on the aggregate side must always be 1. That's a special
case, not a strong form. (Clearly requiring that the aggregate manage
the relationship is a strong form, but that just eliminates using
composition in some situations where it would be a useful to convey
problem space ideas since the lifecycles are no longer tied together.)

Before the loosening composition had a valid interpretation: that the
part object could be embedded in the aggregate object's implementation.
That only works if the part has no relationships with other objects,
but it is very handy for computing space data structures like Array. In
that situation it makes sense for the aggregate to manage the
relationships. But now that the lifecycles are not tied together one
still has to make the same tactical decision during OOP as one would
have to make with a simple aggregation.


>
>
>>Finally, I find the notion of an object being a physical entity
>>disturbing. For one thing, an object can be purely conceptual (e.g.,
>>Marriage, Arbitration, etc.). A member of a class abstracted from a
>>concept is still a concept.
>>
>
> An object is something that takes physical space in a computer. It
> consumes physical execution cycles. And it is represented by physical
> source code. It is *this* kind of physicality that needs to be
> managed and considered by the designers, an constrains the use of UML
> to describe the design.


The physical representation of an object in a Turing machine is an
issue, at best, for an OOPL compiler developer or language designer. A
developer of OO applications is not at all concerned with that
representation. In fact, the OOPLs have already screwed up this
separation of concerns by doing things like directly mapping attributes
to storage types.

[In fairness the OOPLs have to make compromises with Turing. My problem
is that they didn't do it indirectly. The OOP developer should be able
to think of the problem solution entirely in terms of attribute ADTs.
The mapping of those ADTs to storage types could have been done
separately (e.g., a separate input file to the compiler using
conventions similar to typedef). It should also be possible to provide
that specification more generically in terms of data domains so that the
compiler is free to optimize actual storage.]

Willard Thompson

unread,
Sep 19, 2002, 1:26:11 PM9/19/02
to
"Tom Jones" <tomjo...@hotmail.com> wrote in message news:<unth5j...@corp.supernews.com>...
> I have asked a number of OO developers the difference between these 3 terms.
>
> This is my synthesized take on their meanings (correct me if I am wrong):
>
> The consensus is that composition and containment are synonymous.
>
> Composition infers a "has-a" relationship. A car "has-a" engine. A
> lifetime is also inferred by composition. If the car goes away, the engine
> goes away.
>
> Almost everyone I talked to has a different definition for aggregation (or
> they had no definition at all). Some people said that aggregation is just
> like containment, in that the aggregator "contains" or holds the aggregatee.
> The analogy I heard was that "an airport is a holding place for airplanes,
> so the airport is said to 'aggregatee airplanes'". Also, the lifetimes of
> the aggregator and agregatee are not tied as they are in composition.
>
> Of course this contradicts my assertion above that composition and
> containment are the same thing.
>
> Is it only composition if the enclosing class actually creates the contained
> object?
>
> Ok OO gods... I would appreciate your thoughts on the definitions of:
>
> - Containment
> - Composition
> - Aggregation
>
> as they pertain to OOD.
>
> Thanks,
> Tom

I've posted to this subject before. If you get a chance check that
out. However, I'll give you the quick and short version. Take it for
what it's worth.

I call the 3 relationships "Association", "Aggregation" and
"Composition" where:

1. *Association* means object A uses object B where A can live without
B, for instance, a baseball player object uses a bat object but
doesn't the baseball player doesn't need a bat when playing defense.

2. (weak) *Aggregation* (containment) means object A has an object B
that can be removed/discrete, for instance, a microwave is still a
microwave even if it doesn't have food in it.

3. *Composition* (strong aggregation) means object A is made up of
object B (and others), for instance, a car is not a car without its
engine therefore the car is composed of many parts namely an engine.

Sometimes it might be more meaningful to have just two relationships 1
and 2 together and 3. Some people might view 1 and 2 together as
being one because they only look at the fact that it is a discrete
relationship. Where as in 3 above it's not.

Anyway, this helps me distinguish (UML) semantics. Remember, this is
subjective i.e. it's a benefit as well as a drawback when trying to
optimize (say a design). Ultimately, it depends on the context of
your project. Hope I can shed some light.

Regards,
--Willard

Daniel T.

unread,
Sep 19, 2002, 5:37:35 PM9/19/02
to
> > I think the <<abstract>> stereotype (which is not a standard UML
> > stereotype BTW) suggests that B has an interface that is usable by A
> > and implemented by C.
>
>
> I have no idea what the <<abstract>> stereotype is. I did a word search
> on the v1.4 spec and could not find it. [I also did a word search on
> 'composition' and Acrobat didn't find that either, though there were a
> couple. Evidently Acrobat has a problem with italics.]

I may be wrong, but in UML you may represent a class name in italics,
when the class name is in italics, the class is considred an "abstract"
class. Is this not true? I'm pretty sure it *used* to be there.

Uncle Bob (Robert C. Martin)

unread,
Sep 19, 2002, 7:00:35 PM9/19/02
to
It is remotely possible that on (or about) Thu, 19 Sep 2002 21:37:35
GMT, "Daniel T." <a@b.c> might (or might not) have written:

Yes, that is a UML convention. The <<abstract>> stereotype is not.
In UML the official way to denote that a class is abstract is to
include the {abstract} property:

+--------------------+
| Shape |
| {abstract}|
+--------------------+

Uncle Bob (Robert C. Martin)

unread,
Sep 19, 2002, 7:15:36 PM9/19/02
to
It is remotely possible that on (or about) 19 Sep 2002 10:26:11
-0700, wil...@bletchleypark.net (Willard Thompson) might (or might
not) have written:

>I've posted to this subject before. If you get a chance check that


>out. However, I'll give you the quick and short version. Take it for
>what it's worth.
>
>I call the 3 relationships "Association", "Aggregation" and
>"Composition" where:
>
>1. *Association* means object A uses object B where A can live without
>B, for instance, a baseball player object uses a bat object but
>doesn't the baseball player doesn't need a bat when playing defense.

Association means that the objects send messages to each other. If
the association is "navigable" (i.e. it has an arrowhead) then
messages can only be sent in one direction.

There are several stereotyped forms of association. Normal
association is a "data relationship" (to quote Rumaugh) which means
that some piece of data is used to hold a reference, or pointer, or
key, to the object we will be sending messages to. If the
<<parameter>> stereotype is used, then we will be sending messages to
the argument of a function. If the <<local>> stereotype is used, then
we will be sending messages to a variable that is local to the current
method. If the <<global>> stereotype is used, we will be sending
messages to a global variable.


>
>2. (weak) *Aggregation* (containment) means object A has an object B
>that can be removed/discrete, for instance, a microwave is still a
>microwave even if it doesn't have food in it.

UML defines aggregation as "whole/part"; but does not provide much
more of a definition than that. (with one exception that I'll discuss
below). Note that it is hard to tell the difference between 1 and 2
above. A microwave is a microwave even if it doesn't have food in it;
but a baseball player is still a baseball player even if he doesn't
have a bat. The two concepts don't seem different.

In UML association differs from aggregation in that cycles are not
permitted in the instance graph. Any object can be associated with
itself, but an object may not be aggregated with itself. Nor can it
be aggregated with itself through a long cycle of aggregations.


>
>3. *Composition* (strong aggregation) means object A is made up of
>object B (and others), for instance, a car is not a car without its
>engine therefore the car is composed of many parts namely an engine.

In UML composition is a form of aggregation in which the composite has
responsibility for the lifetime of the component. The term "lifetime
responsibility" does not mean that the composite either creates nor
destroys the component. It just means that the composite is
responsible for making decisions that result in the eventual
destruction of the component. Thus, a composite can pass a component
to another composite.

Composites are fully capable of existing without any components. The
diagram below is quite legal:

|A|<#>---------->|B|
0..1

It simply means that an instance of A holds an instance of B, then the
A instance takes responsibility for the lifetime of B.

Lifetime responsibility implies copy responsibility. If someone makes
a copy of a composite, that composite must make copies of all the
components. If the copies weren't made, then the copied composite
would share lifetime responsibility for the same components as the
original -- and UML does not allow a component to have more than one
composite at a time.

Daniel T.

unread,
Sep 19, 2002, 7:17:12 PM9/19/02
to
"H. S. Lahman" <vze2...@verizon.net> wrote:

> Responding to Martin...

> >>Nor does the diagram say that A controls the lifecycle of B instances.
> >>
> >
> > According to the UML docs, lifetime responsibility is the definition
> > of the composition relationship used in the diagram above.
>
>
> The actual quote (3.48.1) is:
>
> "Composite aggregation is a strong form of aggregation which [sic]
> requires that a part instance be included in at most one composite at a
> time and that the composite object has sole responsibility for
> disposition of the parts. The multiplicity of the aggregate end may not
> exceed one (it is unshared)."

I think the "it is unshared" is the key here.

[A]<*>----[B]

means that for any particluar B object, only one object is allowed to
hold a pointer to it. This naturally implies lifetime responsibility.
There must be some mechinism in place to ensure that the B object is
removed from the system before the A object releases its link...

> Note that this is where UML has loosened the definition in v1.4 by
> including the "at a time" phrase. If a Part can be a participant in a
> different composite aggregation at some other time, then clearly the
> 'disposition' cannot include deletion in that situation. (Personally I
> think UML dropped the ball here by raising more issues than they
> clarified -- see below.)

I don't agree. The link has more to do with access rights than lifetime
this way.

I think it still does, for example:

[A]<*>--->[B]<---<*>[C]

has a very different meaning than:

[A]------>[B]<------[C]

In the latter an A object and a C object could both share a B object, in
the former, that is not the case.

Uncle Bob (Robert C. Martin)

unread,
Sep 20, 2002, 12:43:45 AM9/20/02
to
It is remotely possible that on (or about) Thu, 19 Sep 2002 23:17:12
GMT, "Daniel T." <a@b.c> might (or might not) have written:

>"H. S. Lahman" <vze2...@verizon.net> wrote:
>
>> Responding to Martin...
>
>> >>Nor does the diagram say that A controls the lifecycle of B instances.
>> >>
>> >
>> > According to the UML docs, lifetime responsibility is the definition
>> > of the composition relationship used in the diagram above.
>>
>>
>> The actual quote (3.48.1) is:
>>
>> "Composite aggregation is a strong form of aggregation which [sic]
>> requires that a part instance be included in at most one composite at a
>> time and that the composite object has sole responsibility for
>> disposition of the parts. The multiplicity of the aggregate end may not
>> exceed one (it is unshared)."
>
>I think the "it is unshared" is the key here.
>
>[A]<*>----[B]
>
>means that for any particluar B object, only one object is allowed to
>hold a pointer to it. This naturally implies lifetime responsibility.

With the exception that any object can have an association or
aggregation with that instance of B. It is only the composition
relationship that must be unique.

>There must be some mechinism in place to ensure that the B object is
>removed from the system before the A object releases its link...

Or rather, A must see to it that B is either destroyed, or passed to
another object that will take responsibility.

>> Before the loosening composition had a valid interpretation: that the
>> part object could be embedded in the aggregate object's implementation.

Just a nit. I don't recall a "loosening". As I recall, from the very
early days of UML, the intent was *always* that composites could pass
components one to another. The embedding of one instance within
another (i.e. C++ classes holding other instances by value) was only
one possible interpretation of composition. It was never intended to
be the sole interpretation.

>
>I think it still does, for example:
>
>[A]<*>--->[B]<---<*>[C]
>
>has a very different meaning than:
>
>[A]------>[B]<------[C]
>
>In the latter an A object and a C object could both share a B object, in
>the former, that is not the case.

In the former, the A and C instance cannot share the same B instance
*at the same time*. But they can pass that B instance back and forth
to each other.

Daniel T.

unread,
Sep 20, 2002, 9:00:19 AM9/20/02
to
"Uncle Bob (Robert C. Martin)"
<u.n.c.l.e.b.o.b.@.o.b.j.e.c.t.m.e.n.t.o.r.d.o.t.c.o.m> wrote:

> It is remotely possible that on (or about) Thu, 19 Sep 2002 23:17:12
> GMT, "Daniel T." <a@b.c> might (or might not) have written:
>
> >"H. S. Lahman" <vze2...@verizon.net> wrote:
> >
> >> Responding to Martin...
> >
> >> >>Nor does the diagram say that A controls the lifecycle of B instances.
> >> >>
> >> >
> >> > According to the UML docs, lifetime responsibility is the definition
> >> > of the composition relationship used in the diagram above.
> >>
> >>
> >> The actual quote (3.48.1) is:
> >>
> >> "Composite aggregation is a strong form of aggregation which [sic]
> >> requires that a part instance be included in at most one composite at a
> >> time and that the composite object has sole responsibility for
> >> disposition of the parts. The multiplicity of the aggregate end may not
> >> exceed one (it is unshared)."
> >
> >I think the "it is unshared" is the key here.
> >
> >[A]<*>----[B]
> >
> >means that for any particluar B object, only one object is allowed to
> >hold a pointer to it. This naturally implies lifetime responsibility.
>
> With the exception that any object can have an association or
> aggregation with that instance of B. It is only the composition
> relationship that must be unique.

If other objects hold a reference to the B object, then the A object
cannot be said to have "sole responsibility" for its "disposition".

Before Booch and Rumbaugh got together, we had OMT's "uses", and
"aggregation" and Booch's "uses", "has(shared)", and "has(unshared)". I
think UML's "uses", "aggregation", & "composition" were meant to map
onto Booch's association types.

The whole point here is that at some higher level, we want it so that
[B] can be ignored. If we allow just anybody to connect to it once it is
in the composition relationship, we loose that divide.

I realize that none of this is imposed by the strict definition of
"Composition" in UML. That's why I generally don't use UML, preferring
instead something that is better suited to my design philosophy.

> >There must be some mechanism in place to ensure that the B object is

> >removed from the system before the A object releases its link...
>
> Or rather, A must see to it that B is either destroyed, or passed to
> another object that will take responsibility.

Agreed.

> >
> >I think it still does, for example:
> >
> >[A]<*>--->[B]<---<*>[C]
> >
> >has a very different meaning than:
> >
> >[A]------>[B]<------[C]
> >
> >In the latter an A object and a C object could both share a B object, in
> >the former, that is not the case.
>
> In the former, the A and C instance cannot share the same B instance
> *at the same time*. But they can pass that B instance back and forth
> to each other.

Agreed.

H. S. Lahman

unread,
Sep 20, 2002, 10:53:27 AM9/20/02
to
Responding to Daniel T....


>>The actual quote (3.48.1) is:
>>
>>"Composite aggregation is a strong form of aggregation which [sic]
>>requires that a part instance be included in at most one composite at a
>>time and that the composite object has sole responsibility for
>>disposition of the parts. The multiplicity of the aggregate end may not
>>exceed one (it is unshared)."
>>
>
> I think the "it is unshared" is the key here.
>
> [A]<*>----[B]
>
> means that for any particluar B object, only one object is allowed to
> hold a pointer to it. This naturally implies lifetime responsibility.
> There must be some mechinism in place to ensure that the B object is
> removed from the system before the A object releases its link...


As I read the unshared part it means that a B can only participate in
one aggregate at a time. without the lifecycle constraint one can
reinstantiate the relationship so that B participates with some other
aggregate.

This is just a variant on substitution in a 1:1 relationship. In

1 1
A ---------- B

every B must always be related to an A but it doesn't have to be the
same A throughout the execution. However, this is also "unshared"
because B can't be related to two+ As at any time.


>
>
>>Note that this is where UML has loosened the definition in v1.4 by
>>including the "at a time" phrase. If a Part can be a participant in a
>>different composite aggregation at some other time, then clearly the
>>'disposition' cannot include deletion in that situation. (Personally I
>>think UML dropped the ball here by raising more issues than they
>>clarified -- see below.)
>>
>
> I don't agree. The link has more to do with access rights than lifetime
> this way.


I would agree an extent. With the lifecycle constraint B was
essentially a private part of A's implementation. That restricted
access more than the current definition (see below).


But this is a no-no under both the old and new definitions because B
can't be shared by two aggregates at the same time.


>
> has a very different meaning than:
>
> [A]------>[B]<------[C]
>
> In the latter an A object and a C object could both share a B object, in
> the former, that is not the case.


If one embeds B in A then it is part of A's implementation. Allowing C
to access it breaks the encapsulation (i.e., implementation hiding) of
A. Therefore one should never embed an object when it has *any* sort of
relationship to a third object. That combined with the removal of the
lifecycle constraint means that, in effect

1
A --------> B <------- C

and

A <*>-----> B <------- C

are identical in that the OOP level implementation decisions are exactly
the same. More importantly,

A <*>-----> B // i.e., other objects relate only to A

and

1
A --------> B

also have identical OOP decisions. That is, whether B is related to a
different A in its life determines whether embedding is appropriate in
both cases. Thus there seems to be no point in having the composition
relationship anymore because it provides no useful additional
specification information for OOP.

H. S. Lahman

unread,
Sep 20, 2002, 11:14:51 AM9/20/02
to
Responding to Martin...


>>>Before the loosening composition had a valid interpretation: that the
>>>part object could be embedded in the aggregate object's implementation.
>>>
>
> Just a nit. I don't recall a "loosening". As I recall, from the very
> early days of UML, the intent was *always* that composites could pass
> components one to another. The embedding of one instance within
> another (i.e. C++ classes holding other instances by value) was only
> one possible interpretation of composition. It was never intended to
> be the sole interpretation.


It is a loosening in the sense that the coincident lifecycle constraint
has been removed.

I don't recall anything about passing components. That's a bad idea in
general because it is the worst form of coupling. A composite mitigates
that only because of the carnal knowledge of one another already implied
(i.e., "You will be forgiven for context dependence here because the
implementations are already dependent on one another").

But that is really beside the point. Relationships define the structure
of logical relations between individual members of different sets. How
that structure is utilized is a quite different thing.

I agree that embedding is only one implementation. The real issue is
the constraint on referential integrity implied by coincident
lifecycles. Embedding just happens to be both the simplest and most
efficient approach to guaranteeing that integrity.

H. S. Lahman

unread,
Sep 20, 2002, 11:46:34 AM9/20/02
to
Responding to Martin...


>>1. *Association* means object A uses object B where A can live without
>>B, for instance, a baseball player object uses a bat object but
>>doesn't the baseball player doesn't need a bat when playing defense.
>>
>
> Association means that the objects send messages to each other. If
> the association is "navigable" (i.e. it has an arrowhead) then
> messages can only be sent in one direction.


I suspect that you are using 'means' here in the sense of 'implies'.
But the paragraph reads as if relationships exist only as a messaging
structure. So to clarify...

An association describes a <broad> static structure for how individual
members of different sets are logically related. Messages have nothing
to do with relationship semantics. Exchanging messages is a dynamic
mechanism for peer-to-peer flow of control. Though messages utilize the
existing static relationship structure and are constrained by it, they
are a very different critter.

Nor does the arrowhead have anything <directly> to do with messages. It
describes the same "uses", "aggregation", "has", etc. sorts of notions
already cited in this thread. It is simply a refinement on the nature
of the logical relationship (i.e., its structure). That sort of
refinement happens to constrain eventual message passing but it exists
and is defined independently of message passing.

Daniel T.

unread,
Sep 20, 2002, 1:12:20 PM9/20/02
to
"H. S. Lahman" <vze2...@verizon.net> wrote:

> Responding to Daniel T....


>
> >
> > I think it still does, for example:
> >
> > [A]<*>--->[B]<---<*>[C]
>
>
> But this is a no-no under both the old and new definitions because B
> can't be shared by two aggregates at the same time.

I don't agree. The *class* be can be used by both [A] and [C], but no
one B object can be held by both an A object and a B object at the same
time.

> > has a very different meaning than:
> >
> > [A]------>[B]<------[C]
> >
> > In the latter an A object and a C object could both share a B object, in
> > the former, that is not the case.
>
>
> If one embeds B in A then it is part of A's implementation. Allowing C
> to access it breaks the encapsulation (i.e., implementation hiding) of
> A. Therefore one should never embed an object when it has *any* sort of
> relationship to a third object. That combined with the removal of the
> lifecycle constraint means that, in effect
>
> 1
> A --------> B <------- C
>
> and
>
> A <*>-----> B <------- C
>
> are identical in that the OOP level implementation decisions are exactly
> the same. More importantly,

Again, I don't agree. In the former diagram, an A object and several C
objects could all be holding references to the same B object. In the
latter diagram, any B object held by an A object cannot be held by any
other object.


> A <*>-----> B // i.e., other objects relate only to A
>
> and
>
> 1
> A --------> B
>
> also have identical OOP decisions.

Yes they do, but only because the class C has been removed.

Uncle Bob (Robert C. Martin)

unread,
Sep 20, 2002, 4:52:20 PM9/20/02
to
It is remotely possible that on (or about) Fri, 20 Sep 2002 13:00:19

GMT, "Daniel T." <a@b.c> might (or might not) have written:

>"Uncle Bob (Robert C. Martin)"
> <u.n.c.l.e.b.o.b.@.o.b.j.e.c.t.m.e.n.t.o.r.d.o.t.c.o.m> wrote:
>
>> It is remotely possible that on (or about) Thu, 19 Sep 2002 23:17:12
>> GMT, "Daniel T." <a@b.c> might (or might not) have written:
>>

>> >[A]<*>----[B]


>> >
>> >means that for any particluar B object, only one object is allowed to
>> >hold a pointer to it. This naturally implies lifetime responsibility.
>>
>> With the exception that any object can have an association or
>> aggregation with that instance of B. It is only the composition
>> relationship that must be unique.
>
>If other objects hold a reference to the B object, then the A object
>cannot be said to have "sole responsibility" for its "disposition".

Now who's dealing in implementation details? ;^) In any case I
disagree. I can have an owning object that takes full responsibility
for the disposition of some instance; but I can have other object
temporarily holding references to that controlled instance.

>Before Booch and Rumbaugh got together, we had OMT's "uses", and
>"aggregation" and Booch's "uses", "has(shared)", and "has(unshared)".

Actually, that was "has by reference" and "has by value" which were
meant to map to the notion of C++'s pointer and value instance
variables. (Before that it was "uses" and "contains", but they
weren't very well defined. I remember when Grady changed them. I was
working at Rational at the time.)

>I
>think UML's "uses", "aggregation", & "composition" were meant to map
>onto Booch's association types.

At first they did. Long, long ago in the nether reaches of UML
history. But that mapping was obliterated by the second or third
revision. Back in those days Grady, et. al., were creating new
revisions of UML every other month or so.

>The whole point here is that at some higher level, we want it so that
>[B] can be ignored. If we allow just anybody to connect to it once it is
>in the composition relationship, we loose that divide.

I agree that is a valid design concept. It is the concept behind the
Facade pattern. However, the UML definition of the composition
relationship does not give you what you want.

You can get what you want by using a user defined stereotype like
<<facade>>:

|<<facade>>|
| A |<#>--------->|B|

You can define this to mean that any component of A is private to A
and no other instance in the system can hold a reference to it.

>I realize that none of this is imposed by the strict definition of
>"Composition" in UML. That's why I generally don't use UML, preferring
>instead something that is better suited to my design philosophy.

I understand, though I'm glad that my favorite book writers don't
adopt that philosophy. There is benefit to a standard language,
imperfect though that language might be.

H. S. Lahman

unread,
Sep 21, 2002, 12:00:03 PM9/21/02
to
Responding to Daniel T....


>>>[A]<*>--->[B]<---<*>[C]
>>>
>>
>>But this is a no-no under both the old and new definitions because B
>>can't be shared by two aggregates at the same time.
>>
>
> I don't agree. The *class* be can be used by both [A] and [C], but no
> one B object can be held by both an A object and a B object at the same
> time.


Good point.


>
>
>>>has a very different meaning than:
>>>
>>>[A]------>[B]<------[C]
>>>
>>>In the latter an A object and a C object could both share a B object, in
>>>the former, that is not the case.
>>>
>>
>>If one embeds B in A then it is part of A's implementation. Allowing C
>>to access it breaks the encapsulation (i.e., implementation hiding) of
>>A. Therefore one should never embed an object when it has *any* sort of
>>relationship to a third object. That combined with the removal of the
>>lifecycle constraint means that, in effect
>>
>> 1
>>A --------> B <------- C
>>
>>and
>>
>>A <*>-----> B <------- C
>>
>>are identical in that the OOP level implementation decisions are exactly
>>the same. More importantly,
>>
>
> Again, I don't agree. In the former diagram, an A object and several C
> objects could all be holding references to the same B object. In the
> latter diagram, any B object held by an A object cannot be held by any
> other object.


I can also express that same constraint, if necessary, in the first
example through discriminators or OCL. But the second does, indeed,
identify a special case of the first form.

However, I don't see a need for that sort of semantic redundancy in a
notation. [Given that the MDA profile for Executable UML employs less
than half of UML, there appears to be enough redundancy there already so
that nobody will notice, though. B-)]

BTW, I have a practical reason for why using explicit relationship
constraints is better. The model developer defines the actual
participants in action language when relationships are instantiated.
Therefore the model developer is responsible for ensuring that this
situation doesn't get screwed up (i.e., Bs that are related to an A are
not also related to a C).

The translation engine or OOP developer can handle that with embedding
for composition by rote. That's because of faith that the model
developer did the Right Thing. But what if the model developer screws
up? If there is no explicit constraint one will not know until the
application crashes and burns.

But if there is an explicit constraint that can be routinely enforced by
checking for consistency as the relationship is instantiated via
assertions or whatever. The application will still have a problem
because the model was not correct, but at least one has root cause
diagnosis and the possibility of a graceful exit.

Now the engine or OOP developer can look at the overall context and
infer the constraint so that the same sort of checking is implemented.
Having the engine do that makes an already complex task more
complicated. Depending on an OOP developer to make the right inference
risks human frailty. Better to have an explicit constraint to be
implemented.

Either developer can still screw up (i.e., the modeler can forget to
express the constraint or the programmer can forget to implement it) but
at least the problem is within the area of each's specific expertise and
that <hopefully> reduces the likelihood of error. [When one spends two
decades in the test business, one tends to see all the world's problems
in terms of defect prevention. B-)]


>
>
>
>>A <*>-----> B // i.e., other objects relate only to A
>>
>>and
>>
>> 1
>>A --------> B
>>
>>also have identical OOP decisions.
>>
>
> Yes they do, but only because the class C has been removed.


By your arguments above, any relationship with C is independent because
the Bs involved in that relationship are a disjoint set from those
involved with As. It is always up to the model developer to ensure that
they are disjoint sets. Thus, regardless of whether there is a C or
not, the A/B relationship will be implemented exactly the same way.

C only comes into it in one of two ways when identifying correctness
criteria:

Case 1: an explicit relationship constraint is provided to indicate the
the Bs must be in disjoint sets. This is no different than any other
constraints on relationships (e.g., loop constraints).

Case 2: One infers the constraint from the context when composition is
used where B has another relationship. In effect this makes the
implications of composition context-dependent.

While either approach works, the former is more consistent with the way
other relationship constraints are handled and leaves less to chance. I
would also argue that the Bs being disjoint sets is a crucial problem
space constraint and should be explicitly defined in the model rather
than implied.

H. S. Lahman

unread,
Sep 27, 2002, 12:04:46 PM9/27/02
to
Responding to Daniel T....


>>>I think it still does, for example:
>>>
>>>[A]<*>--->[B]<---<*>[C]
>>>
>>
>>But this is a no-no under both the old and new definitions because B
>>can't be shared by two aggregates at the same time.
>>
>
> I don't agree. The *class* be can be used by both [A] and [C], but no
> one B object can be held by both an A object and a B object at the same
> time.


In the shower this morning I had a spontaneous flashback and realized
that I was having a Metamucil Moment when I originally responded to this
by agreeing. In fact, I was right the first time.

The composition relationship is unconditional on the aggregate side.
Therefore *every* B must be part of the composition of some A at any
given time. Similarly, it must be part of the composition of some C.
But a B can only participate in one aggregate at a time, so such a
construct is illegal.

Universe

unread,
Sep 27, 2002, 2:03:30 PM9/27/02
to
H. S. Lahman wrote:

> Responding to Daniel T....


>>>>I think it still does, for example:
>>>>
>>>>[A]<*>--->[B]<---<*>[C]
>>>>
>>>
>>>But this is a no-no under both the old and new definitions because B
>>>can't be shared by two aggregates at the same time.
>>>
>>
>> I don't agree. The *class* be can be used by both [A] and [C], but no
>> one B object can be held by both an A object and a B object at the same
>> time.


> In the shower this morning I had a spontaneous flashback and realized
> that I was having a Metamucil Moment when I originally responded to this
> by agreeing. In fact, I was right the first time.

> The composition relationship is unconditional on the aggregate side.
> Therefore *every* B must be part of the composition of some A at any
> given time. Similarly, it must be part of the composition of some C.
> But a B can only participate in one aggregate at a time, so such a
> construct is illegal.

I will respond within a day or 2 on with why I think UML composition,
aggregation and "part/whole" semantics generally are limiting and
short-sighted.

Michael Feathers

unread,
Sep 27, 2002, 2:29:09 PM9/27/02
to

> Responding to Daniel T....
> >>>I think it still does, for example:
> >>>
> >>>[A]<*>--->[B]<---<*>[C]
> >>>
> >>
> >>But this is a no-no under both the old and new definitions because B
> >>can't be shared by two aggregates at the same time.
> >>
> >
> > I don't agree. The *class* be can be used by both [A] and [C], but no
> > one B object can be held by both an A object and a B object at the same
> > time.


Teaser Question: What if A and C are related by inheritance?


Michael Feathers (fun to see how the spec deals with these things)
www.objectmentor.com


Daniel T.

unread,
Sep 27, 2002, 4:16:32 PM9/27/02
to
"H. S. Lahman" <vze2...@verizon.net> wrote:

> Responding to Daniel T....
>
>
> >>>I think it still does, for example:
> >>>
> >>>[A]<*>--->[B]<---<*>[C]
> >>>
> >>
> >>But this is a no-no under both the old and new definitions because B
> >>can't be shared by two aggregates at the same time.
> >>
> >
> > I don't agree. The *class* be can be used by both [A] and [C], but no
> > one B object can be held by both an A object and a B object at the same
> > time.
>
>
> In the shower this morning I had a spontaneous flashback and realized
> that I was having a Metamucil Moment when I originally responded to this
> by agreeing. In fact, I was right the first time.
>
> The composition relationship is unconditional on the aggregate side.
> Therefore *every* B must be part of the composition of some A at any
> given time. Similarly, it must be part of the composition of some C.
> But a B can only participate in one aggregate at a time, so such a
> construct is illegal.

OK, so let's compare it to this:

name address
[Person]<*>--------------->[String]<----------------<*>[House]

Are you still going to hold to your Metamucil position? :-)

Daniel T.

unread,
Sep 27, 2002, 4:18:28 PM9/27/02
to
In article <an26hi$5hs$2...@news1.radix.net>,
Universe <univer...@radix.net> wrote:

> H. S. Lahman wrote:
>
> > Responding to Daniel T....
>
>
> >>>>I think it still does, for example:
> >>>>
> >>>>[A]<*>--->[B]<---<*>[C]
> >>>>
> >>>
> >>>But this is a no-no under both the old and new definitions because B
> >>>can't be shared by two aggregates at the same time.
> >>>
> >>
> >> I don't agree. The *class* be can be used by both [A] and [C], but no
> >> one B object can be held by both an A object and a B object at the same
> >> time.
>
>
> > In the shower this morning I had a spontaneous flashback and realized
> > that I was having a Metamucil Moment when I originally responded to this
> > by agreeing. In fact, I was right the first time.
>
> > The composition relationship is unconditional on the aggregate side.
> > Therefore *every* B must be part of the composition of some A at any
> > given time. Similarly, it must be part of the composition of some C.
> > But a B can only participate in one aggregate at a time, so such a
> > construct is illegal.
>
> I will respond within a day or 2 on with why I think UML composition,
> aggregation and "part/whole" semantics generally are limiting and
> short-sighted.

Aggreed, I commented on this earler.

Michael Feathers

unread,
Sep 27, 2002, 4:44:37 PM9/27/02
to

"Daniel T." <a@b.c> wrote in message
news:a-CFD8FC.16...@nnrp05.earthlink.net...

> > The composition relationship is unconditional on the aggregate side.
> > Therefore *every* B must be part of the composition of some A at any
> > given time. Similarly, it must be part of the composition of some C.
> > But a B can only participate in one aggregate at a time, so such a
> > construct is illegal.
>
> OK, so let's compare it to this:
>
> name address
> [Person]<*>--------------->[String]<----------------<*>[House]


Touche. Good call.


Michael Feathers
www.objectmentor.com


Uncle Bob (Robert C. Martin)

unread,
Sep 27, 2002, 5:15:00 PM9/27/02
to
"H. S. Lahman" <vze2...@verizon.net> might (or might not) have
written this on (or about) Fri, 27 Sep 2002 16:04:46 GMT, :

>Responding to Daniel T....
>
>
>>>>I think it still does, for example:
>>>>
>>>>[A]<*>--->[B]<---<*>[C]
>>>>
>>>
>>>But this is a no-no under both the old and new definitions because B
>>>can't be shared by two aggregates at the same time.
>>>
>>
>> I don't agree. The *class* be can be used by both [A] and [C], but no
>> one B object can be held by both an A object and a B object at the same
>> time.
>
>
>In the shower this morning I had a spontaneous flashback and realized
>that I was having a Metamucil Moment when I originally responded to this
>by agreeing. In fact, I was right the first time.
>
>The composition relationship is unconditional on the aggregate side.
>Therefore *every* B must be part of the composition of some A at any
>given time. Similarly, it must be part of the composition of some C.
>But a B can only participate in one aggregate at a time, so such a
>construct is illegal.

If the cardinality on both compositions was 0..1, it would be legal.
I don't usually bother with such nuances. I presume that the reader
will understand that the cardinality has to be 0..1 if there is more
than one owner.

Daniel T.

unread,
Sep 27, 2002, 11:23:32 PM9/27/02
to
In article <an2g0g$q5o$1...@slb7.atl.mindspring.net>,
"Michael Feathers" <mfea...@objectmentorNOSPAM.com> wrote:

Call me naughty Michael. I had the above example in mind when I wrote
the A-B-C example, but held the thought to use against dissenters.

Sometimes I forget that this is supposed to be a learning forum, not a
debate forum. I'll try not to be so bad in the future. :-/

H. S. Lahman

unread,
Sep 28, 2002, 11:37:29 AM9/28/02
to
Responding to Daniel T....


> OK, so let's compare it to this:
>
> name address
> [Person]<*>--------------->[String]<----------------<*>[House]
>
> Are you still going to hold to your Metamucil position? :-)


Yes, I would. It is still illegal because of the constraint on
composition that says that the Part cannot be associated with more than
one Whole at a time. It would be just as illegal as

1 1 1 1
Person ---------------> String <---------------------- House
name address

in this context because the String value of a Person's name is not
semantically mappable to the String value of a House address. But the
relationships require that every String value serve as both some
Person's name and some House's address. To convey what you want one
needs a 0..1 on the Person and House sides. But one can't do that with
compositions by definition.

H. S. Lahman

unread,
Sep 28, 2002, 11:52:12 AM9/28/02
to
Responding to Martin...


>>>>>I think it still does, for example:
>>>>>
>>>>>[A]<*>--->[B]<---<*>[C]
>>>>>

>>>>><snip>


>>
>
> If the cardinality on both compositions was 0..1, it would be legal.
> I don't usually bother with such nuances. I presume that the reader
> will understand that the cardinality has to be 0..1 if there is more
> than one owner.


But that is not an option for composition. The multiplicity must be 1
on the aggregate side. Though UML v1.4 has loosened the instance life
cycle constraint it has not loosened the constraint that a B must be
part of *some* member of the aggregate. You can swap A and C
participants for a given B but that B still must be a part of some A and
a part of some C at all times.

H. S. Lahman

unread,
Sep 28, 2002, 12:02:14 PM9/28/02
to
Responding to Feathers...


>>>>>I think it still does, for example:
>>>>>
>>>>>[A]<*>--->[B]<---<*>[C]
>>>>>
>>>>>
>>>>But this is a no-no under both the old and new definitions because B
>>>>can't be shared by two aggregates at the same time.
>>>>
>>>>
>>>I don't agree. The *class* be can be used by both [A] and [C], but no
>>>one B object can be held by both an A object and a B object at the same
>>>time.
>>>
>
>
> Teaser Question: What if A and C are related by inheritance?


You are right, this is probably why they loosened the instance life
cycle constraint in UML v1.4. Now one can have

B <------------<*> AC
A
|
+----+----+
| |
A C

where one employs subclass migration for AC during the execution. At
the superclass level a given B would still have its life cycle tied to
the same AC "instance".

Uncle Bob (Robert C. Martin)

unread,
Sep 29, 2002, 12:28:40 AM9/29/02
to
"H. S. Lahman" <vze2...@verizon.net> might (or might not) have
written this on (or about) Sat, 28 Sep 2002 15:52:12 GMT, :

>Responding to Martin...
>
>
>>>>>>I think it still does, for example:
>>>>>>
>>>>>>[A]<*>--->[B]<---<*>[C]
>>>>>>
>>>>>><snip>
>>>
>>
>> If the cardinality on both compositions was 0..1, it would be legal.
>> I don't usually bother with such nuances. I presume that the reader
>> will understand that the cardinality has to be 0..1 if there is more
>> than one owner.
>
>
>But that is not an option for composition. The multiplicity must be 1
>on the aggregate side. Though UML v1.4 has loosened the instance life
>cycle constraint it has not loosened the constraint that a B must be
>part of *some* member of the aggregate.

Here is the relevant quote from the UML 1.4 document:

3.48 Composition
3.48.1 Semantics
Composite aggregation is a strong form of aggregation, which requires

that a part instance be included in at most one composite at a time

and that the composite object has sole responsibility for the
disposition of its parts. The multiplicity of the aggregate end may

not exceed one (it is unshared).

H. S. Lahman

unread,
Sep 29, 2002, 11:00:59 AM9/29/02
to
Responding to Martin...


>>But that is not an option for composition. The multiplicity must be 1
>>on the aggregate side. Though UML v1.4 has loosened the instance life
>>cycle constraint it has not loosened the constraint that a B must be
>>part of *some* member of the aggregate.
>>
>
> Here is the relevant quote from the UML 1.4 document:
>
> 3.48 Composition
> 3.48.1 Semantics
> Composite aggregation is a strong form of aggregation, which requires
> that a part instance be included in at most one composite at a time
> and that the composite object has sole responsibility for the
> disposition of its parts. The multiplicity of the aggregate end may
> not exceed one (it is unshared).


That's the same quote I cited earlier in this thread. It is ambiguous
about the multiplicity. However, two paragraphs below that they clarify
with:

"In other words, the composite object projects its identity onto each
link corresponding to the part end of a composition aggregation."

This is a very strong statement about the nature of whole/part at the
class level. It says that the part is *intrinsically* associated with
the whole through identity so a conditional relationship to the
composite is not possible.

Daniel T.

unread,
Sep 29, 2002, 12:12:33 PM9/29/02
to
"H. S. Lahman" <vze2...@verizon.net> wrote:

> Responding to Daniel T....
>
>
> > OK, so let's compare it to this:
> >
> > name address
> > [Person]<*>--------------->[String]<----------------<*>[House]
> >
> > Are you still going to hold to your Metamucil position? :-)
>
>
> Yes, I would. It is still illegal because of the constraint on
> composition that says that the Part cannot be associated with more than
> one Whole at a time.

Obviously no one String object is a part of more than one Whole at a
time, yet each Person may have a String object as a part, and each House
may have a String as a part. The constraint on composition is not a
class based constraint, but an object based one.

Of course I may be wrong on this, I've not read the UML spec that
closely. Does it clear up the matter?

I've allways wondered what was the difference between:

+--------------+ +--------------+
| Person | | House |
+--------------+ +--------------+
| name: String | | name: String |
+--------------+ +--------------+

and the diagram at top.

If my assumption about the constraint on composition is wrong, then it
seems you have shown me what the difference is.

Uncle Bob (Robert C. Martin)

unread,
Sep 29, 2002, 5:38:07 PM9/29/02
to
"Daniel T." <a@b.c> might (or might not) have written this on (or
about) Sun, 29 Sep 2002 16:12:33 GMT, :

>"H. S. Lahman" <vze2...@verizon.net> wrote:
>
>> Responding to Daniel T....
>>
>>
>> > OK, so let's compare it to this:
>> >
>> > name address
>> > [Person]<*>--------------->[String]<----------------<*>[House]
>> >
>

>I've allways wondered what was the difference between:
>
>+--------------+ +--------------+
>| Person | | House |
>+--------------+ +--------------+
>| name: String | | name: String |
>+--------------+ +--------------+
>
>and the diagram at top.

I don't believe that there is a difference.

Uncle Bob (Robert C. Martin)

unread,
Sep 29, 2002, 5:44:23 PM9/29/02
to
"H. S. Lahman" <vze2...@verizon.net> might (or might not) have
written this on (or about) Sun, 29 Sep 2002 15:00:59 GMT, :

>Responding to Martin...
>
>
>>>But that is not an option for composition. The multiplicity must be 1
>>>on the aggregate side. Though UML v1.4 has loosened the instance life
>>>cycle constraint it has not loosened the constraint that a B must be
>>>part of *some* member of the aggregate.
>>>
>>
>> Here is the relevant quote from the UML 1.4 document:
>>
>> 3.48 Composition
>> 3.48.1 Semantics
>> Composite aggregation is a strong form of aggregation, which requires
>> that a part instance be included in at most one composite at a time
>> and that the composite object has sole responsibility for the
>> disposition of its parts. The multiplicity of the aggregate end may
>> not exceed one (it is unshared).
>
>That's the same quote I cited earlier in this thread. It is ambiguous
>about the multiplicity.

I don't find it ambiguous. Multiplicity cannot exceed one. That
means it can be 0..1.

>However, two paragraphs below that they clarify
>with:
>
>"In other words, the composite object projects its identity onto each
>link corresponding to the part end of a composition aggregation."

I think that statement is far more subject to interpretation than the
other.

In any case, the intent for composition has always been that composite
objects can shed their responsibilities to their parts by handing
those parts to other objects that are willing to take over the
responsibility. If composites are to be allowed this ability then the
multiplicity on the composite side must be allowed to go to zero.

Martin Fowler

unread,
Sep 29, 2002, 6:33:15 PM9/29/02
to
Daniel T. wrote:
> "H. S. Lahman" <vze2...@verizon.net> wrote:
>
>
>>Responding to Daniel T....
>>
>>
>>
>>>OK, so let's compare it to this:
>>>
>>> name address
>>>[Person]<*>--------------->[String]<----------------<*>[House]
>>>
>>>Are you still going to hold to your Metamucil position? :-)
>>
>>
>>Yes, I would. It is still illegal because of the constraint on
>>composition that says that the Part cannot be associated with more than
>>one Whole at a time.
>
>
> Obviously no one String object is a part of more than one Whole at a
> time, yet each Person may have a String object as a part, and each House
> may have a String as a part. The constraint on composition is not a
> class based constraint, but an object based one.
>
> Of course I may be wrong on this, I've not read the UML spec that
> closely. Does it clear up the matter?

You are exactly right Daniel. The rule on composites, indeed the only
real semantic rule, is that the part can only be part of one whole. Your
diagram is a perfect example of this. A string may stand alone, or it
may be the name for a Person, or it may be the address for a house (or
it may be a part of something else. What it can't be is both the name of
a person and the address of a house. Composition is perfect for value
objects.

Part of the reason that this is confusing is that this isn't something
you find in database oriented static models (like ER) where there is a
more fixed division between attributes and relationships. You can't
express this constraint with multiplicities alone.


>
> I've allways wondered what was the difference between:
>
> +--------------+ +--------------+
> | Person | | House |
> +--------------+ +--------------+
> | name: String | | name: String |
> +--------------+ +--------------+
>
> and the diagram at top.
>

There is no difference. UML 1.x defines attributes as an alternative
notation for composition.

UML 2 defines attributes as an alternative notation for any navigable
association, which is broader and better fits with the usage in the field.

Martin

H. S. Lahman

unread,
Sep 30, 2002, 11:37:48 AM9/30/02
to
Responding to Daniel T....


>>>OK, so let's compare it to this:
>>>
>>> name address
>>>[Person]<*>--------------->[String]<----------------<*>[House]
>>>
>>>Are you still going to hold to your Metamucil position? :-)
>>>
>>
>>Yes, I would. It is still illegal because of the constraint on
>>composition that says that the Part cannot be associated with more than
>>one Whole at a time.
>>
>
> Obviously no one String object is a part of more than one Whole at a
> time, yet each Person may have a String object as a part, and each House
> may have a String as a part. The constraint on composition is not a
> class based constraint, but an object based one.


I have to disagree. All relationships are class based. They define the
static structure of relations between sets. Which particular set
members (objects) participate is not specified in the relationship;
those must be defined in a dynamic model.

The composition relationship is unconditional on the composite side.
(See my related discussion with Martin over this nearby.) That means
that *every* member of the String set must be related to *some* Person
set member at all times. Similarly, *every* member of the String set
must be related to *some* member of the House set and that leads to the
conflict.


>
> Of course I may be wrong on this, I've not read the UML spec that
> closely. Does it clear up the matter?
>
> I've allways wondered what was the difference between:
>
> +--------------+ +--------------+
> | Person | | House |
> +--------------+ +--------------+
> | name: String | | name: String |
> +--------------+ +--------------+
>
> and the diagram at top.


Since the subset of Person names is <assumed> disjoint from the subset
of House names, the correct relationship is:

0..1 1 1 0..1
Person ----------- String ---------------- House

However, one must also explicitly indicate the disjoint sets with
relationship constraints, either using discriminator expressions or OCL.

[In UML the discriminator is not just an identifier for a data
dictionary. It actually represents a particular set partitioning that
can be used in logical expressions to constrain referential integrity.
This only becomes obvious when one has a superclass with two subclassing
relations. In that case the dual relations are ambiguous unless one
defines whether the subsets of each relation are disjoint. If the
discriminators are the same all subclasses belong to the same
partitioning and an instance can only be a member of one subclass
selected from among both relationships. It the discriminators are
different the relations are independent partitionings and an instance
must be a combination of one subclass from each relation.]

H. S. Lahman

unread,
Sep 30, 2002, 1:04:19 PM9/30/02
to
Responding to Martin...


>>>Here is the relevant quote from the UML 1.4 document:
>>>
>>>3.48 Composition
>>>3.48.1 Semantics
>>>Composite aggregation is a strong form of aggregation, which requires
>>>that a part instance be included in at most one composite at a time
>>>and that the composite object has sole responsibility for the
>>>disposition of its parts. The multiplicity of the aggregate end may
>>>not exceed one (it is unshared).
>>>
>>That's the same quote I cited earlier in this thread. It is ambiguous
>>about the multiplicity.
>>
>
> I don't find it ambiguous. Multiplicity cannot exceed one. That
> means it can be 0..1.


Or it can mean that a part can only be an element of one composite at a
time without saying anything about whether it must always be an element
of a composite.


>
>
>>However, two paragraphs below that they clarify
>>with:
>>
>>"In other words, the composite object projects its identity onto each
>>link corresponding to the part end of a composition aggregation."
>>
>
> I think that statement is far more subject to interpretation than the
> other.


A relationship is a class level structure, not an instance level
structure; it defines the static structure of relations among sets. If
the Part set shares identity with the Whole set the sets are
inseparable. I don't see how that is open to interpretation.

To describe the sort of identity sharing UML prescribes for composition
one would need something like

Bolt
A
|
+-----+-----+
| |
Engine <*>-------> EngineBolt FrameBolt <------<*> Frame

rather than

Engine <*>-------> Bolt <---------<*> Frame

Such subclassing would only make sense if there were something special
about EngineBolts that was unique to the Engine context, which is
exactly what composition's identity sharing describes.


>
> In any case, the intent for composition has always been that composite
> objects can shed their responsibilities to their parts by handing
> those parts to other objects that are willing to take over the
> responsibility. If composites are to be allowed this ability then the
> multiplicity on the composite side must be allowed to go to zero.


I don't think delegating the responsibility is intended at all. As soon
as the "composite" can delegate that responsibility, the responsibility
is arbitrary. Passing the object reference is just an implementation of
relationship navigation to whoever really owns the responsibility. IOW,
the design has already determined that the responsibility belongs
somewhere else than the composite. Therefore such a relationship is not
composition in the UML sense because the composite doesn't really own
the responsibility and never did.

I think Feathers had the right idea. I think the "at a time" change was
intended specifically for the situation where the composite is a
superclass and its subclasses are migrated. In that case the Part is
related to different Whole subclass objects over its life but they are
the same, single instance of the superclass. But that superclass
instance still has sole responsibility for the disposition of the parts.

Richard Riehle

unread,
Oct 2, 2002, 9:15:20 PM10/2/02
to
"H. S. Lahman" wrote:

> To describe the sort of identity sharing UML prescribes for composition
> one would need something like
>
> Bolt
> A
> |
> +-----+-----+
> | |
> Engine <*>-------> EngineBolt FrameBolt <------<*> Frame
>
> rather than
>
> Engine <*>-------> Bolt <---------<*> Frame
>
> Such subclassing would only make sense if there were something special
> about EngineBolts that was unique to the Engine context, which is
> exactly what composition's identity sharing describes.

I hope this doesn't sound too picky.

In another thread, the one dealing with "What is an object?" , some
contributors
have deprecated OOP as too noun-centric. I suspect one reason that
criticicism
continues to be seen is that we so often give examples of objects that are
static
nouns, rather than objects that are characterized by their behavior. A
bolt has
not internal state. Consequently, it is difficult to model it as a software
object,
in the OOP sense.

I favor examples that include both attributes and methods. One of my
favorite
examples is that of Machine. Granted, this is also somewhat academic, but it

seems to work when I am teaching OOP to industry and academia.

Avoiding specific language constructs, we would have

class Machine
public:
Turn_On();
Turn_Off();
Is_On();
private:
Is_On : Boolean := False;
end Machine;

where the implementation is in a separate file (or wherever your favorite
language requires it to be).

Now, as we describe the hierarchy, we can ask about the all-important issue
of specialization (via inheritance) or genericity, along with the issue of
polymorphism. Also, we probably would want Machine to be an abstract
class since no one has ever actually seen a Machine and we could not create
an instance of a Machine anyway.

Machine (A) --
parenthetical A is for Abstract
^
|
followed by the specialization examples.

Now the subclassing (or specialization) will make sense in terms of both the

attributes and methods. We can also do compositions that make sense in
terms of how the other classes will invoke those methods and represent the
notion of encapsulation quite nicely.

I think those in this forum who seem to dislike OOP simply fail to
understand
the fundamental issues. Certainly, the complaints I see posted demonstrate
a failure in that respect. Then again, there will always be those with an
intractable and argumentive nature. Those people we simply ignore.

Richard Riehle


H. S. Lahman

unread,
Oct 3, 2002, 11:36:46 AM10/3/02
to
Responding to Riehle...


>>To describe the sort of identity sharing UML prescribes for composition
>>one would need something like
>>
>> Bolt
>> A
>> |
>> +-----+-----+
>> | |
>>Engine <*>-------> EngineBolt FrameBolt <------<*> Frame
>>
>>rather than
>>
>>Engine <*>-------> Bolt <---------<*> Frame
>>
>>Such subclassing would only make sense if there were something special
>>about EngineBolts that was unique to the Engine context, which is
>>exactly what composition's identity sharing describes.
>>
>
> I hope this doesn't sound too picky.
>
> In another thread, the one dealing with "What is an object?" , some
> contributors
> have deprecated OOP as too noun-centric. I suspect one reason that
> criticicism
> continues to be seen is that we so often give examples of objects that are
> static
> nouns, rather than objects that are characterized by their behavior. A
> bolt has
> not internal state. Consequently, it is difficult to model it as a software
> object,
> in the OOP sense.


This is making assumptions about the problem space (i.e., Bolt has no
state). All I indicated was that there had to be something special
about EngineBolt vs. FrameBolt to employ specialization.


>
> I favor examples that include both attributes and methods.


So do I. But that is cumbersome in fixed font text for Email when one
has to anticipate mail readers with only 60-70 character line width.
Providing such details did not seem important here since the context was
only about whether the strong Whole/Part semantics of a composition
relationship required Part to be distinct _in some way_ from Parts in
other composition relationships.

----

Having mounted that defense, I will now officially back off of my
assertion that the Part class cannot participate in two composition
relationships. The reason is due to a chain of logic I was about to use
to refute your assertion about Bolt not having state.

A Bolt would be likely to have a state in the form of state variables
(attributes). But the first example that leaped to mind was Size that
could be used to discriminate between usages. That could be used to
partition the set of Bolts appropriate for Engines from those
appropriate for for Frames. Alas, that would be an attribute of Bolt
and only its value would distinguish the subclasses.

While there are situations where one can use subclassing solely to deal
with unique relationships when there are no specialization differences,
those are rather rare and one properly avoids them when there are other
alternatives. Usually a simpler solution is to just constrain the
relationships. For example, one could have a simple association:

1 1 1 1
[A] ----------- [B] ------------- [C]
R1 R2[!R1]

where the relationship discriminators partition the [B] set into
disjoint subsets, one for each relationship. So in this case if 'B' is
Bolt, then the Bolt set could be partitioned into "Size suitable for A"
and "Size suitable for C" (assuming there are only two sizes).

I still believe I am correct that the relationships are unconditional
for composition, but my logic was flawed in arguing that precluded a
class participating in dual compositions. That would only be true if
the relationship were unconstrained so that the default for binary
associations applied where all members of the participating sets could
participate. But if one constrains the compositions as

[A] <*>---------- [B] ----------<*> [C]
R1 R2[!R1]

the Part *class* can participate in multiple compositions, though any
given instance is still restricted to one composition.

It is ironic that it took this long for that to dawn for two reasons.
The first is that I used the simple association example previously in
this thread to demonstrate that a particular B can't participate in only
one relationship when they are unconditional _unless the relationships
are constrained_.

The second is that I pointed out to someone else in another thread a
short time ago that discriminators were not simply relationship
mnemonics; that they actually represented a specific partitioning of the
participating class' membership sets. While the default in a binary
relationship is trivial (i.e., the subset is the whole set), that can be
modified by relationship constraints.

The mind is always the second thing to go.

Richard Riehle

unread,
Oct 6, 2002, 1:00:38 PM10/6/02
to
"H. S. Lahman" wrote:

> Responding to Riehle...

[snip, snip, snip of a lot of interesting and excellent
stuff]

> The mind is always the second thing to go.

Please be aware that my nitpicking was not intended to
deprecate your original point. I knew you would agree
with my nit, but were constrained in your presentation
by the need to pursue simplicity and clarity.

We don't have and argument.

As for the mind being the second thing to go, as a person
of advanced antiquity, myself, I can attest to that. However,
since I see myself as being in the twilight of dementia, I
frequently find it appropriate to defer to the intellectual
acuity of others. Perhapst some of my strongly
held opinions are more a function of a kind of technological
ateroscleroctic residue from my once nimble brain than as
original insights. :-)

Regards,

Richard Riehle


0 new messages