Paul Gielens:ThoughtsService

another Endpoint to my thoughts

News

Syndication

Ads


Favorites

Projects

Domain Objects should Always be Savable

Frequently discussions on the Domain-Driven Design list contain some real gems. So does a topic started by Bil Simer topic "Loading business entities and bypassing business rules".

We have a business entity that has various rules. For example the length of
the title of a project (yeah yeah, data validation vs. real business rule
but walk with me on this). So for the title to be valid, it can't be null.
However the user says they want to be able to create stuff and come back to
it later so while there's a business rule on the validation, the business
object itself can be pretty empty (as long as we can recall it for the user
to modify later). So it's a bit of a quandary. A rule that says "the title
of the project must not exceed 50 characters and not be empty" but a user
who says "the system must allow me to save something to edit later in any
state".

This is a situation where Domain-Driven Design really shines. A possible solution is to add a constraint to the database by setting the maxlength on the title field for the Product entity, and set the allowsnull property to false. Of course the class wrapping the Product entity has to make sure that the Title property is initialized with an empty string before persisting it. Remember when I said behavior is scattered across the layers in Organizing Domain Logic?

With a model focus we have the solution at hand. This however, does mean we should handle the database with care!

A Domain Object regardless of its state, should be savable

Some objects go through a one-way lifecycle, from an initial state to a final state, but most of the time the object's state is determined through their interactions. Lifecycle states are usually recorded in read-only properties that are changed during conduct business services. So in the case of Bil's example the Project is broken down into stages, since projects are rarely tackled as a single, monolithic job. A project progresses through the lifecycle states of planning, design, construction, commissioning, operation and termination. The planning state can have a derived lifecycle state concept, pre-feasibility etc.

Always is a "big" word because we should try to avoid reaching those states that make us jump through hoops in order to make them persistable. There are a couple of design principles to keep in mind. The first principle is knowing where in the lifecycle by making the lifecycle state a property on the object. The second principle says rules should be located with state which translates to the best practice that rules should be defined as closely as possible to the relevant lifecycle states.

I remember a posting talking about loading a domain object from a
persistence store where it would bypass the rules. I ran into the problem
today because I loaded up my domain object and started to map the values
from the data entity. The entity holding all the values from the database
were pretty empty, but when I wrote the mapping from service entity to
business object, my business logic failed (title cannot be null for
example). So I was stuck without being able to set the values (even if they
were empty) on my business object .

The problem of setting values in an instance that is being recreated by reading its values back from the database is a generic problem. There are several ways to deal with this problem:

Reconstitute a Domain Object from persistence

Through a specific constructor used just for reconstitution. It could look like this:

public Project(DataRow row)

or

public Project(int id, title description, ...)

Another option is through a specific method SetField(int fieldIndex, object value) and finally the least intrusive solution is through the use of reflection against private fields. For a great explanation and the pro's and con's of either solution see Jimmy Nilsson [Nilsson ADDDP].

[Nilsson ADDDP]
Nilsson, Jimmy. Applying Domain-Driven Design and Patterns with Examples in C# and .NET. Addison-Wesley, 2006.

[Nicola et al. SOM]
Nicola, Jill, Mark Mayfield, and Mike Abney. Streamlined Object Modeling: Patterns, Rules, and Implementations. New Jersey: Prentice Hall, 2002.

Posted: Sep 10 2006, 12:26 PM by p.gielens | with 3 comment(s)
Filed under:

Comments

No Comments