Jean-Paul is a big fan of DTOs. Initially I was skeptical of because I saw them as an unnecessary additional mapping layer. However I filed this technique away in my tool box. And today I needed to reach into that tool box and DTOs were perfect for the problem in hand.
I was working on a complex screen that was an aggregation of many domain objects. To make matters worse the relevant parts of the domain model were in the middle of a “transitional period”. I wanted to avoid mapping a complex web of properties in the view because of testability concerns. I know that I could use MVP but I don’t think that it adds a lot of value, especially considering the additional effort. Hopefully I am never going to need to use it again because Microsoft MVC will CTP soon.
My solution was to create a DTO and build the screen on that. Initially in the Repository I simply created a stub implementation that returns a hard coded IList<> of the DTOs. Once the screen was working I fixed the domain model.
Previously I posted about NHibernate Projections. With DTOs you need to map from your domain onto the DTO at some point. I chose to do this in the Repository using projection because it is the most efficient place to do this (testing is a little harder than in a mapping layer but not significantly so).
In the process I learned something new about HQL. In some cases we need to use field rather than property (the default) access in the hbm.xml files.When performing the projection I needed to reference the field in the HQL query e.g. “select new CustomerDTO(c.Property, c._field) from Customer c”.
“Once the screen was working I fixed the domain model.”
To me thats an interesting approach — its been drilled into me, and I’ve taken it as gospel that the database and back-end whatevers all need to come before the screens. How well does this approach work in comparison? I can see some huge opportunities here, but on the flip side people older and wiser than me have said differently.
Certainly one of the things that DTOs buy you is flexibility in the the order that tasks are completed. However even without DTOs I am still constructing the domain entities before the associated database objects. My repositories are often stubs that return canned data. In fact I’ve even developed an entire (small!) application before I even created the database. TDD is the primary reason that I’ve ended up here – it’s much easier to test the domain than the database. Evolutionary design really does work…if you have supporting tests.
Jason,
I like your solution using projection to form a view specific entity, but am confused with the pattern terminology. Does the problem space really call for a DTO or more of a presentation entity? (Presentation Model) I guess I see DTO’s as objects which get moved between tiers, a classic example being webservices or remoting. They may provide aggregation\facade of the domain, but thats about it.
It seems like in this scenario calling the customer a DTO has implications, especially if you were to apply it to a larger enterpise (which you were clearly not, but I cant help myself!). One I can think of is Validation, which would fall on the CustomerDTO since it is more or less bound to the view. Another is that we have created a repository method which returns a CustomerDTO specifically for the behavior of this view.
Would you do it different in a greenfield enterprise scenario? Again, very cool stuff.
Jarod – yes there is a terminology issue here. JP himself was called on this: http://www.jpboodhoo.com/blog/ScreenBoundDTOUpdateGettingTheTerminologyRight.aspx.
Regarding validation I don’t really see that this scenario creates an additional problem. Typically I treat validation is a screen level concern (at least when there are screens involved!). I don’t like this but with another approach you need a way to map errors back to fields and I have not determined a good way to do this. I don’t like the ASP.NET validation controls (especially from a testability POV) but they do solve the problem.
Note that the previous paragraph is all theory as I have not yet tackled DTO validation…but that will change today (if I ever stop responding to comments!). I’ll do a follow up post on what happens.
Regarding the additional repository method I am not completely comfortable with this either. I am a firm believer in avoiding premature optimization. As I indicated in the original posting my concern about DTOs is that they were superfluous because they didn’t add value. I don’t expect that I will use them all the time, just where necessary. It remains to be seen how often this turns out to be.