Does aggregation have to be one-to-many? - uml

I've always avoided using aggregation because it seems so subjective which one-to-many relationships should be classed as aggregations. But I'm reviewing a model produced by someone else in which aggregations are used for many-to-many relationships (as in: a course consists of several modules, a module may be part of several courses). That strikes me as plain wrong, but I can't find a definitive rule against it. What's the official ruling?

Two things:
Are shared aggregations allowed? According to the UML spec, yes.
Is it useful in practice? Generally I'd say no.
I am not a fan of the UML Aggregation relationship. Whilst ownership is intuitively appealing, it is too subjective practically. I don't use it, and generally don't recommend it be used (although see footnote). Instead, focus on the important questions:
What's the cardinality?
What's the create/delete behaviour?
Why does the relationship exist? (i.e. what business fact/rule is the relationship capturing?
All above can be done with straight associations. If the answer is (a) it's one to many, (b) the 'one' end is responsible for creating/deleting the 'many' end and (c) you really want to, then use the Composite association. Aggregation however doesn't generally improve readability of the model, it adds confusion and detracts from surfacing the underlying domain rules/requirements.
hth.
footnote: there is one scenario where Aggregation does have well-defined semantics and can be useful. Specifically, if you have a recursive relationship, Aggregation says the resultant object structure is acyclic (i.e. a DAG). Downside is relatively few people realise that property - certainly not business domain experts. So you typically have to highlight anyway, e.g. in a comment / constraint.

A good website for this is
http://www.uml-diagrams.org/class-diagrams.html
If you search there for "Shared and Composite Aggregation" you will read, that shared parts can be modeled as aggregations. Even if the composite holding the part will be discarded the parts are allowed to survive.
This seems to make many to many relationships possible. For example sharing a part of a view for several view-components. Why not...
Personally this matches my understanding, that UML is very interpretative.

Let's set the terms. The Aggregation is a metaterm in the UML standard, and means BOTH composition and shared aggregation, simply named shared. To often it is named incorrectly "aggregation". It is BAD, for composition is an aggregation, too. As I understand, you mean "shared".
Again, if we'll look at the UML standards (look for Superstructure documentation there), we'll find, that "Precise semantics of shared aggregation varies by application area and modeler." So, ANY strategy you choose is acceptable. And you even can use different strategy for different projects.
But the shared aggregation IS useful and CAN be used with multiplicities on both sides and even the empty diamond can be on both sides.
The association in UML is an abstraction, that can be realized in any language and in any way, only the realization must be up to the diagram.
Such association, as on the diagram, can be realized as following:
Every instance of Student has a list of courses he is registered to,
and every instance of Courses has a list of registered
students/participants.
But this is not the only way of realization. There could be arrays instead of lists, and even somebody can make it without any normal collection at all - simply using the addresses in memory in C++.
Of course, we could draw two associations, one for student's list of courses and the second for courses' list of students. But thus:
our diagram becomes more complex and, therefore, less readable.
we are describing thoroughly the elementary things that any coder will do anyway in 99% cases.
we are limiting the freedom of coders. And in 1% of cases they'll have to choose between not following the diagram and not coding effectively. It is simply not your job.
So, do as you wish. Forbidden is only to change the strategy during one project and to FORBID others to use their only strategy.

Related

Class diagram - confused about aggregation [duplicate]

Here I am, with another question about aggregation and association. I wanted to learn some basics of UML, so I started reading "UML distilled" by Martin Fowler. I read both chapters about classes, and there is one thing that I can't fully grasp I think, and that is aggregation vs association. In the book there is this quote:
In the pre-UML days, people were usually rather vague on what was aggregation and what was
association. Whether vague or not, they were always inconsistent with everyone else. As a result,
many modelers think that aggregation is important, although for different reasons. So the UML
included aggregation (Figure 5.3) but with hardly any semantics. As Jim Rumbaugh says, "Think of it
as a modeling placebo" [Rumbaugh, UML Reference].
As I understand from this quote and topics that I read on Stack Overflow it doesn't matter which one of those two relations I use, they mean basically the same, or is there any situation where the usage of aggregation instead of association would be justified and/or I could not change one to the other without changing the "meaning" of a class diagram?
I am asking this, because this book is from 2003 and some things could have changed during those few years.
Maybe this can help you, but i don't think you will find the perfect explanation:
The difference is one of implication. Aggregation denotes whole/part
relationships whereas associations do not. However, there is not
likely to be much difference in the way that the two relationships are
implemented. That is, it would be very difficult to look at the code
and determine whether a particular relationship ought to be
aggregation or association. For this reason, it is pretty safe to
ignore the aggregation relationship altogether. [Robert C. Martin | UML]
And an example for each situation:
a) Association is a relationship where all object have their own
lifecycle and there is no owner. Let’s take an example of Teacher and
Student. Multiple students can associate with a single teacher and
single student can associate with multiple teachers, but there is no
ownership between the objects and both have their own lifecycle. Both
can create and delete independently.
b) Aggregation is a specialized form of Association where all object have their own lifecycle but there is ownership and child
object can not belong to another parent object. Let’s take an example
of Department and teacher. A single teacher can not belong to
multiple departments, but if we delete the department, the teacher object
will not be destroyed. We can think about “has-a” relationship.[Maesh | GeeksWithBlogs]
Rumbaugh's statement is the most telling and Uncle Bob's good advice. As I've said elsewhere, Aggregation is semantically so weak as to offer nothing practically beneficial. It only has one valid corner case (acyclicity of recursive relationships) however few people know and understand that. So you end up having to point out in comments anyway.
I just don't use it. And have never felt any loss. Stick with simple binary associations and focus on what really matters - getting the cardinality and naming right. You'll get far more from that than trying to decide the undecidable association vs. aggregation.
hth.
I tend to use Aggregation to show a relation that is the same as a Composition with one big distinction: the containing class is NOT responsible for the life-cycle of the contained object. Typically, a (non-null) pointer or reference to the object-to-be-contained is passed to the containing class's constructor. The containing object, for the duration of its life-cycle, depends upon the contained object existing. The containing object cannot do its job (fully) without the contained object. This is my interpretation of the "Part/Whole" relationship implied by Aggregation.
This term often gets confused.
Aggregation and composition are some of the types of association. There is
hardly a difference between aggregations and associations during
implementation, and many will skip aggregation relations altogether in
their diagrams with association relation.
You can get the idea from this analogy.
Class:A(person) and Class:B(car) has association relation, if
Class:A has a Class:B declaration, and also Class:B(car) object is not essential to create a Class:A(person) object.
Class:A(car) and Class:B(tyre) has aggregation relation, if
Class:A has a Class:B declaration, and also Class:B(tyre) object is essential to create a Class:A(car) object.
Cheers!
In UML aggregation is under-defined and since they haven't got any clearly defined semantic.
A valid use-case of an aggregation is the encapsulation of a several classes, as stated in "Domain Driven Design" by Eric Evans.
E.g. a car has four wheels.
You might want to calculate the total amount of meters each wheel has driven, for each car.
This calculation is done by the car-entity, since it knows which wheels it has and you don't care which wheels belong to which car.
The car is the aggregation-root for all it's parts, like wheels, and you can't access the parts of a car from outside the aggregation, just the root.
So basically an aggregation encapsulates a set of classes which belong to each other.
They do not mean the same! I can put it in this way:
Association relationship: A class references another class. Actually it shows that a class is related to another class but they
don't necessarily have attributes to show this relationship... e.g
'Teacher' and 'Student' classes, although 'Teacher' class has no
attribute that refer to students, but we do know that in reality a
teacher do have students... And also 'School' class has 'teachers' and
'students' properties that now make those two classes related to each
other.
Aggregation relationship: A class contains another class. But if the container(ClassRoom) is destroyed, the contained(Chair) is not.
Actually the ClassRoom owns the Chair. Aggregation is a more stronger
relationship than the Association relationship.
Here is also a tutorial about it and the whole UML2.0 which explains everything easy and simple, you may find it useful: https://github.com/imalitavakoli/learn-uml2
TIP: Also let me mention that because the Association relationship exists between classes most of the times, we sometimes don't draw it to prevent unnecessary complexity.
Implementation wise there is not much of a difference but conceptually there is big difference: aggregations are used to express a hierarchy. When you work with a hierarchy of components there are certain type of operations you need to have in the root interface:
find subcomponents in the hierarchy
add/remove subcomponents to/from the hierarchy
change common attributes of all components
traverse the hierarchy recursively (Visitor pattern)
reconfigure the hierarchy and the links (associations) between the components
Most of these operations are not needed when dealing with associations.
To add, I would just suggest to download the UML specification from the OMG site: best reference and see p 110.
None indicates that the property has no aggregation semantics.
Shared indicates that the property has shared aggregation semantics. Precise semantics of shared aggregation varies by application area and modeler.
Composite indicates that the property is aggregated compositely, i.e., the composite object has responsibility for
the existence and storage of the composed objects (see the definition of parts in 11.2.3).

