From: Jennifer Jazz on
My question is regarding the mapping of Class diagram to the C++
coding.

There are 3 realtions in Class diagram

1) Assosication
2) Composition
3) Aggregation (Weak Composition).

-----------------------------------------------------
Class diagram for A ----- B (Association)
I handle it coding like that

main() {
A objA;
B objB;

objA.funA(objB); // or
objB.funB(objA);

}

-----------------------------------------------------
A <>---- B (filled diamond) for compoistion
Take the example of CAR and ENGINE, this relation is composition

I handle it coding like that

class B {
}

class A {
B objB; //or B* objB

}

This shows when A's Object destroys B also destroys.
Im clear with above two concepts but when aggregation comes.

A <>---- B (non-filled diamond) for agregation
Take the example of CAR and WHEEL-CUP.

class B {
}

class A {
B* ptrB;

}

Take the example of CAR and WHEEL-CUP, this relation is aggregation.
CAR changes its wheel-cup each time when it go to service the car.

CAR <>------ Wheel-CUp

im not getting one thing thing when car destroyed (i.e. destructor
called) does Wheel-Cup should also destroy? iF yes then the difference
between COMPOSITION and AGGREGATION is only left that in aggregation
the aggregated object (B* ptrB) points to different objects i.e.
different wheel cups at different states. and in COMPOSITION it only
keep points to only one object. AND in both aggre. and comp. object B
destoys as object A destroys.

One more question , in composition the Object B is created as object A
is created i.e. (When CAR is created ENGINE also created) but what abt
wheel cups? when they will be created and destroyed? as wheel cups
can live independly and when car goes for services, they new wheel
cups only points of the this car showing new wheel cups attached. So
the other wheel cups destroyed !!??

I shall be very very thankful if u answer me this question

From: Daniel T. on
Jennifer Jazz <Jeniffer911(a)gmail.com> wrote:

> My question is regarding the mapping of Class diagram to the C++
> coding.
>
> There are 3 realtions in Class diagram
>
> 1) Assosication
> 2) Composition
> 3) Aggregation (Weak Composition).

IMHO... You are too caught up with who destroys what. Try this:

When class A cannot compile without including class B's header (in
either A's header or cpp file,) then A has an "association" with B.

If class A (or any object of class A) sends messages to objects of class
B, either through the dot operator or the -> operator, then A (also) has
an aggregation relationship with B... No matter how A gained access to
the B object(s).

If particular objects of class A are the only ones that can send
messages to particular objects of class B, then A has a composition
relationship with B, again no matter how the A objects gained access to
the B objects.

Here is an unusual example:

class B {
B();
~B();
public:
void foo();
friend class BFactory;
};

class BFactory {
public:
B* create() { return new B; }
void destroy( B* b ) { delete b; }
};

class A {
BFactory bf;
B* b;
public:
A() {
b = bf.create();
}
~A() {
b->foo();
bf.destroy( b );
}
};

In the above, A<#>---BFactory (composition)
A<#>---B (also composition)
BFactory --- B (association)

Even though BFactory is the *only* class allowed to destroy B objects,
there is only an association relationship between it and B.

> Take the example of CAR and WHEEL-CUP, this relation is aggregation.
> CAR changes its wheel-cup each time when it go to service the car.
>
> CAR <>------ Wheel-CUp
>
> im not getting one thing thing when car destroyed (i.e. destructor
> called) does Wheel-Cup should also destroy?

In C++, "the last one out, closes the door". I.E., an object must be
deleted/destroyed by the last bit of code to hold a pointer to it. (This
is obvious right?)

So... A Car object is holding a pointer to 4 WheelCup objects, does it
*know* that no other objects are holding pointers to those 4 wheel-cups?
If so, then it needs to destroy them, otherwise no.

Then the question becomes, which is it, composition or aggregation?

(1) If only Car objects send messages to WheelCup objects, then the
relationship is composition. The Car knows to delete the WheelCap
because the car owns it.

(2) If several different objects have been sending messages to WheelCup
objects, then the relationship is aggregation. The Car's destruction of
the WheelCups is a coincidence of how the code is structured.

> I shall be very very thankful if u answer me this question

C++ is (I think) unique in that the programmer must explicitly say when
an object is destroyed and that confuses the issue. If destruction of an
object really decided between aggregation and composition, then all
object relationships in C++ would be composition because they all must
be explicitly destroyed
From: H. S. Lahman on
Responding to Jazz...

> My question is regarding the mapping of Class diagram to the C++
> coding.
>
> There are 3 realtions in Class diagram
>
> 1) Assosication
> 2) Composition
> 3) Aggregation (Weak Composition).

Implementation-wise there is no difference at all between aggregation
and association. Aggregation exists in UML to provide symmetry with
composition (i.e., a Whole/Part semantics but without the referential
integrity constraint). IOW, the notion of Whole/Part is only relevant in
the problem space so there is nothing being specified for the
implementation.

Composition, OTOH, specifies a referential integrity constraint where
the Whole must control the life cycle of the Part. That constraint is
actually orthogonal to the implementation of the relationship. So one
could implement a composition exactly the same way as an association.
However, if one did so, one would also have to ensure that the Whole
managed the disposition of the Part explicitly elsewhere in the code.

