September 2013

Volume 28 Number 9

Data Points - Coding for Domain-Driven Design: Tips for Data-Focused Devs, Part 2

By Julie Lerman

Read the entire Domain-Driven Design series:
Coding for Domain-Driven Design: Tips for Data-Focused Devs, Part 1
Coding for Domain-Driven Design: Tips for Data-Focused Devs, Part 2
Coding for Domain-Driven Design: Tips for Data-Focused Devs, Part 3

Julie LermanThis month’s column will continue celebrating the 10th anniversary of Eric Evans’ book, “Domain-Driven Design: Tackling Complexity in the Heart of Software” (Addison-Wesley Professional, 2003). I’ll share more tips for data-first developers who are interested in benefiting from some of the coding patterns of Domain-Driven Design (DDD). Last month’s column highlighted:

  • Setting persistence concerns aside when modeling the domain
  • Exposing methods to drive your entities and aggregates, but not your property setters
  • Recognizing that some subsystems are perfect for simple create, read, update and delete (CRUD) interaction and don’t require domain modeling
  • The benefit of not attempting to share data or types across bounded contexts

In this column you’ll learn what’s meant by the terms “anemic” and “rich” domain models, as well as the concept of value objects. Value objects seem to be a topic that falls into one of two camps for developers. It’s either so obvious that some readers can’t imagine why it warrants any discussion at all, or so baffling that others have never been able to wrap their heads around it. I’ll also encourage you to consider using value objects in place of related objects in certain scenarios.

That Condescending Term: Anemic Domain Models

There’s a pair of terms you’ll often hear with respect to how classes are defined in DDD—anemic domain model and rich domain model. In DDD, domain model refers to a class. A rich domain model is one that aligns with the DDD approach—a class (or type) that’s defined with behaviors, not just with getters and setters. In contrast, an anemic domain model consists simply of getters and setters (and maybe a few simple methods), which is fine for many scenarios, but gains no benefit from DDD.

When I started using Entity Framework (EF) Code First, the classes I intended Code First to work with were probably 99 percent anemic. Figure 1 is a perfect example, showing a Customer type and the Person type from which it inherits. I’d often include a handful of methods, but the basic type was merely a schema with getters and setters.

Figure 1 Typical Anemic Domain Model Classes Look Like Database Tables

public class Customer : Person
{
  public Customer()
  {
    Orders = new List<Order>();
  }
  public ICollection<Order> Orders { get; set; }
  public string SalesPersonId { get; set; }
  public ShippingAddress ShippingAddress { get; set; }
}
public abstract class Person
{
  public int Id { get; set; }
  public string Title { get; set; }
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string CompanyName { get; set; }
  public string EmailAddress { get; set; }
  public string Phone { get; set; }
}

I finally looked at these classes and realized I was doing little more than defining a database table in my class. It’s not necessarily a bad thing, depending on what you plan to do with the type.

Compare that to the richer Customer type listed in Figure 2, which is similar to the Customer type I explored in my previous column (msdn.microsoft.com/magazine/dn342868). It exposes methods that control access to properties and other types that are part of the aggregate. I’ve tweaked the Customer type since you saw it in the earlier column to better express some of the topics I’m discussing this month.

Figure 2 A Customer Type That’s a Rich Domain Model, Not Simply Properties

public class Customer : Contact
{
  public Customer(string firstName, string lastName, string email)
  {
    FullName = new FullName(firstName, lastName);
    EmailAddress = email;
    Status = CustomerStatus.Silver;
  }
  internal Customer()
  {
  }
  public void UseBillingAddressForShippingAddress()
  {
    ShippingAddress = new Address(
      BillingAddress.Street1, BillingAddress.Street2,
      BillingAddress.City, BillingAddress.Region,
      BillingAddress.Country, BillingAddress.PostalCode);
  }
  public void CreateNewShippingAddress(string street1, string street2,
   string city, string region, string country, string postalCode)
  {
    BillingAddress = new Address(
      street1,street2,
      city,region,
      country,postalCode)
  }
  public void CreateBillingInformation(string street1,string street2,
   string city,string region,string country, string postalCode,
   string creditcardNumber, string bankName)
  {
    BillingAddress = new Address      (street1,street2, city,region,country,postalCode );
    CreditCard = new CustomerCreditCard (bankName, creditcardNumber );
  }
  public void SetCustomerContactDetails
   (string email, string phone, string companyName)
  {
    EmailAddress = email;
    Phone = phone;
    CompanyName = companyName;
  }
  public string SalesPersonId { get; private set; }
  public CustomerStatus Status { get; private set; }
  public Address ShippingAddress { get; private set; }
  public Address BillingAddress { get; private set; }
  public CustomerCreditCard CreditCard { get; private set; }
}