UML class diagram Aggregation vs. Association [duplicate]

Here I am, with another question about aggregation and association. I wanted to learn some basics of UML, so I started reading "UML distilled" by Martin Fowler. I read both chapters about classes, and there is one thing that I can't fully grasp I think, and that is aggregation vs association. In the book there is this quote:
In the pre-UML days, people were usually rather vague on what was aggregation and what was
association. Whether vague or not, they were always inconsistent with everyone else. As a result,
many modelers think that aggregation is important, although for different reasons. So the UML
included aggregation (Figure 5.3) but with hardly any semantics. As Jim Rumbaugh says, "Think of it
as a modeling placebo" [Rumbaugh, UML Reference].
As I understand from this quote and topics that I read on Stack Overflow it doesn't matter which one of those two relations I use, they mean basically the same, or is there any situation where the usage of aggregation instead of association would be justified and/or I could not change one to the other without changing the "meaning" of a class diagram?
I am asking this, because this book is from 2003 and some things could have changed during those few years.
Maybe this can help you, but i don't think you will find the perfect explanation:
The difference is one of implication. Aggregation denotes whole/part
relationships whereas associations do not. However, there is not
likely to be much difference in the way that the two relationships are
implemented. That is, it would be very difficult to look at the code
and determine whether a particular relationship ought to be
aggregation or association. For this reason, it is pretty safe to
ignore the aggregation relationship altogether. [Robert C. Martin | UML]
And an example for each situation:
a) Association is a relationship where all object have their own
lifecycle and there is no owner. Let’s take an example of Teacher and
Student. Multiple students can associate with a single teacher and
single student can associate with multiple teachers, but there is no
ownership between the objects and both have their own lifecycle. Both
can create and delete independently.
b) Aggregation is a specialized form of Association where all object have their own lifecycle but there is ownership and child
object can not belong to another parent object. Let’s take an example
of Department and teacher. A single teacher can not belong to
multiple departments, but if we delete the department, the teacher object
will not be destroyed. We can think about “has-a” relationship.[Maesh | GeeksWithBlogs]
Rumbaugh's statement is the most telling and Uncle Bob's good advice. As I've said elsewhere, Aggregation is semantically so weak as to offer nothing practically beneficial. It only has one valid corner case (acyclicity of recursive relationships) however few people know and understand that. So you end up having to point out in comments anyway.
I just don't use it. And have never felt any loss. Stick with simple binary associations and focus on what really matters - getting the cardinality and naming right. You'll get far more from that than trying to decide the undecidable association vs. aggregation.
hth.
I tend to use Aggregation to show a relation that is the same as a Composition with one big distinction: the containing class is NOT responsible for the life-cycle of the contained object. Typically, a (non-null) pointer or reference to the object-to-be-contained is passed to the containing class's constructor. The containing object, for the duration of its life-cycle, depends upon the contained object existing. The containing object cannot do its job (fully) without the contained object. This is my interpretation of the "Part/Whole" relationship implied by Aggregation.
This term often gets confused.
Aggregation and composition are some of the types of association. There is
hardly a difference between aggregations and associations during
implementation, and many will skip aggregation relations altogether in
their diagrams with association relation.
You can get the idea from this analogy.
Class:A(person) and Class:B(car) has association relation, if
Class:A has a Class:B declaration, and also Class:B(car) object is not essential to create a Class:A(person) object.
Class:A(car) and Class:B(tyre) has aggregation relation, if
Class:A has a Class:B declaration, and also Class:B(tyre) object is essential to create a Class:A(car) object.
Cheers!
In UML aggregation is under-defined and since they haven't got any clearly defined semantic.
A valid use-case of an aggregation is the encapsulation of a several classes, as stated in "Domain Driven Design" by Eric Evans.
E.g. a car has four wheels.
You might want to calculate the total amount of meters each wheel has driven, for each car.
This calculation is done by the car-entity, since it knows which wheels it has and you don't care which wheels belong to which car.
The car is the aggregation-root for all it's parts, like wheels, and you can't access the parts of a car from outside the aggregation, just the root.
So basically an aggregation encapsulates a set of classes which belong to each other.
They do not mean the same! I can put it in this way:
Association relationship: A class references another class. Actually it shows that a class is related to another class but they
don't necessarily have attributes to show this relationship... e.g
'Teacher' and 'Student' classes, although 'Teacher' class has no
attribute that refer to students, but we do know that in reality a
teacher do have students... And also 'School' class has 'teachers' and
'students' properties that now make those two classes related to each
other.
Aggregation relationship: A class contains another class. But if the container(ClassRoom) is destroyed, the contained(Chair) is not.
Actually the ClassRoom owns the Chair. Aggregation is a more stronger
relationship than the Association relationship.
Here is also a tutorial about it and the whole UML2.0 which explains everything easy and simple, you may find it useful: https://github.com/imalitavakoli/learn-uml2
TIP: Also let me mention that because the Association relationship exists between classes most of the times, we sometimes don't draw it to prevent unnecessary complexity.
Implementation wise there is not much of a difference but conceptually there is big difference: aggregations are used to express a hierarchy. When you work with a hierarchy of components there are certain type of operations you need to have in the root interface:
find subcomponents in the hierarchy
add/remove subcomponents to/from the hierarchy
change common attributes of all components
traverse the hierarchy recursively (Visitor pattern)
reconfigure the hierarchy and the links (associations) between the components
Most of these operations are not needed when dealing with associations.
To add, I would just suggest to download the UML specification from the OMG site: best reference and see p 110.
None indicates that the property has no aggregation semantics.
Shared indicates that the property has shared aggregation semantics. Precise semantics of shared aggregation varies by application area and modeler.
Composite indicates that the property is aggregated compositely, i.e., the composite object has responsibility for
the existence and storage of the composed objects (see the definition of parts in 11.2.3).

