I am learning about Primitive Obsession. Please see the value object below:

public class UserName
    private readonly string value;

    public UserName(string value)
        if (value == null)
            throw new ArgumentNullException("value");
        if (!UserName.IsValid(value))
            throw new ArgumentException("Invalid value.", "value");

        this.value = value;

    public static bool IsValid(string candidate)
        if (string.IsNullOrEmpty(candidate))
            return false;

        return candidate.Trim().ToUpper() == candidate;

    public static bool TryParse(string candidate, out UserName userName)
        userName = null;
        if (string.IsNullOrWhiteSpace(candidate))
            return false;

        userName = new UserName(candidate.Trim().ToUpper());
        return true;

    public static implicit operator string(UserName userName)
        return userName.value;

    public override string ToString()
        return this.value.ToString();

    public override bool Equals(object obj)
        var other = obj as UserName;
        if (other == null)
            return base.Equals(obj);

        return object.Equals(this.value, other.value);

    public override int GetHashCode()
        return this.value.GetHashCode();

which I took from here: http://blog.ploeh.dk/2015/01/19/from-primitive-obsession-to-domain-modelling/

Say the Aggregate Root class is: Customer. Would it be "better" to name like this:


Also say a customer has a list of Orders, which contains Products. How would I name the Product Description class? The two options are:


There's nothing domain-driven-design specific, or primitive specific, about how those value types should be named.

Typically, you will choose names that express the semantics of the value, rather than validation or implementation details. Within the domain model, those semantics are typically restricted to queries that have meaning within the domain model itself (Balance, for example, to describe the current billing state of an Account); at the boundary those semantics are typically restricted to queries that produce domain agnostic representations TimeStamp.toIso8601()

It's frequently the case that crud domains will have a number of types that have no interesting semantics at all. "Name", "Description", "EmailAddress" are commonly handles to data that the domain model never inspects directly. You probably don't need separate implementations for CustomerName and ProductName if the domain model doesn't treat them differently.

You might want type aliasing, in a context where there are two different Name values that you want to avoid confusing. Here's a discussion a aliasing in C#.

Part of the point of is that the language in the code should be in close alignment of the language in the business. So the "real" answer is: pay close and careful attention to the language that the domain experts use, and match those spellings as closely as you can manage.

| improve this answer | |

Not the answer you're looking for? Browse other questions tagged or ask your own question.