Value Objects
Value objects are immutable, strongly typed domain objects that encapsulate a single value. They help combat stringly typed
code and “primitive obsession.” ^1
Value objects are a fundamental concept in Domain-Driven Design (DDD). They provide a way to model the business domain in a way that is clear, concise, and robust.
Why Use Value Objects?
- Stronger typing: Value objects provide a more expressive and type-safe way to represent domain concepts. The compiler enforces the type of the value object, preventing runtime errors.
- Immutability: Value objects are immutable. This means that once a value object is created, its value cannot be changed. This helps to prevent accidental data corruption and makes your code more predictable.
- Encapsulation: Value objects encapsulate the logic for validating and manipulating the underlying value. This makes your code easier to understand and maintain.
Example of a Value Object
Consider the example of a customer ID. A customer ID is a unique identifier that can be used to track a customer. Using an int
to represent a customer ID can lead to problems:
public void DoSomething(int customerId, int supplierId, int amount)
The compiler won’t warn you if you accidentally swap customerId
and supplierId
.
Using a value object, the method signature becomes much more strongly typed:
public void DoSomething(CustomerId customerId, SupplierId supplierId, Amount amount)
Now the caller can’t mess up the order of parameters, and the objects themselves are guaranteed to be valid and immutable.
Implementing a Value Object
public class CustomerId : ValueObject
{
}
This example shows how a CustomerId
is defined. CustomerId
derives from the package’s ValueObject
type. Value objects can have validation as well:
public class CustomerId : ValueObject
{
public override Validation Validate() => Value > 0
? Validation.Ok
: Validation.Invalid("Customer IDs cannot be zero or negative.");
}
Using Value Objects
Instead of using an int
to represent a customer ID, we can now use the CustomerId
value object:
var customerId = CustomerId.From(42);
Benefits of Value Objects
- Improved code readability: Using value objects makes your code easier to read and understand.
- Reduced code duplication: Validation is in one place.
- Increased testability: Value objects are easier to test than primitives.
- Improved domain modeling: Value objects help you model the business domain in a way that is more accurate and expressive.
Resources:
Note:
The code in this outline is taken from the stringlytyped
repository and related files. ^1 ^2
## Top-Level Directory Explanations
<a class='local-link directory-link' data-ref="samples/" href="#samples/">samples/</a> - This directory contains example projects demonstrating the usage of StringlyTyped library.
<a class='local-link directory-link' data-ref="src/" href="#src/">src/</a> - This directory contains the source code of the StringlyTyped library.
<a class='local-link directory-link' data-ref="tests/" href="#tests/">tests/</a> - This directory contains unit tests for the StringlyTyped library. It includes benchmark tests and small tests.