In this richer model, rather than simply exposing properties to be read and written to, the public surface of Customer is made up of explicit methods. Review the Private Setters and Public Methods section of last month’s column for more details. My point here is to help you better comprehend the difference between what DDD refers to as an anemic versus a rich domain model.

Value Objects Can Be Confusing

Though they seem simple, DDD value objects are a serious point of confusion for many, including me. I’ve read and heard so many different ways of describing value objects from a variety of perspectives. Luckily, each of the different explanations, rather than conflicting with one another, helped me build a deeper understanding of value objects.

At its core, a value object is a class that doesn’t have an identity key.

Entity Framework has a concept of “complex types” that comes fairly close. Complex types don’t have an identity key—they’re a way of encapsulating a set of properties. EF understands how to handle these objects when it comes to data persistence. In the database, they get stored as fields of the table to which the entity is mapped.

For example, instead of having a FirstName property and a LastName property in your Person class, you could have a FullName property:

public FullName FullName { get; set; }

FullName can be a class that encapsulates the FirstName and LastName properties, with a constructor that forces you to provide both of those properties.

But a value object is more than a complex type. In DDD, there are three defining characteristics of a value object:

  1. It has no identity key (this aligns with a complex type)
  2. It’s immutable
  3. When checking its equality to other instances of the same type, all of its values are compared

Immutability is interesting. Without an identity key, a type’s immutability defines its identity. You can always identify an instance by the combination of its properties. Because it’s immutable, none of the type’s properties can change, so it’s safe to use the type’s values to identify a particular instance. (You’ve already seen how DDD entities protect themselves from random modifications by making their setters private, but you could have a method that allows you to affect those properties.) Not only does a value object hide the setters, but it prevents you from modifying any of the properties. If you modified a property, that would mean the value of the object has changed. Because the entire object represents its value, you don’t interact with its properties individually. If you need the object to have different values, you create a new instance of the object to hold a new set of values. In the end, there’s no such thing as changing a property of a value object—which effectively makes even formulating a sentence that includes the phrase “if you need to change a value of a property” an oxymoron. A useful parallel is to consider a string, which is another immutable type (at least in all languages with which I’m familiar). When working with a string instance, you don’t replace individual characters of the string. You simply create a new string.

My FullName value object is shown in Figure 3. It has no identity key property. You can see that the only way to instantiate it is by providing both property values, and there’s no way to modify either of those properties. So it fulfills the immutability requirement. The final requirement, that it provides a way to compare equality to another instance of that type, is hidden in the custom ValueObject class (that I’ve borrowed from Jimmy Bogard at bit.ly/13SWd9h) from which it inherits, because that’s a bunch of convoluted code. Although this ValueObject doesn’t account for collection properties, it meets my needs because I don’t have any collections within this value object.

Figure 3 The FullName Value Object

public class FullName:ValueObject<FullName>
{
  public FullName(string firstName, string lastName)
  {
    FirstName = firstName;
    LastName = lastName;
  }
  public FullName(FullName fullName)
    : this(fullName.FirstName, fullName.LastName)
  {    }
  internal FullName() { }
  public string FirstName { get; private set; }
  public string LastName { get; private set; }
 // More methods, properties for display formatting
}

Keeping in mind that you may want a modified copy—for example, similar to this FullName but with a different FirstName—Vaughn Vernon, author of “Implementing Domain-Driven Design” (Addison-Wesley Professional, 2013), suggests FullName could include methods to create new instances from the existing instance:

public FullName WithChangedFirstName(string firstName)
{
  return new FullName(firstName, this.LastName);
}
public FullName WithChangedLastName(string lastName)
{
  return new FullName(this.FirstName, lastName);
}

When I add in my persistence layer (Entity Framework), it will see this as an EF ComplexType property of any class in which it’s used. When I use FullName as a property of my Person type, EF will store the properties of FullName in the database table where the Person type is stored. By default, the properties will be named FullName_FirstName and FullName_LastName in the database.

FullName is pretty straightforward. Even if you were doing database-focused design, you might not want to store FirstName and LastName in a separate table.

But now consider another scenario—imagine a Customer with a ShippingAddress and a BillingAddress:

public Address ShippingAddress { get; private set; }
public Address BillingAddress { get; private set; }

