Distinguishing Compositions and Associations
For all the application developers out there, this is a request for comments. In business apps there are generally two types of relationships: compositions and associations. Compositions are tightly-coupled relationships where the composition's lifetime is tied to its parent. Associations are loosely-coupled reference relationships. In designing a prescriptive framework such as the Microsoft Business Framework, it may be beneficial to the application developer to distinguish compositions and associations from each other while coding in a way that does not involve referring to the documentation. In other words, how can I tell that when I navigate from Order to Customer (as in Order.Customer) that I am referring to an association rather than a composition?
So two questions for everyone:
- How useful would it be to be able to distinguish between compositions and associations when coding against those relationships?
- What ideas do you have to help make that distinction?
Comments
- Anonymous
August 20, 2004
- I really don't know how useful it would be with the notational complexity that would come with it. Or in the case below with the implicit operators its only a declarative property. But as .NET programmers usually is quite bliss about lifetime and resources it might be good to force them to think about it in the design phase and have it expressed in code.
2. The obvious solutions as I see it within the .NET environment would be to use some kind of naming convention I.e Order.CustomerRef or by using functions for references lik Order.GetCustomer()/Order.SetCustomer(cust) or Order.Customer()/Order.Customer(cust). This is as opposed to Order.ShippingAddress = new Address(); for containment/composition.
Another solution wich i would prefer be to use some kind of generic Ref and/or Val class to denote a reference or containment.
struct Ref <T>
{
private T _ref;
public Ref(T reference) { _ref = reference; }
public T Ref { get { return _ref; } }
}
declared like
Ref<Customer> Customer;
used like
order.Customer = new CustomerRef(lookup.GetCustomer(4711));
Customer c = order.Customer.Ref;
struct Val <T>
{
private T _val;
public Val(T val) { _val = value; }
public T Val { get { return _val; } }
}
The value class could use real value semantics if T supports cloneable and make an actual clone of T when assigning it.
Adding implicit operators this can be used
public static implicit operator T(Ref<T> r) { return r.Ref; }
public static implicit operator Ref<T>(T r) { return new Ref<T>(r); }
It can be declared as Ref or Val but still used in code as usual.
In C++ I have used shared_ptr/ptr types as opposed to references or value types to distinguis the two kinds of relationships in my models. But I don't see how this cleanly can be transferred to .NET.
- Anonymous
August 20, 2004
- As you guys already mentioned, lifetime management could benefit, e.g. need to call Dispose on the dependents. Also, some code-generating or mapping tools could get a little smarter; say, for generating a database persistence layer.
2. Relationships with 1:n cardinalities are good composition candidates. In WMI/CIM you have weak associations or in relational databases the foreign key attributes being part of the primary key. If your object can only be identified within the scope of another object, it’s likely to be part of a composition.
In the Order.Customer situation, if you'd have a database, there would be a foreign key in Order identifying the Customer, not vice versa.
- Anonymous
August 26, 2004
Do you really need to differentiate between the concepts of composition and association?
Can't you just deal with individual behaviours in the meta-data (XML or attributes) of the reference?
For example...
When you talk about lifetime control I assume you are talking about cascading things like updates and deletes up and down the object graph. Can't you just provide a cascade .net attribute/XML mapping atttribute that provides information about the cascading of updates and deletes?
e.g.
In class Cat...
[CascadeDelete, CascadeUpdate]
List<Kitten> Kittens;
Or in the metadata file Cat.mbf.xml...
...Property=Kittens CascadeDelete=true CascadeUpdate=true... - Anonymous
August 27, 2004
The comment has been removed