In this series, I’m going to write about some of the challenges we’ve been facing with DDD. If you want to adapt DDD on .NET stack, this hopefully will be useful for you. Along with concepts I’ll talk about what works (or doesn’t) well with EntityFramework, but most of it will still be useful with other ORMs - or even without one.

Value Objects

So let’s start with something that might be basic. Value Objects, if you have read the Blue or Red book, is a well defined concept. Martin Fowler puts it really well:

I described Value Object as a small object such as a Money or date range object. Their key property is that they follow value semantics rather than reference semantics.

This is a very simple, yet powerful concept, even if you don’t do DDD, you probably will see the benefit of using this. Let me give you an example. Let’s suppose you have a Customer object that has an email address. You’d want to validate the email address to be in a correct format. A naive way of doing it would be validating the string on the UI (being a web or desktop type of application doesn’t really matter) by your validation framework, and then assuming that the string is in valid form. This approach leads to data corruption and still some other layer bypassing the UI is able to work around the validation. Some other would do that on the entity level, something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Customer 
{
public Customer(string name, string email)
{
ValidateEmail(email);
//Do the work
}

public void UpdateEmailAddress(string email)
{
ValidateEmail(email)
//Do the work
}
}

But what if now you need to pass that customer to a service needs to send the actual email, do the service assumes then that the email is already validated? do you validate that again? If you think there must be a better way of doing this, well there is. Using the value objects, you put the validation inside a class for that concept and ensure that whenever you have an object that has got created, it is in a correct state. Not allowing the objects to be in an invalid state is a very powerful thing to have, so basically you wouldn’t need a validator framework or such, at least not on your domain level. When the object is created you can trust that it has satisfied the validity criteria.

With the Value Object approach, the above code looks something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Email 
{
public Email(string value)
{
ValidateEmail(value);
Value = value;
}

public string Value { get; private set; }

private void ValidateEmail(string value)
{
if(EmailIsNotValid) //Validate however makes sense
throw new DomainRuleViolatedException("Provided value is not a valid email address.");
}
}

One thing to note here is that the Email value object here is immutable and that is a general heuristic.

There’s still room for improvements. Chances are, you are going to persist this email address, or pass it down to a service that sends an email, one thing that changes your experience with value objects is implicit conversion. To think about this, the email address is in nature a string and can be stored and passed around as such, so we can implement a implicit type conversion to a string:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Email
{
public Email(string value)
{
ValidateEmail(value);
Value = value;
}

public string Value { get; private set; }

private void ValidateEmail(string value)
{
if(EmailIsNotValid) //Validate however makes sense
throw new DomainViolatedException("Provided value is not a valid email address.");
}

public static implicit operator string(Email email)
{
return email.Value;
}
}

Note that Implicit conversion can be a double edged sword. Use it scarcely or you might end up in a situation where the conversion automagically happens and you’ll be clueless on why something is working the way it is.

Now you can pass it to your ORM as a string, or directly pass it to an API that’d require an string and the conversion from already valid email address to a string is automatically done for you.

There are numerous examples where the value object pattern is useful, things such as dates and date ranges where the date conceptually should always be in the past or future, or a concept of a numeric value where the value should always be a positive number or in a certain range.

Another thing to note here is that to be able to assign value objects by value (pardon the pun), you’ll need to use Structs and not Classes. The great example of a value object in struct is the System.DateTime. The reason for going with Struct is that inherently you can assign them by value and not by reference which aligns correctly with our concept of Value Objects. I’m not going to use Structs in these series since they don’t play well with EntityFramework.