Home > DDD, Programming > Value Objects

Value Objects

Value Objects

A value object is essentially data without a sense of identity.  This simplifies them as objects within a system because they are immutable (once created they should never change), validated (since they never change should always be in a valid state), and equal (since they have no identity, two value objects with the same data are equivalent).

The best way to see this is via example.  A good example of this is money.  If you have a value object representing a sum of money then two instances of that object worth $20.00USD are equivalent regardless of the makeup of that money.  A store doesn’t care if you provide a single twenty dollar bill, two tens, four fives, or twenty ones.  They only are about receiving twenty dollars.  Thus once that value is added to their system its identity (the specific bills you handed to the cashier) is irrelevant.  A perfect example of a value object.

Immutability

If an object has no sense of identity beyond the value of its members then to change its members is to change its identities.  If you live at a particular address, the summation of street address, city, state, and zip code create the identity of that address.  The moment you change a property of your address (say zip code) the address is no longer your address.  Its identity is altered.  Thus value objects should not expose means to edit their properties.

public class Address
{
     public string StreetAddress { get; private set; }
     public string City { get; private set; }
     public string State { get; private set; }
     public string Zip { get; private set; }
 
     public Address(string streetAddress, string city, string state, string zip)
     {
          StreetAddress = streetAddress;
          City = city;
          State = state;
          Zip = zip;
     }
}

Notice that the only way to give the object value is via its constructor.  This insures that its data (and thus its identity) is never changed.  It makes the object immutable.

Validity

If an object cannot be changed then it better always be valid.  For this reason it makes sense to check that all values provided to the constructor are valid.  Thus insuring the object is always in a valid state.

public class Address
{
     public string StreetAddress { get; private set; }
     public string City { get; private set; }
     public string State { get; private set; }
     public string Zip { get; private set; }
 
     public Address(string streetAddress, string city, string state, string zip)
     {
          if (string.IsNullOrEmpty(streetAddress))
               throw new ArgumentException("Address requires street address");
          if (string.IsNullOrEmpty(city))
               throw new ArgumentException("Address requires city");
          if (string.IsNullOrEmpty(state))
               throw new ArgumentException("Address requires state");
          if (string.IsNullOrEmpty(zip))
               throw new ArgumentException("Address requires zip");
 
          StreetAddress = streetAddress;
          City = city;
          State = state;
          Zip = zip;
     }
}

Equality

Since value objects are the same if their properties are the same it makes testing their equality simple.  It becomes a simple matter of testing their properties.  For readability and convenience I tend to overload operators and the Equals method.

public class Address : IEquatable<Address>
{
     public string StreetAddress { get; private set; }
     public string City { get; private set; }
     public string State { get; private set; }
     public string Zip { get; private set; }
 
     public Address(string streetAddress, string city, string state, string zip)
     {
          if (string.IsNullOrEmpty(streetAddress))
               throw new ArgumentException("Address requires street address");
          if (string.IsNullOrEmpty(city))
               throw new ArgumentException("Address requires city");
          if (string.IsNullOrEmpty(state))
               throw new ArgumentException("Address requires state");
          if (string.IsNullOrEmpty(zip))
               throw new ArgumentException("Address requires zip");
 
          StreetAddress = streetAddress;
          City = city;
          State = state;
          Zip = zip;
     }
 
     public override bool Equals(object obj)
     {
          return Equals(obj as Address);
     }
 
     public bool Equals(Address obj)
     {
          if (obj == null)
               return false;
          return StreetAddress.Equals(obj.StreetAddress) &&
                   City.Equals(obj.City) &&
                   State.Equals(obj.State) &&
                   Zip.Equals(obj.Zip);
     }
 
     public static bool operator ==(Address left, Address right)
     {
          return Equals(left, right);
     }
 
     public static bool operator !=(Address left, Address right)
     {
          return !Equals(left, right);
     }
}

This results in a rather nice value object to work within code. Ensuring that the three important properties of a value object are met within your code.

Categories: DDD, Programming Tags:
  1. No comments yet.
  1. No trackbacks yet.