Suppose we have an Order in a warehouse context. And we have a Client that's getting that Order.
Although in the DB Client
has an ID and a bunch of parameters, but I model it as a value object inside my Order:
class Order extends AggregateRoot {
private client: Client;
private shipping: Shipping;
private items: Array<OrderItem>;
}
class Client extends ValueObject {
public readonly name: string;
public readonly contactPhone: string;
public readonly contactEmail: string;
}
The reason I model it as a value object is simple - I don't think warehouse cares about who the client is. The data is primarily needed for booking couriers, and in this context the Client can't really change his names or contact details - that would require adjustments to courier booking (at which point, might as well just treat it as a different Client altogether).
Now I'm thinking that it would actually be nice to know client ID (for some analytics or traceability). Easy:
class Client extends ValueObject {
public readonly name: string;
public readonly contactPhone: string;
public readonly contactEmail: string;
public readonly clientId: DomainID; // or ClientID, not essential
}
However, here is the confusing point: now this looks like an entity (after all, I'm essentially denormalizing an entity from a different context as a value object). The "identity" doesn't really make sense here, as I wouldn't care about the clientId
when checking for Client
equality.
To put it in other words: for all practical purposes warehouse does not care about client identity. Also, warehouse can not change any client details. But, there exists the implicit understanding that we are shipping to the same client - client with same identity.
Am I fine modeling Client
as a value object? Is this a common trap and I'm just taking the "Value Objects over Entities" rule to an absolute level?