By (data-driven brain) default, I create Address as an Entity, including an AddressId property. And, again, because I “think in data,” I presume that Address will be stored as a separate table in the database. OK, I’m working hard to train myself to stop considering the database while modeling my domain, so that’s of no consequence. However, at some point I’ll add in my data layer using EF and EF will also make this assumption. But EF won’t be able to work out the mappings correctly. It will presume a 0..1:* relationship between Address and Customer; in other words, that an address might have any number of related customers and a Customer will have either no addresses or one address.

My DBA might not like this result and, what’s more important, I won’t be writing my application code based on the same assumption that Entity Framework is making—that there are many Customers to zero or one Address. Because of this, EF might affect my data persistence or retrieval in some unexpected ways. So from the perspective of someone who’s been working with EF quite a lot, my first approach is to fix the EF mappings using the Fluent API. But asking EF to fix this problem would force me to add navigation properties from Address pointing back to Customer, which I don’t want in my model. As you can see, solving this problem with EF mappings would lead me down a rabbit hole.

When I step back and focus on the domain, not on EF or the database, it makes more sense to simply make Address a value object instead of an entity. Three steps are required:

  1. I need to remove the key property from the Address type (possibly called Id or AddressId).
  2. I need to be sure that Address is immutable. Its constructor already lets me populate all of the fields. I have to remove any methods that would allow any properties to change.
  3. I need to ensure that Address can be checked for equality based on the values of its properties and fields. I can do that by inheriting again from that nice ValueObject class I borrowed from Jimmy Bogard (see Figure 4).

Figure 4 Address as a Value Object

public class Address:ValueObject<Address>
{
  public Address(string street1, string street2, 
    string city, string region,
    string country, string postalCode) {
    Street1 = street1;
    Street2 = street2;
    City = city;
    Region = region;
    Country = country;
    PostalCode = postalCode;  }
  internal Address()  {  }
  public string Street1 { get; private set; }
  public string Street2 { get; private set; }
  public string City { get; private set; }
  public string Region { get; private set; }
  public string Country { get; private set; }
  public string PostalCode { get; private set; }
  // ... 
}

How I use this Address class from my Customer class won’t change, except that if I need to modify the address, I’ll have to create a new instance.

But now I no longer need to worry about managing that relationship. And it also provides another litmus test for value objects, in that a Customer really is defined by its shipping and billing information because if I sell anything to that customer, I’ll most likely need to ship it and the Accounts Payable department requires that I have its billing address.

This is not to say that every 1:1 or 1:0..1 relationship can be replaced with value objects, but it’s a nice solution here and my job became a lot simpler when I stopped having to solve one puzzle after another that popped up as I tried to force Entity Framework to maintain this relationship for me.

Like the FullName example, changing Address to be a value object means Entity Framework will see Address as a ComplexType and will store all of that data within the Customer tables. Years of being focused on database normalization made me automatically think this was a bad thing, but my database can handle it easily and it works for my particular domain.

I can think of many arguments against using this technique, but they all begin with “what if.” Any of those that don’t pertain to my domain aren’t valid arguments. We waste a lot of time coding for just-in-case scenarios that never come to pass. I’m trying to be more considerate about adding those preemptive Band-Aids into my solutions.

Not Done Quite Yet

I’m really getting through the list of DDD concepts that have haunted this data geek. As I grok more of these concepts, I become inspired to learn even more. Once I shift my thinking a bit, these patterns make a lot of sense for me. They don’t reduce my interest in data persistence one bit, but separating the domain from the data persistence and infra­structure feels right to me after having them tangled up together for so many years. Still, it’s important to keep in mind that there are so many software activities that don’t need DDD. DDD can help sort out complex problems, but quite often it’s overkill for simple ones.

In the next column I’ll discuss a few other DDD technical strategies that also initially seemed to conflict with my data-first thinking, such as letting go of bidirectional relationships, considering invariants and dealing with any perceived need to trigger data access from your aggregates.


Julie Lerman is a Microsoft MVP, .NET mentor and consultant who lives in the hills of Vermont. You can find her presenting on data access and other Microsoft .NET topics at user groups and conferences around the world. She blogs at thedatafarm.com/blog and is the author of “Programming Entity Framework” (2010) as well as a Code First edition (2011) and a DbContext edition (2012), all from O’Reilly Media. Follow her on Twitter at twitter.com/julielerman and see her Pluralsight courses at juliel.me/PS-Videos.

Thanks to the following technical expert for reviewing this article: Stephen Bohlen (Microsoft)
Stephen A. Bohlen is currently a Senior Technology Evangelist for Microsoft Corporation, and brings his varied 20-plus-years of experience as a former practicing architect, CAD manager, IT technologist, software engineer, CTO, and consultant to assist select Microsoft partner organizations in their adoption of cutting-edge and pre-release Microsoft developer products and technologies.