The Fallacy of Shared Entity Model
What works for the database doesn't work for an entity, and what works for an entity is a really bad idea if you are trying to call a web service, a web service data is really not the right thing when you want a report. Your customer has a Birthday field, which I couldn't care less. I really want to track the last time a user signed in, but you don't have that information avialable to give me. You really don't want to give the employee salary data to the employee listing grid, etc.
I see a lot of dicussion about trying to have a single Entity (in the pure term: something with business meaning) that map to every representation and any scenario. The needs, constraints and requirements for each fo those are very different. Trying to make them all fit in one representation makes this a very bad representation.
Let us consider a simple entity, the Employee. It contains data such as name, date of birth, hire date, salary, etc. On the database side, it may be represented as a temporal table for each property, linked together by the employee id. In the business logic, I have an EmployeeSnapshot, which is not temporal, but is valid for a certain date only. On the UI, I have only a limited view of the employee (with salary information, for instnace), and a web service exposes additional employee information (hierarchies), to be consumed by the CRM (for permissions).
For this simple entity, I already have four different representation. I might be able to satisfy them all within a single class, but what does it gives me? A heavy weight hybrid that I can't really change without affecting all parts of the system.
In my current project, I have:
- Policy - Active Record Entity - Business logic
- AjaxianPolicy - Simple view of the fields that I want to show on the screen - Strictly DTO
When I get to the part that I need web services for, I will also add PolicyMessage class.
On the surface, this seems to break the DRY principal. I now exposed the fact that Policy has a Id property in several places. I don't think that this apply here, it may looks like repetition and more work, but I end up with simpler model to work with, and I can optimize each individual case independently. And by optimize I do not mean perfromance, I mean ease of use, compatability, etc.
Comments
I have just had this realisation myself. In a current project, I have three complete models. The domain model, the web-based model and the webservice based model. I use repositories to handle the cross-model conversion and I've found it's made the individual facades significantly less complex.
Each facade model only requires a subset of the domain model data. While I was trying to come up with a way to use the domain model once (thinking about serialisation and XSLT) , I wondered why I was finding myself reluctant to create a seperate subset of the model. When I realised it was just because I thought it was the "right" thing to do, I cleared the slate and tried the multi-model approach. It's worked for me so far.
It's still the same entity 'Employee', though with different projections. So at different times T and at different locations L you look at the employee instance E through different projections.
The relational model of Codd then says that a projection is really a new entity, so if I do:
select id, name
from employee
I create a new 'entity' with 2 attributes from the full entity employee by projection of the data.
This is also why projections are so important, also from in-memory data, as it gives you the freedom to use the entity instance's data in different forms.
The main problem though is caused by the focus on a 'class' as the definition of an entity. It's not the definition of an entity. A class is a representation of a container for an entity instance, similar to a table or a set of tables, a view or even a select (projection). As a class is fixed, it leads to the problem what to do with an instance of that class with an instance of an entity inside it when you want to use a subset of its data ? you can't chop off a part of the object.
The solution is simply projecting it onto another container, which could be another class.
Frans,
I agree with you.
The point I am trying to make is for people who want a single class as the end all be all location for everything in the application.
That is a bad practice, in my opinion.
Agreed. It would carry too much weight in a lot of occasions. Though it's something a class model forces upon you: Creating a new class SmallEmployee (silly name) which contains just a small set of the attributes of the employee entity, isn't the same as the employee class yet it represents the same employee object. This is often awkward and people refuse to do so. It's one of the (not many) advantages of the relational model over OO. ;)
Comment preview