Domain model implementation consideration - dealing with presentation-domain model mismatch using rich domain model

Sorry about the title

In a typical data management system significant amount of effort is spent on implementing mappings between three different models - presentation, domain and persistence model. In this article I will describe one approach to dealing with these transformations in case special ORM tool cannot be used.

Absence of sophisticated ORM layer does not only complicate conversions related to persistence but also adds complexity to UI related issues. Usually domain model has the least external restrictions since presentation is specified by non-functional requirements and persistence model is constrained by storage optimizations or legacy compatibility. We can decrease some complexity by designing domain model so that it resembles more closely either persistence or presentation model.

Presentation centric approach

This solution means that our domain model will be identical to presentation model and both are implemented using same set of classes.

Database queries will be relatively complex but we are able to optimize data access since we don't need to retrieve anything from database that we don't need for given use case. Once we have the needed data loaded from database it will be quite easy to show it in UI views since we don't have to implement any transformations or presentation wrappers. As database access code is customized for particular use case (each view) it will be quite hard to reuse it between different DAOs. Similar problems arise also in business logic implementation. Unless we pass around only simple types we are forced to make our domain services depend on presentation specific model. This design actually resembles quite closely Transaction Script.

Persistence centric approach

Alternative option is to let database schema guide our domain model.

This way queries will be more simple but data access will not be that optimal since we sometimes select fields we really don't need for given use case. Also in many cases we end up executing more queries per UI view than in previous approach because we may need to aggregate data from multiple different entities. The good news is that we can reuse our queries and business logic as the domain model is shared between use cases.

Which one is better?

Although it seems that presentation centric solution allows better optimizations I don't think it is good option in most cases. Based on some experience with systems built this way I have to say that possible performance gains cannot outweigh the problems caused by code duplication between different use cases.

Dealing with presentation/domain model mismatch

If we have decided that our domain model will be driven by persistence schema we still need to manage presentation model mappings. Sometimes we don't need to do anything cause persistence model and presentation model are quite similar. However if that is not the case then one solution is to create separate presentation model classes which aggregate multiple domain entities and expose only these attributes of entities that are needed for given view. In our current project we found that it is possible to avoid such classes altogether by using "rich" domain model instead of "flat" domain model. I think this pattern had been used for quite some time in this system but probably it wasn't just acknowledged as a pattern.

So far attributes of our domain entities map quite one-to-one to the fields of database tables. Lets say we have entity User which has home country. In typical "flat" domain model this association is implemented using countryId field. This isn't very useful if we need to display all users and for each user show his/her country.

class User {
  private int countryId;
  ...
}

So why not add whole Country to User:

class User {
  private int countryId;
  private Country country;
}

Of course without advanced ORM layer, loading Country entity all the time can become serious performance killer. So why not implement our own lazy initialization? Instead of AOP or proxies all we need is to establish a few rules. First one is that all queries in DAOs will return entities without any associated items. In order to initialize such associations we will implement special loader methods.

Example:

void loadCountry(User user) {
   user.setCountry(countryDao.load(user.getCountryId()));
}

If needed we can also have convenience methods for initializing some association for list of entities like loadCountry(List<User>). Internally this can be implemented by either iterating through collection or by single WHERE IN query.

I don't usually like to have objects laying around which are only partially initialized. However I'm ready to make and exception here because we have a concrete and simple rule which says that whenever you make a DAO call or service call, only simple type attributes are initialized. In essence this is pretty much same stuff that Hibernate does behind the scenes.

Finally we need to decide where should such initializations be implemented. I don't think it should be responsibility of DAOs because then one DAO would need to manage persistence of more than one domain entity. Second choice are Services. Although I think this is the most commonly used option (and it's used in our current project) I don't like it very much either because ideally Services should deal with real domain logic like orchestrating complex business rules. Third and the best choice in my opinion is having this responsibility in Repositories. Repositories are quite much used in Domain Driven Design but I have never been able to understand the difference between DAO and Repository. However in this scenario it makes perfect sense.

If we use such initialization it may happen that we need to duplicate some initialization logic for different UI views. To solve this I suggest not to pollute Repositories with additional combined initializations like loadCountryAndCity. Instead I think it's better to introduce separate application logic Facades that encapsulate use case specific behavior (read more about this from my public blog entry.

Labels

