April 11, 2005

...Learn TDD with Codemanship

OCL Collections and UML Associations

A lot of people get mixed up when using OCL collections in respect of their class diagrams. While the OCL spec makes it quite clear about the differences between a Set, a Bag and a Sequence, the bit that doesn't stand out (blink and you'll miss it) is where these collection types apply in a UML model.

Here's a quick reminder of the OCL collection heirarchy:



Very briefly, a Set is a collection where any element can appear only once and in any order. A Bag is a collection of elements that can appear more than once and in any order. A Sequence is a collection of elements that can appear more than once, but are in a specific order. Of course, in real systems we may need yet more specialised collections, like an OrderedSet - which OCL 2.0 proviudes for, I believe (though I might be wrong) - but for the sake of simplicity, let's not concern ourselves we've these extra specialisms.

The question is, when do we know that we're dealing with a Set as opposed to a Bag or a Sequence? Take this simple class model, for example:



If we navigate from a library to the association end book - ie, library.book - what kind of OCL collection do we end up with? According to the OCL spec, we will end up with a Set. Set is the default collection type for anything with multiplicity greater than 1.

What if the collection is ordered?



Intuitively, if we navigating from PhoneLog to association end call - ie, phoneLog.call - we would expect to end up with elements in the collection being in a specific order - ie, a Sequence.

But when would we end up with a Bag? Well, imagine what we might end up with if we navigated across two Sets:



If we navigated like so - library.book.author - which is the same in OCL as saying:

library.book->collect(author)

and we recall that OCL flattens collections of collections, then we can imagine more than one book with the same author ending up in the resulting collection. Since a Set is in no particular order, we would end up with a collection of elements that may appear more than once and in no specific order - in other words, a Bag. So whenever we flatten collections of collections, we expect to end up with a Bag.

To get a different kind of collection (eg, the collection of all authors that have books in a specific library), we need to use the appropriate operation to convert the library.book.author Bag into a Set:

library.book.author->asSet()

I hope that's cleared things up!


Posted 15 years, 10 months ago on April 11, 2005