In my last post, I talked about a Generic Expression Builder class for easily creating domain entities through expression builders. This generic base class takes away some of the burden while developing these expression builder classes. Expression builders are generally useful inside the domain when you need to create and set up a complete aggregate root from scratch, not to say that expression builders aren’t useful in other parts of an application (e.g. creating message objects, DTO’s, etc.).
Another place where a fluent interface can add value is for implementing behavior on a domain entity. Taking the same example from my previous post, where we have a domain class named Document with the name of the author, a title and one or more associated tags. Suppose we have a command that needs to add a new Tag to the existing list of tags for a particular Document. We usually end up with code like this:
public class Document { var IList<Tag> _tags = new List<Tag>(); ... public void AddTag(String name) { var newTag = new Tag(name); _tags.Add(newTag); } }
The usual mistake I see a lot is to let the AddTag method directly take a Tag object. However, in this case the Document class is the aggregate root where Tag is merely a value object that lives within the boundaries of its aggregate root. This means that the aggregate root is responsible for creating instances of a Tag (also check out this post from Udi Dahan).
Lets make this code a bit more fluent. In my previous post, I provided a separate expression builder for creating new Tag objects. This TagBuilder is already used by the expression builder that creates Document objects.
public interface ITagBuilder { void Named(String name); } public class TagBuilder : ITagBuilder { private readonly Action<Tag> _afterBuildAction; public TagBuilder(Action<Tag> afterBuildAction) { _afterBuildAction = afterBuildAction; } public void Named(String name) { var tag = new Tag(name); _afterBuildAction(tag); } }
Now lets reuse this builder class for our domain method that adds a new Tag for a Document. This is how the AddTag method is implemented:
public ITagBuilder AddTag() { return new TagBuilder(newTag => _tags.Add(newTag)); }
And this is how the calling code looks:
document.AddTag().Named("Science"));
I have to admit that it does involve some overkill for this simple example. However, the code becomes a lot more clear when you have to provide a couple of more arguments to a domain method. Again, not everything is a nail for this shiny hammer. But it does bring some nice, readable code when needed. Here’s another example that attaches the data of a file to a Document:
document.Attach() .FileWithName("The Universe in a Nutshell.pdf") .AndData(new Byte[] { ... });
The fact that we can just reuse an existing expression builder is also a clear advantage.
Till next time
@Jan
I implemented a similar pattern on my blog a while back and got heat from some who thought I was violating SRP by allowing my agg root to return such a factory/builder…everyone wanted me to inject it. My opinion though is that the very notion of an Aggregate Root ‘violates’ SRP by placing both the behavior of an entity _and_ the role it plays as the root…and I’m ok with that. Any thots?
@Mike: I personally don’t consider this as a violation of SRP. In my post, I linked to a post from Udi where he advises to “always get an entity”. It is the duty of an aggregate root to enforce its boundaries. I therefore consider the expression builder being a part of the domain. In my example, the value object is not created by the aggregate root, but by the expression builder itself. The aggregate only adds to its collection.
After reading your article, I must say that the resemblance of the phases we’ve been through freaks me out :-). If you want your domain entity to return a different builder (your example talks abot different signatures), then one might put this in a seperate ‘BuilderFactory’. NH 2.1 now supports IoC, so such a factory can be injected into a domain object when retrieved from NH.
One of the major advantages in using expression builders this way is loosening up dependencies on the domain. My 2 (Euro)cents.
@Jan
Thanks for the reply. Sorry to freak you out though… 😉 I pressed forward with this approach frequently into my current project and found it very simple to extend. Something itches me about injecting such builders into my entities at construction but it’s great to have this functionality should the need arise.
Keep up the good articles !
Mike
Seems like named parameters would make questionable that which is proposed here as a clear advantage of method chaining.
This looks good but I cannot see explicitly from this post or the former, but do you not expose the Tags collection via a public getter property called Tags on the Document class? The previous post showed code such as
var tagBuilder = new TagBuilder(tag =>
ProvideValueFor(document => document.Tags, tag));
which I interpret as having such a property. Whilst the backing field is retrieved for the collection (even if that is, and usually would be, private) to perform the actual Add call to the collection, if you expose the Tags collection and it is not a ReadOnlyCollection, then the consumer can simple add a Tag object without going through the Fluent building path or through the call to AddTag. Am I right in this analysis?
@Dokie: The Tags collection is exposed as an IEnumerable.