|
From: Jennifer Jazz on 2 May 2007 17:26 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 3 May 2007 08:42 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 3 May 2007 13:05 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 3 May 2007 18:05 "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 4 May 2007 11:41
"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> > >> |