UML - association or aggregation (simple code snippets)

I drives me crazy how many books contradicts themselves.
Class A {} class B {void UseA(A a)} //some say this is an association,
no reference is held but communication is possible
Class A {} class B {A a;} //some say this is
aggregration, a reference is held
But many say that holding a reference is still just an association and for aggregation they use a list - IMHO this is the same, it it still a reference.
I am very confused, I would like to understand the problem.
E.g. here: http://aviadezra.blogspot.cz/2009/05/uml-association-aggregation-composition.html - what is the difference between Strong Association and Aggregation, in both cases the author uses a field to store the reference..
Another example:
This is said to be Association:
And this is said to be Aggregration:
public class Professor {
// ...
}
public class Department {
private List<Professor> professorList;
// ..
}
Again, what is the difference? It is a reference in both cases
This question has been, and will be, asked many times in many different variants, because many people, including many high-profile developers, are confused about the meaning of these terms, which have been defined in the UML. Since the question has been asked many times, it has also been answered many times. See, e.g. this answer. I'll try to summarize the UML definitions.
An association between two classes is not established via a method parameter, but rather via reference properties (class attributes), the range/type of which are the associated classes. If the type of a method parameter is a class, this does not establish an association, but a dependency relationship.
It's essential to understand the logical concept of associations first, before looking at how they are coded. An association between object types classifies relationships between objects of those types. For instance, the association Committee-has-ClubMember-as-chair, which is visualized as a connection line in the class diagram shown below, may classify the relationships FinanceCommittee-has-PeterMiller-as-chair, RecruitmentCommittee-has-SusanSmith-as-chair and AdvisoryCommittee-has-SarahAnderson-as-chair, where the objects PeterMiller, SusanSmith and SarahAnderson are of type ClubMember, and the objects FinanceCommittee, RecruitmentCommittee and AdvisoryCommittee are of type Committee.
An association is always encoded by means of reference properties, the range/type of which is the associated class. For instance, like so
class Committee { ClubMember chair; String name;}
In the UML, aggregation and composition are defined as special forms of associations with the intended meaning of classifying part-whole-relationships. In the case of aggregation, as opposed to composition, the parts of a whole can be shared with other wholes. This is illustrated in the following example of an aggregation, where a course can belong to many degree programs.
The defining characteristic of a composition is to have exclusive (or non-shareable) parts. A composition may come with a life-cycle dependency between the whole and its parts implying that when a whole is destroyed, all of its parts are destroyed with it. However, this only applies to some cases of composition, and not to others, and it is therefore not a defining characteristic. An example of a composition where the parts (components) can be detached from the whole (composite) and therefore survive its destruction, is the following:
See Superstructures 2.1.1:
An association may represent a composite aggregation (i.e., a whole/part relationship). Only binary associations can be aggregations. Composite aggregation is a strong form of aggregation that requires a part instance be included in at most one composite at a time. If a composite is deleted, all of its parts are normally deleted with it. Note that a part can (where allowed) be removed from a composite before the composite is deleted, and thus not be deleted as part of the composite. Compositions may be linked in a directed acyclic graph with transitive deletion characteristics; that is, deleting an element in one part of the graph will also result in the deletion of all elements of the subgraph below that element. Composition is represented by the isComposite attribute on the part end of the association being set to true.
Navigability means instances participating in links at runtime (instances of an association) can be accessed efficiently from instances participating in links at the other ends of the association. The precise mechanism by which such access is achieved is implementation specific. If an end is not navigable, access from the other ends may or may not be possible, and if it is, it might not be efficient. Note that tools operating on UML models are not prevented from navigating associations from non-navigable ends.
Your above examples are on different abstraction levels. Department/Course are concrete coding classes while Department/Professor are at some abstract business level. Though there is no good source (I know) explaining this fact, composition and aggregation are concepts you will use only on business level and almost never at coding level (exception below). When you are at code level you live much better with Association having role names on both sides. Roles themselves are a different(/redundant!) rendering of properties of a class that refer to the opposite class.
Aggregation as a strong binding between classes is used e.g. in database modeling. Here you can delete a master only if the aggregates have all been deleted previously (or vice vera: deleting the master will force deletion of the aggregates). The aggregate can not live on its own. The composition as in your example is (from my POV) a silly construct as it pretends to be some week aggregation. But that's simply nonsense. Then use an association. Only on a business level you can try to model (e.g.) machine parts as composite. On a concrete level a composition is a useless concept.
tl;dr;
If there is a relation between classes show it as simple association. Adding details like roles will aid when discussing domain details. Use of composition/aggregation is encouraged only when modeling on business level and dis-encouraged on code level.
I've written an article about the differences between UML Association vs Aggregation vs Composition based on the actual UML specification rather then interpretations of book authors.
The primary conclusion being that
In short, the Composition is a type of Association with real constraints and impact on development, whereas the Aggregation is purely a functional indication of the nature of the Association with no technical impact.
Navigability is a completely different property and independent of the AggregationKind.
For one thing, UML is a rich language, meaning there is more than one way to describe the same thing. That's one reason you find different ways described in different books (and conflicting answers on SO).
But a key issue is the huge disconnect between UML and source code. How a specific source code construct is represented in UML, and vice versa, is not part of the UML specification at all. To my knowledge, only one language (Java) has an official UML profile, and that's out of date.
So the representation of specific source-language constructs are left to the tool vendors, and therefore differ. If you intend to generate code from your model, you must follow the vendor's conventions. If, conversely, you wish to generate a model from existing source code, you get a model based on those same conventions. But if you transfer that model to a different tool (which is difficult at the best of times) and generate code out of that, you won't end up with the same code.
In language-and-tool-agnostic mode, my take on which relationships to use in which situations can be found here. One point there worth repeating is that I don't use undirected associations in source-code models, precisely because they have no obvious counterpart in actual code. If in the code class A has a reference to class B, and B also has one to A, then I draw two relationships instead.