Since languages like C++ distinguish between object references and
embedded objects (i.e., objects that are created and die with the host
as part of its implementation), composition is very commonly implemented
as an embedded object in C++ because that satisfies the referential
integrity constraint "for free". But in other languages that support
only object references, one would have to provide explicit code to
enforce the referential integrity constraint.

[Or rely on garbage collection to recognize that the only reference, in
the Whole, has gone away when the Whole goes away. But one should never
rely on garbage collection because there are situations where not
thinking through the implications can lead to problems. If nothing else,
explicitly thinking through when every object /must/ be inaccessible
with ensure one has a firm grasp on the requirements.]

<aside>
IMO, aggregation and composition are, at best, poorly structured in UML
and, at worst, completely unnecessary. OMG has been tinkering with the
semantics for years and there are still debates about what "disposition"
means. To me that just reflects that the marriage between Whole/Part and
referential integrity constraints isn't working out.

Note that UML got painted into this corner because of its roots in the
Booch notation, which was sometimes called Graphical C++ (even by Grady
himself). Thus UML has features like composition relationships and
protected that are pretty much unique to C++. In my view that has two
problems. One is that C++ is the most technically deficient of all the
popular OOPLs. So forcing UML to emulate what it does is not a good idea
on general principles.

The second is that UML is supposed to be an OOA/D notation. As such, the
OOPLs exist to implement the designs that it specifies. Having the OOA/D
notation reflect the constructs of a specific implementation language is
akin to the tail wagging the dog.
</aside>

>
> -----------------------------------------------------
> Class diagram for A ----- B (Association)
> I handle it coding like that
>
> main() {
> A objA;
> B objB;
>
> objA.funA(objB); // or
> objB.funB(objA);
>
> }

There are actually three ways to implement associations:

(1) Passing an object reference to a method, as in your example. This
instantiates a temporary association for the duration of the method
execution. This has two problems. Passing object references is the worst
form of coupling because the receiver has the potential for unlimited
side affects in accessing the object. The second, more important,
problem is that the caller of the function must know exactly which
object the receiver should collaborate with. That is information beyond
what it needs to know about its own collaboration with the receiver.

(2) Employing explicit object identifier attributes and using a static
'find' method for the class. This is a literal implementation of the
relational model that emulates RDBs. This is very rarely done in OO
applications because of the search overhead and because OO relationships
are instantiated at the object level rather than the class level.

(3) Providing a referential attribute that is an object reference (e.g.,
a C++ pointer). This is the preferred way to implement OO associations.
While the receiver still technically has the potential for unlimited
side effects in accessing the reference, the collaboration is controlled
in an important way. The decision about which particular object to
access can be encapsulated separately from collaborations with clients.
Generally the business rules and policies of instantiation (Who) are
different that those for collaboration (When and What). That separation
of concerns will tend to lead to more robust and maintainable applications.

>
> -----------------------------------------------------
> A <>---- B (filled diamond) for compoistion
> Take the example of CAR and ENGINE, this relation is composition
>
> I handle it coding like that
>
> class B {
> }
>
> class A {
> B objB; //or B* objB
>
> }
>
> This shows when A's Object destroys B also destroys.

True. But, apropos of my point above, this is just convenient in C++.
One could use a pointer so long as the B was deleted when the A was.

> Im clear with above two concepts but when aggregation comes.
>
> A <>---- B (non-filled diamond) for agregation
> Take the example of CAR and WHEEL-CUP.
>
> class B {
> }
>
> class A {
> B* ptrB;
>
> }
>
> Take the example of CAR and WHEEL-CUP, this relation is aggregation.

Not quite. This is the preferred way to implement simple associations.
Since aggregation has no special semantics for the implementation, one
can use the simple association implementation. One could also implement
if by passing it as a method argument or providing an explicit
identifier and using a 'find'.

> CAR changes its wheel-cup each time when it go to service the car.
>
> CAR <>------ Wheel-CUp
>
> im not getting one thing thing when car destroyed (i.e. destructor
> called) does Wheel-Cup should also destroy? iF yes then the difference
> between COMPOSITION and AGGREGATION is only left that in aggregation
> the aggregated object (B* ptrB) points to different objects i.e.
> different wheel cups at different states. and in COMPOSITION it only
> keep points to only one object. AND in both aggre. and comp. object B
> destoys as object A destroys.

If the relationship is composition, then Wheel-Cup would normally have
to go away when CAR does. I say 'normally' because one can view the
notion of 'disposition' in a way that allows a Wheel-Cup to be swapped
between Cars. In that view each Car has responsibility for Wheel-Cup's
disposition until it is swapped away (i.e., 'disposition' can mean
'transfer ownership' as well as 'delete'). Then the last Car having the
Wheel-Cup would have to delete it when that Car was deleted.

So the difference between composition and aggregation has nothing to do
with the number of participants in the relationship. It is only about
whether or not there is a referential integrity constraint on the
"disposition" of Wheel-Cup that is enforced by Car.

