Tuesday, May 6, 2014

Breaking Domain Depedency on Data Access: Let Presentation Depend on Data Access

This is the second post about not letting domain layers be depend on data access layers. This post explores the (maybe) most obvious way to reverse the dependency between domain model and data access in classic three-layer architectures

Which is to basically turning this

into this

Notice that the arrow from the Data Access component to the Domain Model? Why is that there?
To answer that lets take a quick look at an example. Say we have a web enabled e-commerce system with an endpoint that lets clients add an item to a logged in users wishlist (in others words a simplistic version of something like Amazons wishlist). To do that the code for the endpoint needs to:
  • Get the user the call is made on behalf of
  • Retrieve that users wish list from the data access component
  • Add the item to the wish list
  • Save the updated wishlist back through the data access component
Which is accomplished with code along the lines of:

This code looks almost like it would have in a classic 3-Layer Architecture. So how does this code justify the dependency arrow from the Data Access component to the Domain component? It does so because:
  • The WishListRepository is found in the Data Access component
  • The call wishListRepository.GetByUserName(Context.CurrentUser.UserName)
    returns a Domain object - an instance of the WishList Domain class.
  • The call wishListRepository.Save(wishList) accepts a Domain object
So there you have it: Allowing the Presentation component to talk to the Data Access component allows you to cut the dependency from Domain to Data Access, but introduces the reverse dependency. For the reasons argued in the first post (and in the resources referenced there) this a much better position to be in than the one in the top most diagram.

An Added Benefit 
 Notice that the data access component now returns Domain objects when queried. That is possible because the dependency points from Data Access to Domain. It used to be the other way around. So ... what did the Data Acces code return on queries before? Most likely some object containing the relevant data from the data base. These types of object come under different names: WishLisDTO, WishListEntities (as in NHibernate or Entity Framework entity), DataModels etc. Regardless of the name their main purpose is to move data from the database into the layer on top of the Data Access layer (i.e. the Domain layer in the top most diagram). But now that the Data Access code returns Domain objects directly these are no longer needed to move data into the rest of the system. In the cases where the mapping from the database to objects is not complicated these DTOs/Entities/DataModels have become superfluous and can be deleted. This can turn out to be a lot of code that can be deleted.

The major downside here is that the endpoint code has been given slightly more responsibility, since it now has to fetch Domain objects - which it also did before - and also has to save them again after interacting with them. Depending on the state of affairs before breaking the Domain to Data Access dependency the endpoint may or may not have had to explicitly save changes. That may have been handled by a combination of dirty tracking and infrastructure code.
In the 4th post of this series I will show a way to remove this extra responsibility from the presentation layer again.

No comments:

Post a Comment