Saturday, December 11, 2010

Ternary associations

I'm often surprised by how many designers/developers are unfamiliar with the notion of a ternary association. To me, they represent a natural decomposition of a relationship between two objects. There is a certain symmetry that is pleasant both intellectually and aesthetically, additionally appealing to the (I seem to remember) Wirfs-Brock notion of distributed intelligence in object systems being a goal worthy of achieving (for a variety of reasons).

In the finance industry, these relationship types fairly seem to assail you from all sides. Take the canonical interpretation of a funds transfer (c.f. payment). At its simplest level, this is a process - the act of moving funds from a source account (source) to a target account (sink). But on further inspection it becomes obvious that the nature of the process itself holds state and behaviour that is not peculiar to either of the parties in the transaction, and thus lends itself to ternary association modelling. Trivially, you might model simple properties (such as a boolean property representing 'intra bank' transfers; if the putative transfer is valid and so on) in this process class; and also behaviour (whether this process is potentially a fradulent/risk attracting one).

The typical UML like representation of a ternary association is as below:

Here, of course, the Payment abstraction represents the ternary association, aggregating behaviour such as that already mentioned. Representation of a ternary in 'concrete' coding terms is usually straightforward. Almost never is a bi-directional association the mechanism to employ; almost always, a completely separate object is required, and in this case it would not be remiss to have the Payment type reference both Source and Sink directly. In fact, one would expect an instance of Payment to be the object that was dealt with directly. Such payments could be created directly or via a factory of some sort.

But is that really a ternary association, or just a simple pair of associations between one object and two other dependents. Why is it not just a whole/part example? If you refer to a payment as a process, why make the distinction at all, as the source and sink objects would surely just be participants in the process itself?

In this case, I think the reference to a ternary is valid; the payment does in fact expose behaviour and derived state that is attributable to the relationships between two discrete objects. And I don't believe that the cardinality of the relationships between the two 'simple' objects has to be many to many for this modelling technique to make sense.

No comments: