Wednesday, October 27, 2010

The Law of Demeter

Upon reading the excellent Head First Design Patterns the first time, I didn't quite understand the Law of Demeter. Their example with Thermometers and Weatherstation seemed contrived. It seemed like unnecessary indirection (though Computer Scientists do say the key to solving most computer science problems is to add another layer of indirection). But today, I found myself working on a problem where it kind of makes sense.

I have this method in my Service Layer

public bool SaveCycle(Cycle request)
{
bool returny;
Cycle cycleToUpdate = cycleRepository.Get(request.Id) ?? request;
PopulateCycleFromForm(cycleToUpdate, request);
if (cycleToUpdate.IsValid())
{
cycleRepository.SaveOrUpdate(cycleToUpdate);
returny = true;
if (cycleToUpdate.CyclePartitions.Count == 0) // new cycles have no partitions associated. create default
{
CreateDefaultCyclePartitions(cycleToUpdate);
}
}
else
{
returny = false;
}
return returny;
}

and Cycle is a Domain Object in my object model. What made the Law of Demeter ring a bell was thinking about:

if (cycleToUpdate.CyclePartitions.Count == 0) // new cycles have no partitions associated. create default
{
CreateDefaultCyclePartitions(cycleToUpdate);
}

I am storing CyclePartitions as a list of objects inside of Cycle in my domain layer. I need to create some default partitions on new cycle creation, so it seems reasonable to check the count of the collection.

But what if, 6 months down the line, I change the type of the CyclePartitions collection I'm using in my Cycle Domain Object to some other collection type? Maybe it exposes a Size property instead of a Count property. Then, I would have to go back and change the Service Layer as well, since I've subtly introduced a dependency here.

But, if I write this in my Service Layer:

if (cycleToUpdate.GetNumberOfCyclePartitions() == 0) // new cycles have no partitions associated. create default
{
CreateDefaultCyclePartitions(cycleToUpdate);
}

Then I am free to do whatever I want inside of my Cycle Domain Object, as the Service Layer only cares about the API.

No comments:

Post a Comment