UML aggregation vs association

Here I am, with another question about aggregation and association. I wanted to learn some basics of UML, so I started reading "UML distilled" by Martin Fowler. I read both chapters about classes, and there is one thing that I can't fully grasp I think, and that is aggregation vs association. In the book there is this quote:
In the pre-UML days, people were usually rather vague on what was aggregation and what was
association. Whether vague or not, they were always inconsistent with everyone else. As a result,
many modelers think that aggregation is important, although for different reasons. So the UML
included aggregation (Figure 5.3) but with hardly any semantics. As Jim Rumbaugh says, "Think of it
as a modeling placebo" [Rumbaugh, UML Reference].
As I understand from this quote and topics that I read on Stack Overflow it doesn't matter which one of those two relations I use, they mean basically the same, or is there any situation where the usage of aggregation instead of association would be justified and/or I could not change one to the other without changing the "meaning" of a class diagram?
I am asking this, because this book is from 2003 and some things could have changed during those few years.
Maybe this can help you, but i don't think you will find the perfect explanation:
The difference is one of implication. Aggregation denotes whole/part
relationships whereas associations do not. However, there is not
likely to be much difference in the way that the two relationships are
implemented. That is, it would be very difficult to look at the code
and determine whether a particular relationship ought to be
aggregation or association. For this reason, it is pretty safe to
ignore the aggregation relationship altogether. [Robert C. Martin | UML]
And an example for each situation:
a) Association is a relationship where all object have their own
lifecycle and there is no owner. Let’s take an example of Teacher and
Student. Multiple students can associate with a single teacher and
single student can associate with multiple teachers, but there is no
ownership between the objects and both have their own lifecycle. Both
can create and delete independently.
b) Aggregation is a specialized form of Association where all object have their own lifecycle but there is ownership and child
object can not belong to another parent object. Let’s take an example
of Department and teacher. A single teacher can not belong to
multiple departments, but if we delete the department, the teacher object
will not be destroyed. We can think about “has-a” relationship.[Maesh | GeeksWithBlogs]
Rumbaugh's statement is the most telling and Uncle Bob's good advice. As I've said elsewhere, Aggregation is semantically so weak as to offer nothing practically beneficial. It only has one valid corner case (acyclicity of recursive relationships) however few people know and understand that. So you end up having to point out in comments anyway.
I just don't use it. And have never felt any loss. Stick with simple binary associations and focus on what really matters - getting the cardinality and naming right. You'll get far more from that than trying to decide the undecidable association vs. aggregation.
hth.
I tend to use Aggregation to show a relation that is the same as a Composition with one big distinction: the containing class is NOT responsible for the life-cycle of the contained object. Typically, a (non-null) pointer or reference to the object-to-be-contained is passed to the containing class's constructor. The containing object, for the duration of its life-cycle, depends upon the contained object existing. The containing object cannot do its job (fully) without the contained object. This is my interpretation of the "Part/Whole" relationship implied by Aggregation.
This term often gets confused.
Aggregation and composition are some of the types of association. There is
hardly a difference between aggregations and associations during
implementation, and many will skip aggregation relations altogether in
their diagrams with association relation.
You can get the idea from this analogy.
Class:A(person) and Class:B(car) has association relation, if
Class:A has a Class:B declaration, and also Class:B(car) object is not essential to create a Class:A(person) object.
Class:A(car) and Class:B(tyre) has aggregation relation, if
Class:A has a Class:B declaration, and also Class:B(tyre) object is essential to create a Class:A(car) object.
Cheers!
In UML aggregation is under-defined and since they haven't got any clearly defined semantic.
A valid use-case of an aggregation is the encapsulation of a several classes, as stated in "Domain Driven Design" by Eric Evans.
E.g. a car has four wheels.
You might want to calculate the total amount of meters each wheel has driven, for each car.
This calculation is done by the car-entity, since it knows which wheels it has and you don't care which wheels belong to which car.
The car is the aggregation-root for all it's parts, like wheels, and you can't access the parts of a car from outside the aggregation, just the root.
So basically an aggregation encapsulates a set of classes which belong to each other.
They do not mean the same! I can put it in this way:
Association relationship: A class references another class. Actually it shows that a class is related to another class but they
don't necessarily have attributes to show this relationship... e.g
'Teacher' and 'Student' classes, although 'Teacher' class has no
attribute that refer to students, but we do know that in reality a
teacher do have students... And also 'School' class has 'teachers' and
'students' properties that now make those two classes related to each
other.
Aggregation relationship: A class contains another class. But if the container(ClassRoom) is destroyed, the contained(Chair) is not.
Actually the ClassRoom owns the Chair. Aggregation is a more stronger
relationship than the Association relationship.
Here is also a tutorial about it and the whole UML2.0 which explains everything easy and simple, you may find it useful: https://github.com/imalitavakoli/learn-uml2
TIP: Also let me mention that because the Association relationship exists between classes most of the times, we sometimes don't draw it to prevent unnecessary complexity.
Implementation wise there is not much of a difference but conceptually there is big difference: aggregations are used to express a hierarchy. When you work with a hierarchy of components there are certain type of operations you need to have in the root interface:
find subcomponents in the hierarchy
add/remove subcomponents to/from the hierarchy
change common attributes of all components
traverse the hierarchy recursively (Visitor pattern)
reconfigure the hierarchy and the links (associations) between the components
Most of these operations are not needed when dealing with associations.
To add, I would just suggest to download the UML specification from the OMG site: best reference and see p 110.
None indicates that the property has no aggregation semantics.
Shared indicates that the property has shared aggregation semantics. Precise semantics of shared aggregation varies by application area and modeler.
Composite indicates that the property is aggregated compositely, i.e., the composite object has responsibility for
the existence and storage of the composed objects (see the definition of parts in 11.2.3).

