According to Martin Fowler, who coined the term, this pattern is an ‘Anti-Pattern’, and it’s “contrary to the basic idea of Object Oriented design”. I’m not an Engineer (although I’m sure my parents wish I was), but engineering is about picking the best approach to solve the problem. The fact of the matter is, depending on the problem at hand, sometimes an ‘Anti-Pattern’ fits. This particular one, actually does serve some purpose, and I think the benefits outweigh the costs. So come with me for a moment, as I defend this pattern.
Firstly, a major argument against this architecture is that it “violates encapsulation”. It depends on your definition of the word ‘encapsulation’. If we refer to Wikipedia, we get two different definitions:
- A language mechanism for restricting direct access to some of the object‘s components.
- A language construct that facilitates the bundling of data with the methods (or other functions) operating on that data.
Some see the concept as either or, some see it as both. The reality is I could argue either. In fact, to me (and I borrowed this from Uncle Bob’s Clean Architecture) C has a very good mechanism for 1) bundling data and function 2) hiding direct access to functions of the object. That mechanism is the header / definition file pair. You expose everything you want the client to see via the header, and keep anything private in the compiled definition. Languages like C# and JAVA (shudder), expose ALL the functionality in one file, exposing to the client ALL the implementation details of the class. Isn’t that a violation of ‘encapsulation’? To me, having a class that stores data, and a class that stores function, then having a module that exposes them together. Is in fact, better encapsulation.
Another massive benefit of this pattern, is the ‘Separation of Concerns’. If you’re keeping all logic within a class, say you want to keep business logic, persistence logic, and presentation logic in the same class. You’ve now just created a coupling between your storage, your business logic, and your presentation layer. Trust me when I tell you, I’ve been to this Hell, and it isn’t a picnic. It’s an unmaintainable nightmare, the kind that Freddy himself couldn’t engineer. You can fight to use language features like partial classes to manage the distinction, but it only helps a little. You might argue that the idea is to only keep business logic with the class. Separate all else. Well what happens when the line between presentation and business logic become fuzzy? Well, people start coupling, and down the rabbit hole we go. This is illustrated in this statement by Fowler himself “The logic that should be in a domain object is domain logic – validations, calculations, business rules – whatever you like to call it. (There are cases when you make an argument for putting data source or presentation logic in a domain object, but that’s orthogonal to my view of anemia.)”  It isn’t orthogonal, in fact, it is the problem. You might be able to make the argument, but someone else might not. So now, you’ve got someone with a little less experience, and a little less insight, who sees this and replicates it, for the problem they’re solving. Next thing you know, you’re wondering how your UI layer now needs your Database layer to compile. Oh! What about code reviews, and proper discipline. We ALL know how software development works, you’ll spend hours in review, debating why this little piece of persistence logic fits, then why this little piece of UI logic fits. If you follow a clear cut pattern, don’t mix your logic with your data, you don’t have this issue, and it’s easier to catch in a code review, because there isn’t room for debate.
You can implement a very nice service layer, which works on your data model, AND use OO techniques. It is possible.
This pattern, keeping your data separate from your logic, finds massive benefit when you’re working with things like RESTful APIs or really any form of serialization / deserialization to POD data streams. This is due to the fact that serialization of function is difficult at best. Rehydration of complex type hierarchies isn’t child’s play, and doesn’t lend itself nicely to simple interfaces (see ODATA as an example). So you want the objects you pass back and forth to be light and airy. These objects are often referred to as DTO’s or ‘Data Transfer Objects’. In this pattern, you pass them between services, that can persist the object, do logic on the object, or display the object. You might decorate them to add functionality, but at the core, the object stands as data alone.
I’m not saying this ‘Anti-Pattern’ is a silver bullet, because the only silver bullet I believe in is Coors Light. I am however saying, if you’re running into the trap of a coupled nightmare, where one too many people made the argument that presentation and data source logic should be in your model, you might want to see if this architecture helps.
“There is nothing either good or bad but thinking makes it so.” – William Shakespeare