> One more question , in composition the Object B is created as object A
> is created i.e. (When CAR is created ENGINE also created) but what abt
> wheel cups? when they will be created and destroyed? as wheel cups
> can live independly and when car goes for services, they new wheel
> cups only points of the this car showing new wheel cups attached. So
> the other wheel cups destroyed !!??

Alas, I have no idea what a "wheel cup" actually is. B-)

Whether there is a composition association can be quite tricky, which is
one of the problems with the way UML defines it. Consider an application
whose primary responsibility was managing an auto assembly line. A
'car' is then just a conceptual assembly container for collecting
various automotive components. Those components exist in inventory prior
to assembly.

However, once they are assembled into a 'car' they become part of it.
Since the main software mission is about assembling parts into a whole,
there is definitely a Whole/Part semantics somewhere in this problem.
Since the software's job is over when the 'car' rolls off the assembly
line, those components are then inseparable from the 'car' as far as the
software is concerned. So one could use composition here even though the
components already exist in inventory if the relationship is
instantiated as he components are added AND if one interprets
'disposition' to mean that the components can't exist independently of
the car _once it is assembled_.

However, my advice is that software design is tough enough without
getting into arcane mental nit-picking like this. So I wouldn't bother
with composition and aggregation. (In fact, in the MDA profile I used
for OOA/D they are not included; we just use simple associations for
everything.)



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

H. S. Lahman
hsl(a)pathfindermda.com
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info(a)pathfindermda.com for your copy.
Pathfinder is hiring:
http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH



From: Daniel T. on
"H. S. Lahman" <h.lahman(a)verizon.net> wrote:

> Note that UML got painted into this corner because of its roots in the
> Booch notation...

Agreed. I think there are elements of compromise between Booch notation
and OMT in UML. OMT had only 2 relational concepts (association, and
"aggregation" which was functionally the same as UML's "composition".)
Early Booch had three relational concepts ("depends", "uses in
interface", and "uses in implementation".) I think UML's relations are
an attempt two graft the two different ideas into one.

Personally, I find the Booch concept more useful.
From: Eugene Kalenkovich on

"H. S. Lahman" <h.lahman(a)verizon.net> wrote in message
news:BDo_h.3380$zE.1660(a)trnddc03...
> Responding to Jazz...
>
>> My question is regarding the mapping of Class diagram to the C++
>> coding.
>>
>> There are 3 realtions in Class diagram
>>
>> 1) Assosication
>> 2) Composition
>> 3) Aggregation (Weak Composition).
>
> Implementation-wise there is no difference at all between aggregation and
> association. Aggregation exists in UML to provide symmetry with
> composition (i.e., a Whole/Part semantics but without the referential
> integrity constraint). IOW, the notion of Whole/Part is only relevant in
> the problem space so there is nothing being specified for the
> implementation.

I agree with almost everything, but not with (aggregation==association). The
main difference is that Whole should know what Part it has (if it really has
it, you are absolutely right about integrity). From implementation point of
view it means that Whole instance has some kind of reference to Part one -
pointer, handler, Id, etc with 0..1 (0..n) relation.

> Composition, OTOH, specifies a referential integrity constraint where the
> Whole must control the life cycle of the Part. That constraint is actually
> orthogonal to the implementation of the relationship. So one could
> implement a composition exactly the same way as an association. However,
> if one did so, one would also have to ensure that the Whole managed the
> disposition of the Part explicitly elsewhere in the code.
>
> Since languages like C++ distinguish between object references and
> embedded objects (i.e., objects that are created and die with the host as
> part of its implementation), composition is very commonly implemented as
> an embedded object in C++ because that satisfies the referential integrity
> constraint "for free". But in other languages that support only object
> references, one would have to provide explicit code to enforce the
> referential integrity constraint.
>
> [Or rely on garbage collection to recognize that the only reference, in
> the Whole, has gone away when the Whole goes away. But one should never
> rely on garbage collection because there are situations where not thinking
> through the implications can lead to problems. If nothing else, explicitly
> thinking through when every object /must/ be inaccessible with ensure one
> has a firm grasp on the requirements.]
>
> <aside>
> IMO, aggregation and composition are, at best, poorly structured in UML
> and, at worst, completely unnecessary. OMG has been tinkering with the
> semantics for years and there are still debates about what "disposition"
> means. To me that just reflects that the marriage between Whole/Part and
> referential integrity constraints isn't working out.
>
> Note that UML got painted into this corner because of its roots in the
> Booch notation, which was sometimes called Graphical C++ (even by Grady
> himself). Thus UML has features like composition relationships and
> protected that are pretty much unique to C++. In my view that has two
> problems. One is that C++ is the most technically deficient of all the
> popular OOPLs. So forcing UML to emulate what it does is not a good idea
> on general principles.
>
> The second is that UML is supposed to be an OOA/D notation. As such, the
> OOPLs exist to implement the designs that it specifies. Having the OOA/D
> notation reflect the constructs of a specific implementation language is
> akin to the tail wagging the dog.
> </aside>
>
>>