UML association vs. composition and detail level
Actually, make that a couple of amateur UML questions! When creating a UML diagram to model some domain concepts and you come across a domain concept that "holds" some information about another concept, is it better to hold a stamp/reference to that entity or hold the whole entity in the model itself? Please bear in mind that this is relating to creating a simple high-level model - I'm sure in the implementation stage things would be slightly different.
For example, which of the two models below is actually correct? The first one has a composition relationship, with FlightBooking holding the whole of Flight. In the second one, FlightBooking just has a reference to Flight.
Secondly, when creating a high level UML diagram modelling domain concepts, how much detail are you really meant to go? For example, in the diagram below, a flight could hold details about origin/destination as strings, or I could model separate classes for these concepts and create a composition relationship. Which of the two is advisable?
开发者_运维技巧Also, just another thing, when modelling the above where a Flight "holds" an orig/destination as another class rather than a string, which of the two ways is the correct way of modelling this? I'm quite confused as to when to show assosciation and when to show composition.
Association :
It means two classes have some kind of relationship, could be anything really.
E.g : A uses B, A is related to B in a given way.
Composition :
This is also a special type of association used for modelling 'Ownership'. This is very similar to Aggregation with the only difference that it depicts a Whole-part relationship and the 'part' entity doesn't have its own independent existence
E.g : A consists of B; B is a part of A and hence cannot exist without A.
Good explanation : UML Class Diagram: Association, Aggregation and Composition
Sorry if this is a bit long...
If you're trying to model domain concepts then I'd encourage you to forget about composition/aggregation and stick with simple associations. Why? Because deciding on composition / aggregation gets in the way of the important questions. They are:
- Why does the relationship exist? Specifically, what domain rules/constraints does it capture?
- What's the cardinality at either end?
- What's the create & delete behaviour? i.e. who creates / deletes instances of the association?
Relationship naming You accomplish (1) by naming the rel ends. Not with role names (e.g. "Flights" in your first example) because that tells you nothing about why the relationship exists. So in your example 1: what does the relationship represent? Is it a reserved seat on the flight? A confirmed one? Paid for? Impossible to tell from the diagram as it stands. There are various approaches for verb-based naming, see e.g. this post. Why do this? Because it prompts you to make sure you understand the domain. A large percentage (probably a majority, although I've never proven it) of the domain rules exist in the relationships. So understanding why the relationships exist is fundamental to understanding the domain.
Cardinality Probably more obvious than naming. You should determine at both ends - both upper and lower. Important at the lower end is whether it's optional (i.e. 0 or 1). At the upper end, 1 or many. Again this surfaces important rules from the domain. Coming back to your example again: how many flights in a flight booking? Can one flight be in multiple bookings? (whatever 'in' means...).
Create / Delete Behaviour Who creates instances of the relationship? Who deletes? If one end gets deleted, what happens to the other end? Again, all important rules from the problem domain.
Those hopefully answer your second question too. Don't skimp on relationships. Take time to understand them. They are the secret sauce to understanding a domain. Answering all the questions above will give you far more insight than trying to decide among composition/aggregation/association.
If you really want to show composition vs association however it is mechanical if you answer the questions above:
- IF the cardinality on one end of the relationship is 1:1 (i.e. can only ever be one), AND
- that same end is responsible for creating and deleting instances of the other end, THEN
- It can be shown as composition.
Otherwise use a simple association. As for aggregation: ignore it. Remove it from your vocabulary. Causes more confusion than it's worth. Everything you can say with aggregation you can say far more clearly and precisely with a properly defined simple association.
hth.
PS: a point of syntax: Composition uses a filled diamond. What you've shown is Aggregation.
Compositions, aggregations and associations.
- Before other things you should understand what the association A to B is.
- Basically it is a solid line between A and B. It can represent one structure that connects class/instanc(es) of A with the class/instances of B. The structure can be of any sort and belong anywhere. All information, written about the line, describes this structure.
- If there are two structures, one structure, that connects one instance of A with instance(s) of B and another structure that connects instance of B with instance(s) of A, you can show them both in ONE association. Then, information written about its B end describes the first structure (b->a) and info about the other end describes the other structure.
- If you'll have more than one structure guiding from A to B, you have to draw two different associations.
- If a joining structure is complex, you could represent it as an Association Class. There you can define more details.
- A joining structure can connect more than two classes, then it will be shown as a large diamond with solid branches to these classes. It is still association! Attention: these two more complex associations are very badly supported by existing tools. You can easily create something absolutely senseless with them. And they are difficult. Use carefully.
- In C++ instance A can have the B instance not by pointer, but directly. There is NO special UML sign for it, it should be shown in the same way as normal, pointer attribute.
- Composition is shown by what is called black or full diamond. It is on the side of the container.
- The other one, empty diamond, is called "shared aggregation", or, shortly, "shared". It is not strictly defined and you can use it creating your own standard. Of course, it would be foolish to put it on the item side of item-container association. But it easily could be on the both ends of association.
- Why the composition diamond can be only on one side? Because composition means, that items exist ONLY while exist reference to them from the container (or container itself). Of course, that couldn't work for both sides.
- On the contrary 'shared' on both sides often has sense. For example, Student instances can have a list of all courses attended, and Courses instance can have a list of all students attending.
- Often you can see name "aggregation" used for "shared aggregation". It is a BAD mistake. Because, according to standard,
composition
,shared
and evennone
, all three are aggregations.
So, composition is a subset of aggregation and aggregation is a feature of the association
For your first example, the first diagram, with composition, is correct. Your second option, referring to flightID as an int, could work but it's incomplete: that int by itself doesn't give you a way to access the Flight object. The Flight class doesn't magically store a list of flight objects that you can retrieve by number, so that second option would need a third class somewhere to store all the Flight objects.
For your second question, at the high level it really depends on personal preference (or your professor's personal preference!). Just try to use your best judgement.
精彩评论