Tuesday, March 07, 2006

About DTO, ViewObjects and friends

A few weeks ago at the DDD forum a user (plind69) asked a question about how to send business objects to the presentation layer but have them show only a subset of data based on security settings. Needless to say, this is a much debated topic as witnessed by the large response and variety of opinions. Most solutions where based on the idea of DTOs, weather they are static or dynamic with proxies.

Users that had used DTO in a solution know how painful they can be: for starters DTOs are hard to maintain since every time a domain class changes so must the DTO (and also their assemblers/desassemblers). Then, there is this strange code-smell feelilng that you're duplicating code all over just for the presentation to use. To avoid this some suggest using dynamic DTOs (a nice dynamic DTO framework can be found here).

Although somewhat similar to dynamic DTO, some suggested using dynamic proxies to restrict the view. The solution looks promising for the particular issue of restrict certain fields, but I still believe that other issues should be accounted that are not possible to address with this particular implementation, like the fact that sometimes there are performance implications that make it undesirable to expose domain objects directly. Per example, imagine a fictional complicated purchase algorithm. If the result is calculated on the server, there is no need to send the actual value but a cached value. DTOs are perfect for the task since all its members are cached values. A DTO is basically only a cached set of data from the domain.

So, is there a solution? I don’t know J. First of all, let me tell you that I don't believe there is a silver bullet (at least not that I found) to solve this issues. I think that the mechanics of how to present domain classes to the user (or WS for that matter) should be considered on a use case-by-use case basis.

Maybe using a mix of adapter and proxy pattern could make life easier? A domain object could be proxified to return (or not according to security permissions) the information from the domain object itself, but if needed it could return a cached value. This could be similar to how you use a mock object but instead of creating all mock interfaces by default you pass in the actual domain object. So assuming you could do something like this:

VO viewObject = new VO(personRepository.ForId(1));
viewObject.cacheValue(“complexProperty”).returnValue(complexValue);
viewObject.restrictView(“restrictedProperty”).throwException(IllegalAccessException.Class);

In this way when you accessed regular properties or method, the information will be requested to the actual Person class; if you request a getComplexProperty you will be returned the cached value and if you request getRestrictedProperty you will get an IllegalAccessException. Also I don't think this approach is usuable in the case of Web Services (DTO seem more appropriate here).

So, what do you think? Is this practical or even possible? How do you feel about the different approaches?

3 comments:

Sergio Bossa said...

Hi Roni,

your thoughts are interesting.

However, I don't understand why you state that using proxies is like using DTOs, and why in your code snippet you call your proxy/pattern a ValueObject.

Given this, I think your idea of configuring proxies on the fly and for various purposes looks promising: I'm working on a new open source project aimed at enhancing web development with the Spring Framework and we could work together on your ideas.

Let me know if you're interested.

Regards,

Sergio B.

Roni & Cindy said...

Ciao Segio!

Regarding DTOs and Proxies I actually meant that they looked similar on how you create dynamic DTOs. Dynamic DTOs usually have the some structure as the domain object since they rely on the model having interfaces (like you ICustomer example). Probably I should expand on that.

"and why in your code snippet you call your proxy/pattern a ValueObject."

I never meant to call them ValueObject, just View Objects...I thought taht would explain their purpose better.

About the framework, it would be nice to collaborate. Could you tell me a bit more about it and what are your ideas.

Sergio Bossa said...

> About the framework, it would be
> nice to collaborate. Could you tell
> me a bit more about it and what are
> your ideas

Yes, sure.
Following the idea of your code snippet, we could be able to construct composite proxies on the fly using "fluent interfaces" ... something like this:

SomeFactory.addCachingProxy(interceptor).
cache(pointcut).cache(pointcut);
SomeFactory.addProtectionProxy(interceptor).
restrict(pointcut);
SomeFactoy.makeProxy(domainObject);

This should be possible with Spring AOP.

Spring Web Tools (http://sourceforge.net/projects/springwebtools) is the new born project I'm working on, comprising also an AOP "toolbox" for enhancing domain models, and these ideas could be integrated.

If you're interested to work on with me, contact me at sergio.bossa(-at-)gmail.com.

Regards!

Sergio B.