Law of Demeter: Some thoughts
Phil Haack wrote a post a few weeks ago about the law of demeter and how it’s not just about reducing the number of dots that appear on one line.
This is a nice side effect of following the law of demeter but I often feel that the main benefit we get from following it is that code becomes easier to change since we haven’t exposed the state of an object all over the place.
I think there are two parts to the law of demeter:
-
That we don’t dig into the internals of objects to retrieve the data we want i.e. 'foo.bar.baz.qux' in Phil’s example but instead create methods on the top level object which delegate to get us the data that we need. In this case we might have 'foo.bar_baz_qux' for example.
-
That we follow tell don’t ask and never retrieve data from an object and then do something with that data, but instead tell the object to do something for us.
The second is harder to find fault with and is generally considered good design. Dan Manges' post on this is the best piece of writing I’ve seen on the subject - definitely worth reading.
The first definitely seems to be more contentious from what I’ve noticed and it seems like we mostly run into trouble when it comes to the boundaries of our domain layer e.g. interacting with a user interface or with another system.
Getting data onto the view
The user interface is an interesting place to start because the majority of applications we write have to interact with the user somehow and then we need to work out how we’re going to display information to them.
Every web framework I’ve worked with makes use of template style pages to display data so we need to somehow get the data out of our domain objects and into these templates.
I’ve come across a few ways to do this:
Directly exposing domain objects
The first and perhaps most obvious way is to expose domain objects to the view directly but when we use this approach I think we need to be careful that we don’t end up inadvertently putting domain logic into the view.
I think it’s also quite important to make sure that we only expose read only versions of properties of our objects if we choose to take this approach otherwise our objects will become really difficult to understand. Dhanji Prasanna has an interesting article about immutability in our code which I think applies here.
The other problem is that once you start exposing properties/getters on your objects then the temptation is there to make use of these properties from other places in our code whereby we run the risk of breaking the idea of tell don’t ask.
Once we do this the difficulty of maintaining code seems to increase quite substantially so if we can avoid that happening it’s a good thing.
View Data Container
An alternative is to make use of a 'ViewData' container which I mentioned briefly on a post I wrote about micro types.
The idea here is that our objects can write themselves into the 'ViewData' container which is then made accessible from the view. The view can then take whichever data it is interested out of the container.
Although this approach reduces the explicit coupling between a view and a domain object it seems to create an implicit coupling between them since the view needs to know what names the domain object has given to each of the things it puts into the container.
I like this approach although I’m not sure how well it would work if we had a lot of data to display.
DTOs/View Model
We can also make use of DTOs which are weak objects with getters/setters where we can put data that we want to display on the view.
An alternative we’re using on my project which seems like a variation of this is to return a JSON object which generally only contains the fields that we are interested in seeing from a user perspective. We do have some places where we are making use of a JSON serializer to return an exact version of an object as JSON.
The problem when using DTOs is that we can end up writing a lot of translation code which is quite boring and which from my experience people are reluctant to test.
I guess tools like AutoMapper and JSON.NET can help to remove this problem although a recent conversation with my colleague Lu Ning leads me to believe that we need to consider the value that we will get from using a DTO compared to just making use of a domain object directly from the view.
This is particularly true if there is not much difference between the domain model and the model of the domain that the user interacts with and if that is the case that it might make more sense to just expose the domain model directly.
Greg Young has taken this to the extreme with his idea of Command Query Separation at the architecture level whereby we would have a write only domain model on one side and then just fill DTOs effectively representing the user’s view of the data on the other side.
In summary
I’m not sure which is my favourite approach of the ones that I’ve come across - none of them seems quite right to me.
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.