Archive

Archive for August, 2009

Ubiquitous language: what is so blindingly obvious you can’t see it?

August 7th, 2009 JDT 1 comment

Ubiquitous Language is the term Eric Evans uses in Domain Driven Design for the practice of building up a common, rigorous language between developers and users. This language should be based on the Domain Model used in the software – hence the need for it to be rigorous, since software doesn’t cope well with ambiguity.
Martin Fowler

Abstract

In which the author outlines the basics of the ‘Ledger Pattern’, an addition to the ubiquitous language and domain model to help facilitate a more natural approach to DDD and OO. It is specifically designed to deal with issues of validation and object creation that occur during object instantiation.

Concrete

Some things are obvious.  Some things are very obvious. And some things are so obvious that you actually need to take a step back in order to see them.  Udi Dahan helped me take that step back some time ago with his article ‘Don’t create aggregate roots‘.  While I agree with him on most of what he details in his post, I feel that something is missing.

What Udi points out is that we should never create instances of domain objects from the service layer (or command handler layer, whatever the layer is that coördinates calls to domain objects). Instead, it is the responsibility of an aggregate root to create a new entity that belongs to his aggregate.  In some cases, this is obvious:

public class Order {   public void AddOrderLine(OrderLine line)   {     orderLines.Add(line);   }   public void AddOrderLine(Product product, int quantity)   {     orderLines.Add(new OrderLine(product, quantity));   } }

The latter method is actually the better: it is very easy to perform validation on the parameters passed before the orderline object is constructed.  This is closely linked to something I blogged on before: domain object validation is done on a context basis.

And even if you believe that validation can be done, consider the example where we create a customer

public void Handle(CreateCustomerCommand cmd) {   ICustomerRepository repo = RepositoryFactory.Get();   Customer customer = new Customer(cmd.FirstName, cmd.LastName);   repo.Save(customer); }

Where is the validation code now? Is it in the constructor? If so, what if we need different validation logic? What if our application goes from being an application used in a store to a web application? Now a customer comes through your website and you need to ensure that an email-address is supplied. We have to face facts: this solution is not adequate.

What we need is a domain concept that fits with the ‘this object can add customers’. So we use our common sense: in the store, the Employee-object can add a user. But who adds employees? Well, that would be the store owner. But where does he come from?

Back up a minute. In the past few sentences I’ve introduced a whole slew of new terms into the ubiquitous language. All of these need to be modeled, coded, tested and used. And what have we really achieved? Nothing much. No matter how far up the chain you push things, at some point you will run into a simple truth: you need an object that is not created and stored in the normal run of the system but that has been present from the start. Therefore I propose the following guideline:

For every aggregate root that is not the entity of any other aggregate root that can act as its creator, define an artificial aggregate root.

I call this artificial root a ledger, because it performs a function similar to an  order or purchase ledger.  Our customers are prime candidates for this: unless the ubiquitous language explicitly calls for some other object to create customers our CustomerLedger takes care of creating and deleting customers.  Note that all these ledgers to is provide a place to create and delete instances, updates are still processed by the actual domain objects.

Ledgers are also a prime place for validation: if a customer must have a first and last name, the ledger validates this. If our customers are now registering through the website the ledger can be extended to handle the adding of customers with the associated required validation of email addresses.

The odd thing about legders is that they are aggregate roots (and therefore entities) that have no identity*. All instances of a ledger class are equal to each other (disregarding lazy-loading and the likes) because they always contain the same data.

Here is a code example detailing what a ledger looks like.  This uses my implementation of the Notification Pattern to let the repository check if the object is in a valid state and to allow it to report this to the presentation layer.

