Logo

NHibernate

The object-relational mapper for .NET

Value objects

Introduction

Eric Evans writes in his DDD book:

When you care only about the attributes of an element of the model, classify it as a value object. Make it express the meaning of the attributes it conveys and give it related functionality. Treat the value object as immutable. Don't give it any identity and avoid the design complexities necessary to maintain entities.

Many objects have no conceptual identity. These objects describe some characteristic of a thing.

A value object is an object that describes some characteristics or attribute but carries no concept of identity .

Samples

There are many samples where the introduction of a value object is useful. One of the most used value objects in DDD is certainly the Money value object. There is even a pattern called after this value object (the money pattern).

A large proportion of the computers in this world manipulate money. But money isn't a first class data type on the .Net framework. The lack of a type causes problems, the most obvious surrounding currencies. If all your calculations are done in a single currency, this isn't a huge problem, but once you involve multiple currencies you want to avoid adding an amount expressed in dollars to an amount expressed in Euro without taking the currency differences into account. Also rounding is a problem. Monetary calculations are often rounded to the smallest currency unit (pennies for dollar and cent for Euro).

Another typical example of a value object is an Address. The address is even a very interesting beast, since it contains a reference to Country which in turn often is treated like an entity.

 address

Yet another example is a geographical coordinate. It consists of the two values longitude and latitude.

 GeoCoordinate

Often we see people introduce a value object for the names of a person. Such a name value object could e.g. consist of the three members first name, middle name and last name where the first and the last are mandatory and the middle name is optional.

 name

Finally another well known value object is Color. Color is a structure which normally consist of four values (red, green, blue and alpha)

color

Note that the alpha channel is an indicator for the transparency of a colored shape. It goes from completely transparent (0) to opaque (255).

Immutability

As told earlier a value object should always be immutable. The consequence of this is that once its properties are set they cannot be changed. The best way to guarantee this is that all properties are read-only (they have private or no setter methods). A new instance of a value object is completely defined through its constructor. Let's take as a sample the Name value object.

public class Name
{
    public string FirstName { get; private set; }
    public string MiddleName { get; private set; }
    public string LastName { get; private set; }
 
    public Name(string firstName, string middleName, string lastName)
    {
        FirstName = firstName;
        MiddleName = middleName;
        LastName = lastName;
    }
}

Validation

Since a value object is immutable it makes sense that each value object must always be in a valid state. The validation happens in the constructor of the value object. Again let's look at the Name value object as an example. Below I present the constructor of the value object. This time with the validation logic.

public Name(string firstName, string middleName, string lastName)
{
    // Validation logic
    if(string.IsNullOrEmpty(firstName)) 
        throw new ArgumentException("First name cannot be undefined.");
    if(string.IsNullOrEmpty(lastName)) 
        throw new ArgumentException("Last name cannot be undefined.");
 
    if(firstName.Length>50)
        throw new ArgumentException("Length of first name cannot exceed 50 characters.");
    if(middleName.Length>30)
        throw new ArgumentException("Length of middle name cannot exceed 30 characters.");
    if(lastName.Length>50)
        throw new ArgumentException("Length of last name cannot exceed 50 characters.");
 
    FirstName = firstName;
    MiddleName = middleName;
    LastName = lastName;
}

The validation logic checks that the first and last name are given and that any of the names does not exceed the maximal tolerated length. If the validation tests have all passed then we are sure that our value object is now in a valid state. From now on we will never again have to make validation check against our Name instance. You should not underestimate the positive consequences of this!

Equality

It is very important that two instances of a value object are comparable, that is whether they contain the same values in their constituent properties. To achieve this we have to at least override the two sister methods Equals and GetHashCode which are inherited from the base class System.Object.

But we should also implement the generic interface IEquatable<T> in our value object to provide a type safe method for comparing two instances.

public class Name : IEquatable<Name>
{
    // omitted code for brevity...
 
    public override int GetHashCode()
    {
        return string.Format("{0}|{1}|{2}", FirstName, MiddleName, LastName).GetHashCode();
    }
 
    public override bool Equals(object obj)
    {
        return Equals(obj as Name);
    }
 
    public bool Equals(Name other)
    {
        if(other==null) return false;
        return FirstName.Equals(other.FirstName) &&
               ((MiddleName == null && other.MiddleName == null) ||
                (MiddleName != null && MiddleName.Equals(other.MiddleName))) &&
                LastName.Equals(other.LastName);
    }
}

