✎ Text Section 5 of 10

Entities and value objects

Separate objects with durable identity from immutable values defined by their attributes.

Inside that aggregate live two kinds of object, and the difference is worth being strict about.

An entity has identity that survives change. A Workspace has an id; rename it, change its plan, add and remove members, and it’s still the same workspace. A Member is an entity too — it’s that person’s membership, tracked over time. Identity is the test: if you care which one it is even after its attributes change, it’s an entity.

A value object has no identity and is defined entirely by its attributes. An EmailAddress is just its value — two of them holding the same string are the same thing, interchangeable. Value objects are immutable: you don’t edit an email, you replace it with another.

They’re cheap and badly underused, and they’re where a surprising amount of small domain logic belongs. An EmailAddress that refuses to exist in an invalid form validates itself once, on construction — and then every part of the system holding one can stop checking. A SeatLimit that can’t be negative.

Push rules down into value objects and your aggregate shrinks and your invariants get easier to see.