public class CustomerLedger {   private IList errorList;   public CustomerLedger()   {     errorList = new List();   }   public IList Customers { get; set; }   public ICommandResult AddCustomer(String firstName, String lastName)   {     Validate.IsNotNullOrEmpty(firstName, "First name null or empty", errorList);     Validate.IsNotNullOrEmpty(lastName, "Last name null or empty", errorList);     if(errorList.Count == 0)       Customers.Add(new Customer(firstName, lastName);     return new CommandResult(errorList);   } }

This code is seemingly not very different from regular aggregate root code, and rightly so!  The only actual difference is the way the object is treated from the repository.

public interface ICustomerLedgerRepository {   CustomerLedger Get();   ICommandResult Save(CustomerLedger ledger); }

No id’s, no fancy lookups: there is no difference between the instances*.

Conclusion

The ledger concept is quite confusing at first, and it is a certain risk to implement: it can be confusing to users, domain experts and programmers alike. To introduce the concept into the ubiquitous language is to soil this language with something that is inherently a technical concern, but at the same time a valid domain problem. Everything that enters your system has an origin, and you need to model this origin up to a certain point.If you talk in terms of roles rather than objects it is a lot easier to introduce: the concept of a ‘CustomerAdder’ makes sense: your system needs something that adds customers.

Technically, this can not be considered a design pattern. But I’m going to call it the ‘Ledger Pattern‘ anyway. It’s either that or calling it ‘the concept formerly known as the artifical aggregate root for aggregate roots that lack natural aggregate roots in the ubiquitous language’. Let’s see you type that ten times in a heated mailing list discussion.

* All my ledgers actually do have an identity to facilitate ORM mapping and retrieval. This means that every aggregate root that is managed by a ledger also has a foreign key that points to this ledger. My database contains a ledger-table which contains an id and the name of the legder.

Categories: Various Tags:

Bring on the default constructors

August 7th, 2009 JDT No comments

The term “default constructor” refers to a constructor that is automatically generated in the absence of explicit constructors (and perhaps under other circumstances); this automatically provide constructor is usually a nullary constructor. In specification or discussion of some languages, “default constructor” may additionally refer to any constructor that may be called without arguments, either because it is a nullary constructor or because all of its parameters have default values.
Wikipedia

Abstract

In which the author outlines why default constructors on domain objects are not a ‘code smell’ for NHibernate and are actually required in most situations.

Concrete

I remember when I first started working with (N)Hibernate. It seemed like  a great tool: no more writing SQL queries, no more writing mapping code, but there was that expletive requirement to have a default no-arguments constructor. So I made that private as to not allow the constructor to be abused, but it still seemed bad: the domain object needs to conform to what an infrastructure framework wants.  It is only now, years after my first encounter with NHibernate, that I see that having a default constructor is not a bad thing. If anything, default constructors on domain objects are good things.

Let’s look at the reason why we need constructors. The raison d’être for a constructor is to force code that news up an instance of a class to provide other objects that said class needs.  In the context of domain layer and domain objects we tend to think of this as ‘creating the object in a state that is valid’. But what is a valid state?  When talking with programmers, analysts or domain experts it’s very easy to define what is a valid state.  In a classical order system with customers valid state will probably include a customer having a first name, last name and valid address details.  But is this really such a big requirement that we have to validate this in the constructor?

Weather or not a domain object is valid is in some cases not up to the object itself, and this is especially true for new instances.  Fact of the matter is that the only thing that determines if a domain object is valid is context.  Why does a customer need a first name, last name and an address? Because we need to be able to ship orders to him.

Read that again. We need to ship orders to him. If we are not shipping orders we do not need to validate anything. This brings the concept of validation into a totally different area. We no longer need to think about validating domain objects after creation, we are now validating pre-conditions for object creation.  This validation is always external to the object being created, allowing you to use the same domain object for different use-cases, without the need to write, test and maintain a gazillion different constructors, or even worse – deal with constructors that have the same parameters but different validation requirements. (The question of where the actual validation occurs for certain domain objects – such as aggregate roots – is a matter I’l talk about in a different post.)

Conclusion

And that, ladies and gentlemen, is why I like default constructors. Because I really don’t care if my domain objects are valid or not. All I care about is that they are valid in the context I’m using them in. And validating that can be done with re-useable code, tried and tested through unittests and talks with domain experts. Full of DDD and OO goodness, just the way I like it.

Categories: Various Tags: