Category-mistakes and Value Objects

Practicioners of Domain Driven Design (DDD) often ask whether something should be modelled as an Entity or as a Value Object. An Entity is a domain-object with an identity-property, so it can change over time and still be tracked. It can also be discerned from similar objects by its identity, even if they have the same state. On the other hand, a Value Object is an immutable object without an identity-property. Two Value Objects with the same state, the same value, are considered replacable, interchangeable, effectively the same. Although the distinction between Entities and Value objects has many merits, it is a so called category-mistake to use the two conjunctive (joined by 'and')  or disjunctive (joined by 'or') in one sentence. A category-mistake is not a term from category theory, but coined by the linguistic philosopher Gilbert Ryle in the middle of the 20th century.

Category-mistakes

An example: someone is visiting Oxford or Cambridge. After having seen a number of colleges, libraries, playing fields, museums, scientific departments and administrative offices the visitor asks: "I've seen all those buildings, but where is the University?" Another illustration: someone watching a cricket game learns what the functions of the bowlers, the batsmen, the fielders, the umpires and the scorers are. He then says "But there is no one left on the field to contribute the famous element of team-spirit". These are some of the examples used by Gilbert Ryle in his book 'The Concept of Mind', first published in 1949, to explain what category-mistakes are [1]. Ryle uses the concept of a category-mistake to show that the sentence "there exist both bodies and minds" (a.k.a. Descartes' Myth) is absurd.

Ryle: "When two terms belong to the same category, it is proper to construct conjunctive propositions embodying them. Thus a purchaser may say that he bought a left-hand glove and a right-hand glove, but not that he bought a left-hand glove, a right-hand glove and a pair of gloves." You'll find more examples and analyses in Ryle's book. BTW: it's one of the best books I've ever read, highly recommended.

Value objects

 I phoned my dentist to change an appointment. "Sorry, we cannot do that", the assistant replied. "Why?", I asked."Because we have a new software system, entirely made with DDD. Appointments are now Value Objects and so they are immutable". Of course I'm just joking, but there is some truth in it: in DDD you can often hear that some date and time should be modeled as an (immutable) Value Object.  You then model an appointment as being on a specific date and time, immutable, and you'll have to reschedule a new appointment if you want it on another date and time.

In essence the date and time are values of the appointment. In our traditional class oriented languages dates and times are objects and those objects are assigned by reference, not by value. And there you have the core of the problem: changing the value of an object means changing any reference to that object. As with many design patterns the solution is specific to the used language and paradigm. For instance: most Gang of Four design patterns are not needed when working in other computer languages than the traditional OO-ones [2]. Those patterns offer solutions for specific problems of class oriented languages. The same holds for the design pattern of Value Objects: it is a solution for the problem that when we define a class to designate a type for values, in many computer languages the value is stored as a reference to an object. In languages where we can define types without defining a class for it we don't have this problem.

Value Objects are just values, values of properties of  (domain) objects. The confusing part is that in many traditional languages those values are molded into objects, mostly because an extensible type-system is missing. Those "objects" can be seen as a poor man's (M/F) solution for types. You sometimes hear the term "value types" to express this idea. It is a type that can only hold a specific value, not a variable; hence it is called 'immutable'.

Entities and Value Objects: different categories

An object can have properties with values. Values can be of a specific type (which are built as an object in many languages). Objects are not of the same category as their properties. It is for instance absurd to say: "in my garage I have my (red) car AND the colour red". Because "red" is just the value of the  colour-property of the car-object and even if that property is instantiated as a (value) object, the car and its colour are still of a different category.

The merits of Value Objects

In 2004, at the time Evans and Fowler wrote about the Value Object Design Pattern [3], two "solutions" were very much used where a Value Object would  have been a better choice: "Primitive Obsession" and "Entititis". "Primitive Obsession" is where a standard type is used, that is built in into the used computer language, like String or Integer. "Entititis" is making everything entities; often easily provided by standard libraries and ORM frameworks. Object orientation was the main paradigm and there were not many possibilities for custom typing other than via object instantiation in the mainstream languages of that moment. So, it came at the right time. Many of the currently used computer languages are still mainly based on classes and objects to define custom types. You can still find plenty of examples of both "Primitive Obsession" and "Entititis", so the idea of Value Objects is still useful.

Aggregation and composition

In UML a distinction is made between aggregation and composition. Both are whole-part relationships and both use a diamond as a symbol in diagrams. A filled diamond depicts composition, an unfilled one aggregation. A composition association implies that the life-cycle of the 'part' cannot extend beyond the life-cycle of the 'whole'. The terms are not used consistently in the literature. In the GoF-book for instance the terms are used in exactly the opposite way: there, a part of an aggregate has the same lifetime as the whole; and what is called an aggragate in UML is called an 'acquaintance' in that book. More important than how words are used is that the distinction is made. From the introduction of the GoF-book: "It's easy to confuse aggragation and acquaintance, because they are often implemented in the same way" and "Ultimately, acquaintance and aggregation are determined more by intent than by explicit language mechanisms. The distinction may be hard to see in compile-time structure, but it's significant". I use the terms aggregate and composition as in UML, so composition is a stricter relation than aggregation: the parts of a composition do not exist outside the whole.

Using a part and the whole conjunctive or disjunctive in one sentence is a category-mistake. In the case of aggregation you could still see it as 2 different entities that are combined in one whole. For instance: a blogpost and its comments. Then the blogost-plus-comments is the whole; both the blogpost and the comments are parts. In the case of composition, the parts form the whole. For instance an order and its order lines: the order cannot be seen apart from its order lines. The whole is the order (not the order-plus-order-lines). Thinking in orders and order lines as separate entities also comes from relational calculus, where everything is a relation: entities, relations, parts, wholes. Active Record, with its one-to-one mapping of database tables and objects, has also contributed to this kind of thinking in the OO-world, where everything is a class.

There are several words that have a slightly different meaning in the DDD-community than in the broader world of software development and modelling. One of those words is "aggregate". In DDD it is used for any minimal constellation of objects that form a consistency boundary for changes of state. I haven't seen much distinction made by DDD-practicioners between aggregation and composition and language is somtimes fuzzy because of category-mistakes. If for instance a bid can be made in an aution, we see diagrams with auctions and bids together. Also the name of one entity is often used as the name of the aggregate and the interface for the whole aggregate is put in that "main" entity, used as entrance for the aggregate (the "aggregate root").

Better models by more accurate language

 I'm not critisising the ideas from DDD, but only saying that some terms might be improved. Names for things are important. Mistakes with subtle differences in meaning can lead to less useful models. Practicioners of DDD understand the power of language; it is therefore that they proudly call themselves "domain linguists", trying to purify the language with which the domain is modelled. The words we use are the building blocks of our models. If the language is not accurate, the model won't be too; garbage in - garbage out. And that is also true for the domain of domain modelling itself.

Herman Peeren
August 2017

 


 

[1] https://en.wikipedia.org/wiki/The_Concept_of_Mind

[2] Gang of Four (GoF) refers to Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, the 4 authors of "Design Patterns: Elements of Reusable Object-Oriented Software" (1994). In 1998 Peter Norvig demonstrated that 16 out of the 23 patterns in Design Patterns are simplified or eliminated (via direct language support) in Lisp or Dylan; see http://www.norvig.com/design-patterns/

[3] Eric Evans: "Domain-Driven Design: Tackling Complexity in the Heart of Software" (2003). Martin Fowler: "Patterns of Enterprise Application Architecture" (2002)

 


 

Also posted on DDD/CQRS mailinglist. Discussions and feedback are possible there:
https://groups.google.com/forum/#!topic/dddcqrs/Icep9ujRllk