domainmodel domainmodel Delete
ddd ddd Delete
design design Delete
orm orm Delete
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Apr 13, 2008

    Sven Filatov says:

    Nice post! Especially interesting for me was introducing complex type attribute...

    Nice post! Especially interesting for me was introducing complex type attributes to entities. However, what do you think of having only the complex type in the entity:

    class User {
      private Country country;
    }
    

    In other words, one entity uses another enity. I suppose that would be the usual approach when using Hibernate? And I hope performance penalty can be avoided with using appropriate caching.

    1. Apr 14, 2008

      Ürgo Ringo says:

      Yes having only complex type field is the purest model that any ORM tool should ...

      Yes having only complex type field is the purest model that any ORM tool should support.

      However without any ORM it is much easier to simply add field containing the primary key of associated entity because then we don't need to implement our own caching/proxying for lazy initialization. When first getting User from database we will load only fields having simple types and then later we can initialize the full associated entity if we really need it. Drawback is that we now have two fields per each association but that shouldn't be that big issue since we don't even have to expose the fact of having the field for primary key association.

  2. Apr 01

    Luiz Ribeiro says:

    Hi Ürgo! Is it right that another possible approach to design the domain mo...

    Hi Ürgo!

    Is it right that another possible approach to design the domain model would be to base it on the domain language used by the people involved in the project (including managers and customer)?
    As I understand this is the main idea behind the whole Domain-Driven Design concept, the rest being basically a set of architectural patterns to help in the creation of such rich domain.

    About the repository, if I got it right it is basically an abstraction of a collection of a given entity.
    In practical terms, a simple repository could be just an interface, part of the application domain, implemented by a DAO, part of the application infrastructure.
    More complicated solutions, like the one that you mentioned, could consist of an actual repository class making use of a DAO.

    Have you come to any conclusions about it ever since you wrote the article?

    Thanks!

    1. Apr 01

      Ürgo Ringo says:

      Yes I think the main point of DDD is to focus on the domain. I suppose that it d...

      Yes I think the main point of DDD is to focus on the domain. I suppose that it doesn't mean mapping everything that domain experts (not to mention managers) will tell one-to-one to application. In complex cases domain models in software will need to go deeper than what is used by people who work in given business.

      In my opinion, in simple cases repository and DAO may have little difference how they are implemented. However the difference is more on the conceptual level or the primary goal of these patterns. Yes, it is suggested to create single repository per aggregate root but theoretically you can have separate DAO for each entity in that aggregate root.

      It is indeed interesting why there is much discussion on the technicalities of DDD while much less attention is paid to actual domain modeling. Maybe this is so because it is much harder to teach the latter. There are of course also analysis patterns but applying them and noticing them is much harder. In many cases deeper understanding of domain model is never achieved (maybe not needed either?).

      1. Apr 01

        Luiz Ribeiro says:

        Yeap, that's why I used the term 'domain language', meaning something that is a...

        Yeap, that's why I used the term 'domain language', meaning something that is agreed between all the parts as the terms that are important for that given project.
        Then the domain model would be based on that.

        And yeah, I think the same about the repository. Also one think that is interesting here for me is that it is part of the domain. Which makes sense since in many cases we talk about, for instance, 'all the users' or other terms that resemble collections. I find it is intersting because it means that indirectly the domain is doing persistence access.

        I have the impression that in many cases just there isn't as much interest on the modeling as there is on the implementation details itself.
        I guess it's hard to see people spending much effort/time on learning/doing domain modeling as it might be seen as useless since it does not produce any real artifact but some diagrams, while coding at will produces, well, code :) It might get even trickier when you mix this with the popular agile ways. This guy always talks about this problem people have with DDD: http://fragmental.tw/2010/03/22/nevermind-domain-driven-design/

        On the side note: I can't help myself from thinking about Grails when I talk about this, because it seems to me that it is kinda harder to implement an anemic domain model with Grails than with Spring let's say.

        1. Apr 01

          Ürgo Ringo says:

          About Grails. I think it is quite easy to implement anemic domain model in Grail...

          About Grails. I think it is quite easy to implement anemic domain model in Grails as it is with Hibernate in Java GORM and Hibernate make it simple to map complex data structures to relational database but this does not mean that people are more inclined to implement business logic in their domain model. One can still expose all queries to controller and implement business logic in controller or procedural service layer. In many cases it may actually not make much difference. Some people even say that if you have simple CRUD app you shouldn't use domain model. I'm not sure I agree with this though since we have used domain model in some quite simple apps like online games.