📜 ⬆️ ⬇️

Entity vs Value Object: full list of differences

The topic of differences in concepts such as Entity and Value Object from Domain-Driven Design is not new. However, I could not find an article with a complete list of their differences, so I decided to write my own.

Types of equivalence


To designate the difference between entities and value objects, we need to define three types of equivalence (equality), which take effect as soon as we try to compare two objects with each other.

Reference equality means that two objects are equal if they refer to the same object on the heap:

image
')
Here is how we can check referential equivalence in C #:

object object1 = new object(); object object2 = object1; bool areEqual = object.ReferenceEquals(object1, object2); //  true 

Identifier equality implies that the class has an Id field. Two objects of this class will be equal if they have the same identifier:

image

And finally, structural equivalence means complete equivalence of all fields of two objects:

image

The main difference between entities and value objects lies in how we compare their instances with each other. The concept of equivalence of identifiers refers to entities, while the structure of equivalence refers to value objects . In other words, entities have an inherent identity, while value objects do not.

In practice, this means that value objects do not have an identifier field, and if two instances of the same value object have the same set of attributes, we can consider them interchangeable. At the same time, even if the data in the two entities are completely identical (except for the Id field), they are not the same entity.

You can think about it in the same way that you think of two people bearing the same name. We do not consider them the same person because of this. They both have an internal (inalienable) identity. At the same time, if we have 1 ruble, we do not care if it is the same coin that we had yesterday. As long as this coin is a 1 ruble coin, we are not opposed to replacing it with another one, exactly the same. The concept of money in this case is an object-value.

Life cycle


Another difference between the two concepts is the life cycle of their instances. Entities live in a continuum. They have a story (even if we do not keep this story) of what happened to them and how they changed throughout their lives.

Value objects, on the other hand, have a zero life cycle. We create and destroy them with ease. This is a consequence, it follows logically from the fact that they are interchangeable. If a ruble coin is exactly the same as another ruble coin, then what's the difference? We can simply replace the existing object with another instance and forget about it after that.

Gaidlan, which follows from this difference, is that value objects cannot exist by themselves, they must always belong to one or several entities. Data that is an object value only has meaning in the context of an entity. In the example with the coins given above, the question “How much money?” Does not make sense, because it does not carry enough context. On the other hand, the question “How much money does Petty have?” Or “How much money does all the users of our system have?” Are completely valid.

Another consequence here is that we do not store value objects separately. Instead, we need to inline (attach) them to entities while saving to the database (more on that below).

Immutability


The next difference is immutability. Value objects must be immutable in the sense that if we need to change such an object, we create a new instance based on the existing one instead of changing the existing one. In contrast, entities are almost always changeable.

Mandatory immutability of value objects is not accepted by all programmers. Some believe that this guideline is not as strict as the previous and value objects may be changeable in some cases. I also held this opinion some time ago.

Currently, I believe that the connection between immutability and the ability to replace one object-value with another lies deeper than I thought. By changing an instance of a value object, we mean that it has a life cycle that is not equal to zero. And this assumption, in turn, leads to the conclusion that value objects have an internal identity, which contradicts the definition of this concept.

This simple mental exercise makes immutability an integral part of value objects. If we accept that they have a zero life cycle, in the sense that they are just an impression of some state and nothing more, then we should also accept that they can represent only one version of this state.

This leads us to the following rule: if you cannot make an object value unchangeable, then this class is not an object value .

How to recognize the object value in the domain model?


It is not always clear whether the concept in the domain model is an entity or an object-value. And unfortunately, there are no objective attributes by which we could judge it. Whether or not a class is an object-value completely depends on the domain in which we work: the same object can be modeled as an entity in one domain and as a value object in another.

In the example above, we view money as non-interchangeably. Thus, this concept is an object-value. At the same time, if we create a system for tracking all bills in the country, we need to consider each note separately for collecting statistics on it. In this case, the concept of money will be the essence.

Despite the lack of objective indicators, we can still use some techniques to relate the concept to entities or objects-values. We have already discussed three types of equivalence: if we can replace one instance of a class with another with the same properties, then this is a good sign that we have an object-value.

A simpler version of the same technique is to mentally compare a class with an integer value. As a developer, it doesn't matter to you whether the number 5 is the same number you used in the previous method. All the fives in your application are the same, regardless of how they were created. This makes the integer type essentially object-value. Now ask yourself: does this class look like an integer? If the answer is yes, then this is an object value.

How to store value objects in a database?


Suppose we have two classes in the domain model: the Person entity and the Address value object:

 // Entity public class Person { public int Id { get; set; } public string Name { get; set; } public Address Address { get; set; } } // Value Object public class Address { public string City { get; set; } public string ZipCode { get; set; } } 

What will the database structure look like in this case? The solution that comes to mind in this situation is to create separate tables for both classes:

image

Such a design, in spite of full validity from the point of view of the database, has two drawbacks. First, the Address table contains an identifier. This means that we will need to enter a separate Id field in the Address class to work with such a table correctly. This, in turn, means that we add some identity to the class. And this already violates the definition of a value object.

The second drawback here is that we can potentially separate the object value from the parent entity. Address can live its own life, because we can delete Person from the database without deleting the corresponding Address line. This would be a violation of another rule, suggesting that the lifetime of the value objects should completely depend on the lifetime of their parent entities.

The best solution in this case would be to “zain-line” the fields from the Address table into the Person table:

image

This will solve both problems: the Address will not have its own identifier and its lifetime will depend entirely on the lifetime of the Person entity.

This design also makes sense if you mentally replace all fields related to Address with a single integer, as I suggested earlier. Do you create a separate table for each integer value in your domain model? Of course not, you just include it in the parent table. The same rules apply to value objects. Do not create a separate table for value objects , just include their fields in the table of the entity to which they belong.

Prefer Value Objects to Entities


The following rule is important in the matter of value objects and entities: always prefer value objects to entities. Value objects are immutable and because of this it is extremely easy to work with them. Ideally, you should always strive to include most business logic in value objects. Entities in such situations will serve as wrappers over them and represent higher-level functionality.

Also, it may happen that the concept that you originally saw as an entity is actually an object-value. For example, you could initially present the Address class in your code as an entity. It can have its own Id and a separate table in the database. After some thought, you notice that in your subject area, addresses do not actually have their own identity and can be used interchangeably. In this case, do not hesitate to refactor your domain model, convert the entity into an object-value.

Conclusion



English version of the article: Entity vs Value Object (DDD)

Source: https://habr.com/ru/post/275599/


All Articles