Andres Aguiar's Weblog

Just My Code

July 2004 - Posts

JetBrains, Domain Specific Languages and Code Generation

There's a very interesting interview in codegeneration.net to JetBrains' Sergey Dmitriev.

O/R Mappers, the Law of Demeter, and Lazy Loading

 Sometime ago I blogged about the problems of using the same domain model from different layers.

 

Basically, my argument was that writing orderLine.Product.Price coupled your code with the object model structure, so I suggested it was better to write orderLine.ProductPrice.

 

This idea is not new, and is called the Law of Demeter.

 

One of the reasons I disliked O/R mappers was because, in my opinion, they forced you to write code such as orderLine.Product.Price. However, that's not necessarily true. A good O/R mapper should let you map the orderLine.ProductPrice to any field in the database that can be retrieved knowing the orderLine primary key.

 

For example, if the Price is not stored in the Product table but in a table that relates Customer and Product (to have a different price for each Customer), I can retrieve the product price from the OrderLine by using orderLine.Order.Customer.Id + orderLine.Product.Id to read CustomerProduct.Price.

 

Note that if I write orderLine.Product.Price and then the product price depends on the customer, there's no way to hide that. I cannot make Product.Price return the customer's price because I cannot obtain the 'Customer.Id' from the Product.

 

I don't know which O/R mappers support creating this mapping directly. But I do know Hibernate (a well-known Java O/R mapper) does not.

 

Of course, with any O/R mapper you can manually write the orderLine.ProductPrice to do something like the following:

 

public decimal ProductPrice

{

   get

   { 

      return CustomerProductFactory.Get(this.Order.Customer.Id, this.Product.Id).Price;

   } 

}

 

This way, you are not solving the problem at the mapping level but in the code.

 

Why do I think it's important to solve this at the mapping level? Because it's a good way to know when you need to eager load or to lazy load.

 

You are not going to add 'shortcut' properties in your classes for every reachable field. For example, if I'm not using the Product.Category.Name in the Order, then I won't have a CategoryName field in it.

 

If I add the shortcut, it’s because the field is relevant to the Order. So I can assume that if it's relevant to the order, it should be eager loaded.

 

In sum, if you want to apply the Law of Demeter to your domain model and your persistence layer, you should never write object.object.property, and you should use the shortcuts to know what to eager load.

 

If you know any O/R mapper that supports this at the mapping level, please let me know.

 

This is what we’ve always done with DeKlarit, but we are not an O/R mapper. In this case, we load DataSets with all the fields that are relevant to an Order, regardless of where they are stored.

NPersist - a new O/R mapper

The guys from Pragmatier are going to release a new free/open-source O/R mapper for .Net.

Mats announced it here.

I think it's a good idea. O/R mapping for .NET is going to be free in the long-term, so instead of fighting that war, is best to have a standard platform for free and build things on top of it. Hibernate went this way in the Java world and succeeded.

There are a number of other projects to do the same thing, but having a long-term O/R mapping technology vendor backing it up is not common among them.

Of course, making ideas a reality is a difficult game, but I whish them luck!

 

More Posts