In his book Domain Driven Design (DDD), Eric Evans encourages using Value objects within domain models. Value objects are immutable types utilized as property of entities. Learn the basics of value objects and DDD in the Domain-Driven Design Fundamentals course that I co-authored with Steve Smith. Pluralsight’s team of developers has long been a proponent of the DDD approach to modeling. They use Value Objects across their domain layer in the blog post-2012. Keith Sparkjoy remarked that this helped their C# code appear more practical. This provides many advantages. “Less mutable state tends to make things easier to test and tends to reduce bugs.”
Immutability in your type is more than merely concealing the properties that are setters. It is paired by one of the crucial aspects in a value-object is its identity linked to the mix of its value and not an undetermined identity property. There are many more reliable patterns to ensure that your value object remains immutable. The key to creating a thing of value is:
It is unchangeable.
Its only usage is as an attribute of an entity or an additional value object
It is aware of the use of its properties in conducting any equality check, which includes ones that base their calculations on hash codes.
The algorithm’s logic should not adversely affect states other than the value object.
An Example Value Object: PersonFullName
Let’s look at a kind that could be reused across an entire system, for instance, a font representing a person’s name. It can represent authors, subscribers’ contacts, authors, and so on. I’ll name it PersonFullName, start with a basic version, and then transform it into an object of value.
Let’s imagine that Pluralsight engineers have established an industry standard: each person must have a unique name (often known as the first name) and a surname (aka the last name). My PersonFullName class initially defines two private fields: given and surname. A Create Factory method ensures that you cannot create a PersonFullName without supplying the two parts of the name. This ensures that the character will not be invalid. The factory passes these onto the constructor, who determines the values for the field. In this instance, it is possible to claim this method of the factory is unnecessary. In this case, you can see an example of this implementation. In addition, I employ the expression definitions of the body (see Daniel Szabo’s blog post to find out more about these) on properties to ensure that the properties are only read. The properties know only how to return the value for the respective fields. Expressions allow me to remark on Keith’s admiration for the properties’ C# code leaning towards functional programming.
There is no identity property in this case. The name cannot be tracked by itself. The class will only be employed as a property for another kind.
The type is already immutable. After you’ve created the object, there’s no way to alter it. If you have misspelled someone’s name, then you’d create a new instance. Similar to what you do using the string.
This is an example of the Author class, which uses values as objects.
The Author’s constructor additionally requires that we provide the values for the surname and given and uses these values to construct a PersonFullName object with a new Guid to identify it. If you must change the name, you could use the FixAuthorName method to create the name automatically. DDD helps us think about the behaviors we want to implement in our systems, not only changing and obtaining property values. FixAuthorName refers to a particular behavior required to address a specific problem.
Simply because PersonFullName is unchangeable does not mean it can’t be intelligent. Often, other methods of displaying names can be built directly in the PersonFullName type. For instance, I’d like to view the full name and alphabetize it by surname. I’ve added some additional properties that can only be read, such as Reverse and FullName, by using the definitions of expression bodies.
Making the Value Object Perform Proper Comparisons
PersonFullname is now an unchangeable type with two values but no identification number. To allow this to become a value object, I must ensure that I can test between two PersonFullName kinds to establish if they are equal. Also, I require the flexibility to accomplish this with the Equals method inherited by all objects in C#, as well as using == or= operators. I’m also thinking about conducting tests using MSTest Assert.AreEqual or assertions from other frameworks.
When comparing two instances of this object, using Equals refers to ensuring that each of the objects’ values are within the objects. Certain equality checks are performed by using the hashcodes of an object. This requires adding boilerplate code. There are a few creative ways to accomplish this.
Visual Studio’s Equals & GetHashCode Quick Action
One option is to utilize the Visual Studio Quick Action feature. The first step that can be performed for the declaration of a class involves generating (i.e., or using override) Equals and GetHasCode.
This will determine what members should be included. I will only engage with the given surname and select the properties instead of the fields. Another alternative would be to use IEquatable, which you wish to implement in a way that doesn’t just add an override to Equals and includes an Equals method to the type you want to use. Another alternative is to create operators. This will make sure you can make use of == and= within your program and properly make a comparison between the two PersonFullName objects.