CelinHC
CelinHC

Reputation: 1984

DDD - Value Object flavor of an Entity

I've seen some DDD projects with value object representations of entities. They usually appear like EmployeeDetail, EmployeeDescriptor, EmployeeRecord, etc. Sometimes it holds the entity ID, sometimes not.

Is that a pattern? If yes, does it have a name? What are the use cases? Are they value objects, parameter objects, or anything else? Are they referenced in the domain model (as property) or are they "floating" just as parameters and returns of methods?

Going beyond...

I wonder if I can define any aggregate as an ID + BODY (detail, descriptor, etc) + METHODS (behavior).

public class Employee {
    private EmployeeID id;
    private EmployeeDetail detail; //the "body"
}

Could I design my aggregates like this to avoid code duplication when using this kind of object?

The immediate advantage of doing this is to avoid those methods with too many parameters in the aggregate factory method.

public class Employee {
   ...
   public static Employee from(EmployeeID id, EmployeeDetail detail){...};
}

instead of

public class Employee {
   ...
   public static Employee from(EmployeeID id, + 10 Value Objects here){...};
}

What do you think?

Upvotes: 3

Views: 580

Answers (3)

mrdnk
mrdnk

Reputation: 685

OK - great question...

DDD Question Answered

The difference between an entity object and a value object comes down to perspective - and needs for the given situation.

Let's take a simple example...

A airplane flight to your favourite destination has...

  1. Seats 1A, 10B, 21C available for you too book (entities)
  2. 3 of 22 Seats available (value object).

The first reflects individually identifiable seat entities that could be filled. The second reflects that there are 3 seats available (value object).

With value object you are not concerned with which individual entities (seats) are available - just the total number.

It's not difficult to understand that it depends on who's asking and how much it matters.

Some flights you book a seat and others you book a (any) seat on a plane.

General

Ask yourself a question! Do I care about the individual element or the totality?

NB. An entity (plane) can consider seats, identity and / or value object - depending on use case. Also worth noting, it has multiple depends - Cockpit seats are more likely to be entity seats; and passenger seats value objects.

I'm pretty sure I want the pilot seat to have a qualified pilot; and qualified co-pilot; but I don't really care that much where the passengers seats. Well except I want to make sure the emergency exit seats are suitable passengers to help exit the plane in an emergency.

No simple answer, but a complex set of a pieces to thing about, and to consider for each situation and domain complexity.

Hope that explains some bits, happy to answer follow-up questions...

Upvotes: 1

Levi Ramsey
Levi Ramsey

Reputation: 20551

What you're proposing is the idiomatic (via case classes) approach to modeling an aggregate in Scala: you have an ID essentially pointing to a mutable container of an immutable object graph representing the state (and likely some static functions for defining the state transitions). You are moving away from the more traditional OOP conceptions of domain-driven design to the more FP conceptions (come to the dark side... ;) ).

If doing this, you'll typically want to partition the state so that operations on the aggregate will [as] rarely [as possible] change multiple branches of the state, which enables reuse of as much of the previous object graph as possible.

Upvotes: 4

Farhan Nasim
Farhan Nasim

Reputation: 817

Could I design my aggregates like this to avoid code duplication when using this kind of object?

What you are proposing is representing the entire entity except its id as a 'bulky' value object. A concept or object's place in your domain (finding that involves defining your bounded contexts and their ubiquitous languages) dictates whether it is treated as a value object or an entity, not coding convenience.

However, if you go with your scheme as a general principle, you risk tangling unrelated data into a single value object. That leads to many conceptual and technical difficulties. Take updating an entity for example. Entities are designed to evolve in their lifecycle in response to operations performed on it. Each operation updates only the relevant properties of an entity. With your solution, for any operations, you have to construct a new value object (as value objects are defined to be immutable) as replacement, potentially copying many irrelevant data.

The examples you are citing are most likely entities with only one value object attribute.

Upvotes: 1

Related Questions