views:

307

answers:

3

Hi I am developing an application that needs to work with a complex domain model using Hibernate. This application uses Spring MVC and using the domain objects in the presentation layer is very messy so I think I should use DTO's that go to and from my service layer so that these match what I need in my views. Now lets assume I have a CarLease entity whose properties are not simple java primitives but it's composed with other entities like Make, Model, etc

    public class CarLease {
        private Make make;
        Private Model model;
        .
        .
        .
    }

most properties are in this fashion and they are selectable using drop down selects on the jsp view, each will post back an ID to the controller.

Now considering some standard use cases: create, edit, display

How would you go about modeling the presentation DTO's to be used as form backing objects and communication between presentation and service layers??

Would you create a different DTO for each case (create, edit, display), would you make DTO's for the complex attributes? if so where would you translate the ID to entity?

how and where would you handle validation, DTO/Domain assembly, what would you return from service layer methods? (create, edit, get)

As you can see, I now I will benefit by separating my view from the domain objects (very complex with lots of stuff I don't need.) but I am having a hard time finding any real world examples and best practices for this. I need some architecture guidance from top to bottom, please keep in mind I will use Spring MVC in case that may leverage on your anwser.

thanks in advance.

+1  A: 

For what it's worth (I'm developing in C# .net - but the principles should hopefully still be helpful to you) I've defined a bunch of types (DTO's) which I use to exchange data between the business and data tiers; and I have more than one type per domain object / entity. These are defined as simple classes.

Each of these is built with a specific task in mind, for example:

  • I have a light-weight type designed to populate list views (lots of "rows" but not many "columns"). I also have a corresponding collection type that holds any number of these.
  • I have a "big" get copy which usually has all the properties of the entity in question - but for only one instance of it. I may have more than one of these depending on the size and complexity of the entity vs the cases of use; and also depending on whether you want to return all the data associated with an instance of the entity straight away, or lazy-load some on later requests.
  • I also usually have separate "save" (new) and "update" types for the entity.

Each type is designed to hold only the information relevant for a given task. For example the "big" will return the date last modified, but I don't expect that in my save and update types because I populate those in the data access layer.

Also, for my app, these types exist in a common assembly - so they can be re-used between any tier, not just between the business and data tiers.

Architectural Fit

There's nothing particular special about this approach, it has it's own pros and cons; exactly what those are and how they affect you will depend on a lot of things - I guess your mileage will vary - but it's certainly served me well for a number of years now.

People often make a fuss over "separation of concerns" - and that's a really wise move; this relates to DTO's in that they are exchanged between layers (and services, components, etc) so there can always some ambiguity over where exactly to draw the line.

I take the approach that if a bit of information is fit to be exchanged between to tiers it's probably fit to be exchanged between any number of tiers - so why not make it accessible to all? It also saves have to re-cast information if you're just passing it through.

As far as complexity goes - there are two ways of handling that:

  1. Use a verbose / human readable naming convention for all; the types so you know what things are; it doesn't matter how many there are - that's what intelli-sense (& docs) are for. The more intuitive the better.
  2. KISS - keep things simple if you can; you'll have to balance sensible reuse and the Single Responsibility Principle (SRP).

Would you create a DTO of a complex property of a main entity?

I've found myself making DTO's for one of 2 reasons:

  1. There's data I know I need to expose (push), and the design of the DTO is a no-brainer: it's driven by the data I want to expose.
  2. Pull: the consumer know's what it wants, and the DTO is designed to meet those needs.

Because they are all defined in a common assembly no one component "owns" it, it helps force you to think from a 'domain' perspective rather than a component centric one; to an extent this will influence the design of the DTO's (balancing reuse vs SRP).

In both cases the DTO's made can be quiet specific to a particular need, or generic; e.g, A DTO that has only a int and a string is not uncommon, it's the sort of thing you'd use for sending to dropdownlists.

Most of the DTO collections I send back (from DAL to BL) are specific to a concept - not generic. I enforce very very basic rules on these via the constructors I offer: every arg is required. I'm not sure if this answers your question "How do you manage the assembly and validation".

Adrian K
Thanks Adrian, in general this is pretty much what I had in mind. Still i'd like to see how all this fits into an application from the design/architecture perspective and what the the level of acceptance is toward using DTO's like this. I've read many advice of implementing this type of design yet I have not seen any elaborate of concise explanation of how all of it fits together cohisively with proper guidelines, best practice and preferably an example.
arrages
would you create a DTO of a complex property of a main entity, in our app many if not most of the properties are taken from a database to popular drop down select boxes, most of them pretty much come down to ID and a description. How do you manage the assembly and validation?
arrages
RE Examples: As far as examples go, I follow this in my open source web application framework; but it's in asp.net so not sure how helpful that will be. I don't have any articles that discuss it, you'll have to look at the source code :( - http://www.morphological.geek.nz/
Adrian K
RE design/arch fit: it's just a style, an approach. I'll update my answer to try and explain.
Adrian K
Thanks Adrian, this makes it much more clearer.
arrages
+1  A: 

The idea that the service layer should return DTO's instead of EJB objects is mostly a pre EJB3/JPA era idea. During CRUD you really gain a lot from working with the model objects (a.k.a. entities) directly.

You can however benefit from using DTO's when used for performance optimizations, for example when model objects are too bulky or when you gain from using some smart joins for aggregating model data.

So unless you are engineering under SOA, I would not recommend working with DTO’s for CRUD operations.

Kdeveloper
Well the reason is that the domain entities are pretty complex with many properties, methods, etc that I don't need. I tried using them but I didn't like the mess, I had to look into the code to see which form component went with what domain property. That and the security concern with Spring MVC mapping with any visible attribute , a NewCarLeaseDTO has only the data required for creating a new car lease. There is also the idea of a clear separation between layers.
arrages
If you want to reduce complexity, why not just use a façade? A DTO is a detached object, but a facade will keep the domain object in the persistent context. This will make crud operations easier than with DTO’s, but still shield the model from inappropriate front-end usage. You could even re-use model validation rules (JSR303 in JPA 2).
Kdeveloper
How would the facade keep the domain object in persistent context?
arrages
The façade does not need to do anything for it, other than just keeping a reference to the domain object that is already in the persistent context.
Kdeveloper
+1  A: 

Have you considered a command query responsibility separation (CQRS) principle? In a nutshell, it is an architectural principle advocating using separate components for read and modify operations.

Modifications are done using commands sent to the Domain Model. Your NewCarLeaseDTO looks like a command -- CreateNewCarLeaseCommand. They contain all the data needed for a particular operation.

On the other hand, reads (either for list or detail vies) are done directly on underlying data store (SQL database). There are many possibilities here, ranging from having the same data store backing read and write parts to having two independent data stores connected via publish/subscribe infrastructure.

When using the latter (two stores) approach to read side, many (like Udi Dahan) advocate using so-called persistent views. It means storing data directly in the form consumable by your views. Transformation (denormalization) is done when synchronizing after model update.

If you wish to learn more about CQRS, I recommend reading Udi Dahan and Greg Young.

Szymon Pobiega
This is interesting, I'll check it out. Thanks.
arrages