Over a million developers have joined DZone.

Aggregation or Composition?

DZone's Guide to

Aggregation or Composition?

Confused about the difference between aggregation and composition—you're not alone. Luckily, MVB David Bernstein is here to help you to distinguish them from one another.

· Performance Zone ·
Free Resource

SignalFx is the only real-time cloud monitoring platform for infrastructure, microservices, and applications. The platform collects metrics and traces across every component in your cloud environment, replacing traditional point tools with a single integrated solution that works across the stack.

I often get questions when I teach object-oriented programming about the difference between aggregation and composition. These are two relationships that are easy to confuse.

Aggregation in the UML class diagram is represented by an open diamond whereas composition is represented as a closed or filled-in diamond. Related to this is the "uses" or "depends on" symbol which is indicated by an arrow. A closed arrow represents inheritance.

So why does the UML call out these different relationships? It is easy to see the difference between inheritance and dependency because inheritance is a very special kind of relationship and we have to explicitly call this out in code. But why does the UML call out the difference between aggregation and composition? It doesn't require any difference in coding syntax, at least not in managed code (we'll discuss unmanaged code in a moment).

It turns out that this distinction is not nearly as important today with managed languages as it was fifteen years ago when we didn't have automatic garbage collection in languages. In unmanaged languages like C or C++ the difference between aggregation and composition includes the notion that composed objects are memory managed by the one who composes them. In other words, if an object allocates memory for an object then it has the responsibility for de-allocating the memory when it's done using it. This is not necessarily true for aggregate objects. However, in managed memory languages like Java and C Sharp, this is no longer an important distinction because memory is cleaned up by the garbage collector.

But there is a conceptual difference between aggregation and composition. I like to illustrate it by talking about parking lots. A parking lot has both aggregation and composition in it. A parking lot is an area that aggregates cars. A parking lot is still a parking lot when there are no cars on it. Aggregation is just a place for the aggregates to inhabit.

By contrast, composition refers to a stronger relationship where the composed object is a required part of its composer. For example, a car is composed of an engine, a steering wheel, four tires, etc. By our definition, a car ceases to be a car if you remove the engine. Composition refers to a strong relationship between the composer and the composed.

I like to think of aggregation as referring to the "has-a" relationship and I like to think of composition as referring to the "has-to-has-a" relationship.

In many situations, we simply do not care whether we are aggregating or composing objects or it may not be clear or relevant to us at the point we are creating a class diagram, so we simply use the arrow that indicates "uses". This arrow indicates that one class uses or depends upon or calls methods upon another class, without specifying who allocates and de-allocates the memory or if the services they are using are required or optional for the other object.

There are only a handful of relationships in software development and in programming languages such as C++ or Java. It is of critical importance that we as developers use the right relationships. When we model using the right relationships it makes a better design. Virtually all of the Gang of Four's twenty-three design patterns are some variation on combining aggregation and inheritance.

One of the most pervasive problems that I see as a software development coach coming in to various organizations or working with various developers is the overuse of inheritance. Inheritance is important and useful but it is not a cure-all for every kind of relationship in programming and a lot of times developers overuse it or use it for the wrong reasons and they end up with brittle code as a result.

SignalFx is built on a massively scalable streaming architecture that applies advanced predictive analytics for real-time problem detection. With its NoSample™ distributed tracing capabilities, SignalFx reliably monitors all transactions across microservices, accurately identifying all anomalies. And through data-science-powered directed troubleshooting SignalFx guides the operator to find the root cause of issues in seconds.

aggregation ,composition ,gang of four ,design patterns ,memory ,garbage collection ,java ,c++

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}