Note that my implementation of GetHashCode is certainly not the unique or best implementation. But it is easy and works for me.

In the Equals method I compare the two instances of the value object property by property. Since the middle name is optional it can be null and thus needs a special treatment.

For convenience we can also override the operators == and != as follows

public static bool operator ==(Name left, Name right)
{
    return Equals(left, right);
}
 
public static bool operator !=(Name left, Name right)
{
    return !Equals(left, right);
}

this allows me to use such constructs as

if(name1 == name2) {...}    or

if(name1 != name2) {...}.

Builders

Creating an instance of a value object can be error prone when using the constructor. The code is not very readable. How should I know whether the following code fragment is correct?

address = new Address("Paradise Street 12", "P.O.Box 233", "Neverland", "82344", unitedStates);

Could it possibly be that the postal code and the city are confused? How should I know. Just by reading I have no idea since the code is not self describing. So, is this the correct version?

address = new Address("Paradise Street 12", "P.O.Box 233", "82344", "Neverland", unitedStates);

Note that both versions compile, but only the first one is correct. To eliminate this weakness people often implement object builders for complex value objects like an address. Often a builder implements some kind of fluent interface to make the code very self explaining and compact (free of syntactic noise!).

address = new AddressBuilder()
    .AddressLine1("Paradise Steet 12")
    .AddressLine2("P.O.Box 233")
    .PostalCode("82344")
    .City("Neverland")
    .Country(unitedStates);

The above code snippet is very self expressing, isn't it?

How is such a builder implemented? Let's have a look at a possible solution

public class AddressBuilder
{
    internal string addressLine1;
    internal string addressLine2;
    internal string city;
    internal string postalCode;
    internal Country country;
 
    [DebuggerStepThrough]
    public AddressBuilder AddressLine1(string line)
    {
        addressLine1 = line;
        return this;
    }
 
    [DebuggerStepThrough]
    public AddressBuilder AddressLine2(string line)
    {
        addressLine2 = line;
        return this;
    }
 
    [DebuggerStepThrough]
    public AddressBuilder PostalCode(string code)
    {
        postalCode = code;
        return this;
    }
 
    [DebuggerStepThrough]
    public AddressBuilder City(string city)
    {
        this.city = city;
        return this;
    }
 
    [DebuggerStepThrough]
    public AddressBuilder Country(Country country)
    {
        this.country = country;
        return this;
    }
 
    public static implicit operator Address(AddressBuilder builder)
    {
        return new Address(builder.addressLine1, builder.addressLine2, builder.city, builder.postalCode, builder.country);
    }
}

Especially have a look at the implementation of the implicit operator!

Note that the DebuggerStepThrough attribute is used to avoid debugging through the builder code since the code can be assumed to be error free (it is trivial).

Object Mother

When following TDD (that is: write the test first and only then implement the code to satisfy the test...) we often need some sample data. In the case of a value object we can directly create such an instance in the test method. But this is not DRY since we will have a lot of code duplication. One possible solution is the introduction of a so called object mother. This is a class with static methods which delivers us prefabricated (valid) value objects.

An Object Mother is another name for a factory for test objects. It can be implemented as static class with appropriate methods, e.g.

public static class ObjectMother
{
    private static readonly Country unitedStates = new Country("USA", "United States of America");
    private static readonly Country switzerland = new Country("CH", "Switzerland");
 
    public static Address GetAddress()
    {
        return new AddressBuilder()
            .AddressLine1("Paradise Street 12")
            .AddressLine2("P.O.Box 233")
            .PostalCode("82344")
            .City("Neverland")
            .Country(unitedStates);
    }
 
    public static Address GetSwissAddress()
    {
        return new AddressBuilder()
            .AddressLine1("In der Matte 8")
            .PostalCode("3000")
            .City("Bern")
            .Country(switzerland);
    }
}

In the above sample I use the address builder introduced above to create sample value objects of type address.

Depending on the needs we can have one or several method for any object type we need (or even several overloads of a method if we want to have some configurability of the created objects...).

Enum type value objects

A special variant of a value object is a value object whose base is a enum type. Let me give some samples:

Let's assume we have a task entity. A task object has a state which can have any of the following values

public enum TaskStatusEnum
{
    Undefined = 0,
    Pending,
    InProgress,
    Done
}

