Twelve years later, things have moved on quite a bit. Many now recognise the benefits of such a split; yet some still, near-religiously, stick to the idea that the anaemic data model is somehow “not real OO”. Part of this stems from the (presumably deliberate) use of a negative term to describe that separation approach. It’s therefore time to fight back with new definition of the terms “RDM” and “ADM”, to help move us away from the antiquated view that separating data from functionality is an anti-pattern. It’s the RDM that has been shown to be the real bad design approach.
Martin Fowler’s article makes various assumptions about what constitutes good data design:
- OO offers the ability to encapsulate state and only allow it to be accessed via an object’s methods.
- Procedural code couldn’t (so easily) encapsulate state in this way.
- OO is inherently better than procedural designs, as it can encapsulate state, tied to functionality. Thus, if a language supports objects, then they should be used to store state and functionality together. Failing to do so is an anti-pattern.
- This doesn’t just apply to domain models; any object that only contains data is “anaemic” as it fails to mix functionality and state.
Does it really matter though? Isn’t the fact that all these languages mix and match programming paradigms a good thing? Their existence (and popularity compared to Smalltalk) would suggest so. Does it really make sense to talk in terms of “OO languages”, “procedural languages” and “functional languages”? Probably not. Anyone keeping tabs on what’s being suggested for implementation in C# 7, for example, will know that those corner-stones of functional programming – tuples, records and pattern matching – are the most popular features requested. Languages are becoming ever more “hybrid”, or “multi-paradigm” in nature.
There’s a good reason why languages, that might traditionally be seen as OO languages, are embracing functional features. The nature of how programs work is changing. Gone are the days of the simple, single-threaded, world. Now days, it’s all about sharing data between distributed, parallel processes, applications or even servers. The single biggest hurdle to this change is shared, mutable state. Various ideas have been tried over the years to overcome problems with shared, mutable state and all, save for one, have problems. That one way, ironically, is to get rid of it! Parts of the system have to have changing state, such as any user interface and any data store. Beyond that, there’s no actual need for state to change as it’s passed around the system.
The “Rich Domain Model” (RDM) is unfortunately built completely on the idea that we pass around state, and the means to change that state, coupled together. For example, we might expect an object that acts as a proxy to a database table to enable us to update it and thus update the table. The very core of the RDM contradicts the needs of modern, distributed, parallel systems; that core is quite rotten. If the core is rotten, then the whole model is rotten, thus RDM really is better seen as the Rotten Domain Model these days.
What well-designed modern systems have, is clusters of functionality, passing around immutable data. We have a separation of the data from the functionality: the two parts are abstracted away from each other. So far from being anaemic, the ADM is an abstracted solution that works well with distributed, parallel systems. The ADM, as the Abstracted Domain Model, has actually been proven to be the better system.
(The image used with this post is from http://www.publicdomainpictures.net)