Aggregation vs CompositionFiled Under: Weekly Tuesday Dose of goodness
Hi all,
Ok. This is really an object oriented post. Do forgive me if I’m not as guru or as strict as many OO purists out there. Remember that I do have to balance between a perfect design and a usable design.
In this article, I shall discuss about a topic taught in C++ Beginner level training.
Aggregation and Composition, what’s so different about them? Do I need have a good grasp of English in order to do it properly?
Read on…
Introduction
Many of us have been taught more or less in Object-Oriented Programming, which is a popular programming methodology used by many programmers and represented by several major languages including C++, Java and C# to name a few…
In OO, there’re many terms, some of which sounds alike, while others sound very sophisticated till it’s misunderstood.
The notion of K.I.S.S (keep it simple and stupid) seems to contradict many of the OO terminology in terms of understanding. Or does it?
We know that OO has quite a few terminologies, each representing a part of OO or a way of doing things. Today, we’re just going to take a look at Aggregation and Composition because I somewhat believe that the so-called thin line that separates them is what that confuse programmers who are not profficient in English.
Composition
Let’s take a look at composition first. Now in a class, there’re several basic building blocks that we know can exists. For example:
1) Access level Modifiers
2) Attributes
3) Methods
I shouldn’t have to explain what are modifiers. If I do, then this article is probably not meant for you.
Next, we have attributes and finally methods.
It’s basically telling other programmers that this class is composed of the following protected, private or public attributes.
So what does composed of mean? It simply means that the article is described or specified explicitly as being an integral part of the class. Which means to say, whenever an instance of this class is instantiated, the specified attribute will always be valid after construction and is part of the object.
“Valid” here means that the attribute itself is instantiated as well regardless of whether it’s a native, system or user-defined class type.
If we go deeper, this is what it’ll mean:
1) If the attribute is 12 bytes long (user-defined structure for example), then it must not be a pointer or reference to qualify as a composition.
2) Since it’s 12 bytes long, under struct alignment, it’ll take up 16 bytes of memory.
3) The object size is thus affected by the size of user-defined type.
4) Since it’s not a pointer or reference, the attribute is guaranteed to be instantiated either by its default constructor or a constructor chosen by the main class’ initialization list.
In such cases, when the copy constructor or the copy assignment operator is called, the default behavior will be a deep copy and will most likely remain as long as it’s a composition.
So in summary, an attribute composition is one that is part of or more correctly, composed of the class and is more likely to be available after construction and by design, will be deep copied.
Aggregation
Next, we’ll talk about aggregation. First of all, the very first confusion we’ll encounter is that, to qualify as an aggregation, the attribute must also be part of the class as well. The second confusion is, it seems as though as all natives are composition, all classes are aggregation.
Now, this confusion is exceptionally true for languages like Java and to some extent, C# as well. This is because, the notion of creating a stack object is virtually impossible in Java but somewhat possible in C#.
Just think, how do you create a user-defined object in Java (which is mutable)?
UserClass obj; //WRONG! obj.a = 0; //BOOM!
The right way would have been:
UserClass obj = new UserClass(); //instantiated obj.a = 0; //now it's usable
In C++, it’s very clear cut. In my previous article, if you should ever use the new operator (Yeah, new is an operator, not a special keyword) the object will always be created in the heap. If not, it’s on the stack yeah? Well, it depends.
Here’s the brain twist:
1) An object and its attributes are always created in the heap if the whole object is instantiated with the new operator.
2) An object and its attributes are always created in the stack if the whole object is declared in a function or method as it is.
3) If an object is instantiated with the new operator and its attributes are declared as it is, then the attribute is still instantiated as part of the object in the heap.
So, what has all these have to do with aggregation?
Well, basically, to qualify an attribute as an aggregation, that attribute must be a pointer or reference. We’re talking about C++ pointer and C++ reference.
Next, if an attribute is aggregated, there’s a chance that this actual object must not even exists.
Last but not least, an aggregated attribute is an association, not composed of.
To clear up the confusion, the only part that is composed of in an aggregation is the pointer itself, this applies to references as well even though they’re just aliases with a fixed referent. You see, a pointer takes up 4 bytes on a 32-bits machine. This 4 bytes must be stored somewhere right?
In this case, it’s stored as part of an attribute in the main object. Thus, the size of the aggregated object does not affect the final size of the main object since the size of the pointer will always remain constant (4 or 8 bytes for 32-bits and 64-bits respectively)
Lastly, an aggregation object is always a foreign object or to be clear, an object that is instantiated separately in a foreign location. While the object is aggregated, it’s not part of the class’ “hard” manifest.
Thus, an aggregated object is most likely to be shallow copied in the respective copy constructor and copy assignment operator. This of course can be changed when you override them for whatever design reasons that justify the deep copy.
Just note, the pointer itself is technically deep copied since the address (4 or 8 bytes) is copied over to the object copy. But do remember, it’s only the address, not the object, that is being copied over and thus should be considered in object-level, a shallow copy instead.
What’s the diff?!
Well, why not take a look at these 2 pictures below?
In fact, every attribute in this particular class is a composition.
In this case, the aggregation is clearly shown. Attribute C is a pointer while Object C which represents the actual object is somewhere out there in the heap. The rest are all compositions.
When should I use what?
It’s all in the design.
If the attribute is meant to be part of the class, then it should be a composition.
If the attribute is meant to be centralized for easy access, such a singleton that holds every single factory’s pointer, then it should be an aggregation.
Do note that aggregation, if abused, may lead to heavy memory fragmentation. How so? Since the object is nothing but a bunch of pointers (addresses) and the rest of the objects are somewhere out there in the heap, then yeah, the object chunk scatter will be greater (much alike an asteroid being blown into pieces). This thus lead to unusually high memory consumption for large number of small objects even when you have a projected heap size.
Conclusion
Unfortunately, this article doesn’t really apply completely to the Java and C# folks since you guys already have a VM to help you deal with things more or less.
It’s a pity though for Java in which a language that has been proclaimed as a pure Object Oriented language (better represented than C++) has the lack of ability to specify composition and aggregation explicitly. However I may be wrong, perhaps setting inner objects to be immutable may help?
Anyways, I do hope that this article can shed some light on these 2 seemingly confusing terminologies and as usual, please do not hesitate to correct me if you think that I’m wrong.
Have a great week ahead!
Signing off,
Jeremy
- Permalink
- Admin
- 20 Jul 2010 1:11 AM
- Comments (1)


August 6th, 2010 at 6:28 pm
To be incredible is to be misunderstood.
Sent from my iPhone 4G