But the direct usage of an enum type is unhandy in a domain model. Thus I never use an enum type directly as a value object but rather encapsulate it in a class. A possible implementation for this would be

public class TaskStatus
{
    public TaskStatusEnum Status { get; private set; }
    public string Description { get { return Status.ToString(); } }
 
    public TaskStatus(TaskStatusEnum status)
    {
        Status = status;
    }
}

Instances of the TaskStatus class are value objects. Only the property Status is mapped to the database. The Name property is only for visual representation of a task status (on a view). Of course I would have to implement the IEquality<T> interface in the above class as well as override the Equals and GetHashCode methods. But I have omitted this for brevity.

For convenience I normally implement also a static property get for any of the possible values of the enum in the above class, that is

public static TaskStatus Undefined { get { return new TaskStatus(TaskStatusEnum.Undefined); } }
public static TaskStatus Pending { get { return new TaskStatus(TaskStatusEnum.Pending); } }
public static TaskStatus InProgress { get { return new TaskStatus(TaskStatusEnum.InProgress); } }
public static TaskStatus Done { get { return new TaskStatus(TaskStatusEnum.Done); } }

As you can see it's a little bit more overhead over using an enum directly but it's definitely worth the effort. You gain all the advantages a value object offers you.

Value objects and NHibernate

When we deal with NHibernate a value object is represented by a -->Component. A value object is not stored in a separate table but rather embedded in the table related to the containing entity. That is, if I have an Account entity which contains a property Balance which in turn is a value object (of type Money) then I only have a table Account in the database (but no Money table) and the fields of the Balance value object are part of the Account table.

Mapping

How are value objects mapped in NHibernate? I want to describe three possible ways how we can achieve the desired result. Let's take a (simplified) entity Account as an example

public class Account
{
    public Guid Id { get; set; }
    public string AccountNo { get; set; }
    public Money Balance { get; set; }
 
    // additional properties and logic
    // omitted for brevity...
}

XML mapping files

The most common way to describe the mapping between a domain model and the underlying database is by using XML mapping files.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="Account">
    <id name="Id">
      <generator class="guidcomb"/>
    </id>
    <property name="AccountNo" not-null="true" length="20"/>
    
    <component name="Balance">
      <property name="Value"/>
      <property name="CurrencyCode"/>
    </component>
    
  </class>
</hibernate-mapping>

Note that the Money value object is mapped via the <component> tag in the mapping file.

Castle Active Record

If you are using Castle Active Record for your mapping then you just have to decorate the Balance property of the Account with the attribute [Nested].

[ActiveRecord]
public class Account
{
    [PrimaryKey]
    public Guid Id { get; set; }
    [Property]
    public string AccountNo { get; set; }
    [Nested("Balance")]
    public Money Balance { get; set; }
 
    // additional properties and logic
    // omitted for brevity...
}

You can provide as a parameter to the attribute the column prefix that will be used when mapped to the underlying database table. In the above example the fields in the Account table would be BalanceValue and BalanceCurrencyCode.

Fluent Interface

With the new Fluent NHibernate framework which I descibed here one can define the mapping as follows

public class AccountMap : ClassMap<Account>
{
    public AccountMap()
    {
        Id(x => x.Id);
 
        Map(x => x.AccountNo)
            .CanNotBeNull()
            .WithLengthOf(20);
 
        Component<Money>(
            x => x.Balance, m =>
                                {
                                    m.Map(x => x.Value, "BalanceValue");
                                    m.Map(x => x.CurrencyCode, "BalanceCurrencyCode");
                                });
    }
}

Note that the benefit of the fluent interface is not the brevity of the code but rather the robustness, testability of the mapping as well as the ability to include the mapping in any refactoring.

Summary

I have introduced you to the value object, which is a fundamental piece of DDD. Not only have I presented you the theory behind a value object but also shown you some possible implementation for immutability, validation and mapping of value objects. I also have shown how one can handle value objects which are based on a .Net enum. Further I introduced the concept of builders (for value objects) which help you make the code more readable (and thus maintainable). Last but not least I discussed the usage of the Object Mother pattern in the context of test driven development (TDD).

Enjoy

Blog Signature Gabriel


Posted Wed, 17 September 2008 02:29:56 AM by gabriel.schenker
Filed under: value object

comments powered by Disqus
© NHibernate Community 2024