Reply to Transfer Objects vs. Business Objects
Recently, I ran across an article on JavaLobby regarding the practice of passing persistence objects through the various tiers vs. mapping them into DTOs. This short post is timely since I’ve been debating myself on a similar topic. I have a few strong feelings about persistence objects making their way through the standard tiers (presentation, service, persistence). I’ll share…
First, I think persistence frameworks are a good thing. As much talk as there has been regarding ORMs, I take them for what they are worth and use them to map my persistence layer where it makes sense. On green field projects, ORMs are great. On existing legacy projects, it’s a bit harder to get them to play nicely. That said, ORMs have a place and the existence of an ORM in your project does not preclude the use of straight data access through JDBC or the like. In fact, there are times when your use case speaks to using both.
Okay, that has nothing to do with piping persistence objects through the tiers per se; however, ORMs facilitate the practice using of persistence objects outside of the persistence layer. If you took the time to map out a persistence model in your ORM, and it meets your domain model, then you might as well go ahead and use it through the various tiers. Think about it. Your persistence model is 9 times out of 10 mapped to your domain model. Your front end deals with use cases that map to your domain model. As a result, you would be hard pressed to justify the maintenance of parallel graphs of object models for the sake of loose coupling. This is very much the case in new development work, especially in an “Agile” shop. What value does your transfer layer bring to the party but more code to maintain and more mapping code to cause breakage?
There are cases where value objects make sense. I see these closer to the front end though and not necessarily a vehicle to shuttle data between presentation and persistence. Take, for example, a web form or a web service backed by some schema. The user/requester has plugged all of their values in and issued the request. Clearly, there are few cases where this “form” does not conform to your persistence model. You wouldn’t want this for various reasons, the least of which is exposing your persistence model to the client. There is a natural mapping pattern here – from incoming document to persistence. This pattern is present in most web and web service based applications. I think the 80-20 rule applies here. If you go with an additional layer of domain indirection here, what have you gained?
Granted, there may be justified reasons for creating a mapping layer. I can think of only a few, but there are some valid reasons for doing this. But, if you are interested in faster turn around, less code to test, and less overhead, then there is little room for the additional layer.
The article goes further to cite a con of using persistence models in the presentation tier as giving rise to LazyInitExceptions. Really? My argument against this is that every use case should understand its portion of the domain model. If you agree to the principal that your domain model maps closely to your persistence model, then you already know your graph of persistence objects you need to deal with.
Example : Customer submits an order. Yep, you guessed it… I brought in the entire domain (read persistence backed graphs) into the picture to address this use case. This includes, at the very least, customers, orders, order lines, and products. There are relationships here that indicate what portions of this graph I need to deal with. There are other relationships that I don’t care about and would not need to load. My use case drives my graph and my graph instances are for the correct persistence model.
There is room for compromise. The presentation tier could carry its own, light weight, wrapper around persistence objects. This, at least, eases the pain of maintenance and exposes attributes necessary for presentation work to be done without affecting the persistence model too much. This could be used for managing collections, UI attributes, context based attributes that do no require persistence, etc… These aspects are transient and only help to satisfy presentation or organizational concerns.
I do think there is a sliding scale here to all of this. In most cases, your dealing with a dual use graph. It just so happens that your domain model serves your presentation tier. If you haven’t bled the persistence concern to the presentation tier, I think you’re okay. If your application is massive and needs to map to a DTO for legacy concerns, do what you must.
As with everything, your mileage will vary…