Am I allowed to have "incomplete" aggregates in DDD?

DDD states that you should only ever access entities through their aggregate root. So say for instance that you have an aggregate root X which potentially has a lot of child Y entities. Now, for some scenario, you only really care about a subset of these Y entities at a time (maybe you're displaying them in a paged list or whatever).
Is it OK to implement a repository then, so that in such scenarios it returns an incomplete aggregate? Ie. an X object who'se Ys collection only contains the Y instances we're interested in and not all of them? This could for instance cause methods on X which perform some calculation involving the Ys to not behave as expected.
Is this perhaps an indication that the Y entity in question should be considered promoted to an aggregate root?
My current idea (in C#) is to leverage the delayed execution of LINQ, so that my X object has an IQueryable to represent its relationship with Y. This way, I can have transparent lazy loading with filtering... But getting this to work with an ORM (Linq to Sql in my case) might be a bit tricky.
Any other clever ideas?
I consider an aggregate root with a lot of child entities to be a code smell, or a DDD smell if you will. :-) Generally I look at two options.
Split your aggregate into many smaller aggregates. This means that my original design was not optimal and I need to identify some new entities.
Split your domain into multiple bounded contexts. This means that there are specific sets of scenarios that use a common subset of the entities in the aggregate, while there are other sets of scenarios that use a different subset.
Jimmy Nilsson hints in his book that instead of reading a complete aggregate you can read a snapshot of parts of it. But you are not supposed to be able to save changes in the snapshot classes to the database.
Jimmy Nilsson's book Chapter 6: Preparing for infrastructure - Querying. Page 226.
Snapshot pattern
You're really asking two overlapping questions.
The title and first half of your question are philosophical/theoretical. I think the reason for accessing entities only through their "aggregate root" is to abstract away the kinds of implementation details you're describing. Access through the aggregate root is a way to reduce complexity by having a trusted point of access. You're eliminating friction/ambiguity/uncertainty by adhering to a convention. It doesn't matter how it's implemented within the root, you just know that when you ask for an entity it will be there. I don't think this perspective rules out a "filtered repository" as you describe. But to provide a pit of success for devs to fall into, it should be impossible instantiate the repository without being explicit about its "filteredness;" likewise, if shared access to a repository instance is possible, the "filteredness" should be explicit when coding in the caller.
The second half of your question is about implementation on a specific platform. Not sure why you mention delayed execution, I think that's really orthogonal to the filtering question. The filtering itself could be a bit tricky to implement with LINQ. Maybe rather than inlining the Where lambdas, you set up a collection of them and select one depending on the filter you need.
You are allowed since the code will compile anyway, but if you're going for a pure DDD design you should not have incomplete instances of objects.
You should look into LazyLoading if you're afraid to load a huge object of which you will only use a small portion of its child entities.
LazyLoading delays the loading of whatever you decide to lazy-load until the moment they are accessed. They make use of callbacks to call the loading method once the code calls for them.
Is it OK to implement a repository then, so that in such scenarios it
returns an incomplete aggregate?
Not at all. Aggregate is a transnational boundary to change the state of your system. Never use aggregates for querying data. Split the system into Write and Read sides. (read about CQR & CQRS). When we think "CRUD" based, we implement our system, based on some resource. Lets say you have "Appointment" aggregate. Thinking "Crudish" means we should implement usecases Create, Update, Delete, GetAll appointments. That means Appointment[] should be returned for GetAll. When you think usecase based, (HexagonalArchitecture) your usecases would be ScheduleAppointment, RescheduleAppointment, CancelAppointment. But for query side it can be: /myCalendar. We return back all appointments for a specific user in a ClientCalendar object. Create separate DTO's for Query sides. Never use aggregates for this purpose.

Resources