The Smart DTO

A Data Transfer Object, DTO, is a very simple data-only object typically used for marshalling data across some kind of boundary in your app. A good DTO consists solely of public fields or read/write properties and is Serializable for what should be obvious reasons. Most people seem to gravitate toward read/write properties. I don’t really have an opinion on the matter. While it’s not really important whether or not that boundary lives on another server or AppDomain those are typically the boundaries that require DTOs. WCF calls them DataContracts.

Smart You Say?

I know, “Smart” and “DTO” don’t seem to belong together. Isn’t a DTO just for data transport? Shouldn’t I limit my DTOs to one mission and purpose in life? Yes and no. While you should keep the DTO simple and limited to a single responsibility, I’m a fan of something I’ve been calling a “Smart DTO.” A Smart DTO is a lot like the a Plain Old DTO (PODTO? POD? Nah.) only it adds a few features that the consumer of your DTO can leverage if it wants too. Data Binding and declarative validation are excellent candidates. (Even though I’m using the term Smart DTO you will, I hope, recognize that I’m still keeping things fairly dumb.)

Data Binding

There is a tiny bit of efficiency you can gain by defining a base class that provides the basic infrastructure needed for data binding in .NET. I say tiny because it only saves you from a few lines of code, but, hey, every little bit counts right?

public abstract class SmartDTO : INotifyPropertyChanged
{
   public SmartDTO() {}

   public event PropertyChangedEventHandler PropertyChanged;

   protected virtual void OnPropertyChanged(string propertyName)
   {
      if (this.PropertyChanged != null)
      {
         PropertyChangedEventArgs args =
            new PropertyChangedEventHandler(propertyName);
         this.PropertyChanged(this, args);
       }
   }
}

In your DTO subclass you’d consume the functionality of the base class like so:

public class PersonDTO : SmartDTO
{
   private string _name;

   public PersonDTO() {}

   public string Name
   {
      get { return _name; }
      set
      {
         _name = value;
         OnPropertyChanged(“Name”);
      }
   }
}

Declarative Validation

Validation is also a convenient thing to put into your Smart DTOs. Specifically I’m talking about the attribute-based implementation of the Martin Fowler’s Notification pattern. I won’t get super specific on this as Jeremy Miller just posted a recipe for implementing this pattern. The DTO above would look like so:

public class PersonDTO : SmartDTO
{
   private string _name;
   private string _email;

   public PersonDTO() {}

   [Required]
   public virtual string Name
   {
      get { return _name; }
      set
      {
         _name = value;
         OnPropertyChanged(“Name”);
      }
   }
   [Required, EmailFormat]
   public virtual string Email
   {
      get { return _email; }
      set
      {
         _email = value;
         OnPropertyChanged(“Email”);
      }

}

DTO Do’s and Don’ts

DO NOT bother with interfaces for your DTOs.

DO define a SmartDTO base class with infrastructure for data binding.

DO use declarative validation on your DTO classes.

DO put your DTOs in a separate assembly and don’t be afraid to distribute that assembly to the consumer IF you own the consumer.

DO NOT rely on the consumer to validate the contents of a DTO.

DO use virtual properties to facilitate using your DTOs with your favorite mocking framework.

DO consider writing a simple Domain-Specific Language for your DTOs. It’s very easy to do and will save a great deal of typing. A simple code generator with a very simple file format will get you to where you need to go, ex:

Class Namespace
Class Name
Property1:Type:Validator1,Validator2,Validator3
PropertyN:Type:Validator1,Validator2,Validator3

MyCompany.MyProduct.DTO
Person
FirstName:string:Required
LastName:string:Required
Ssn:string:Required,SsnFormat
Email:string:Required,EmailFormat

DO NOT confuse the DTO with an Entity (Business Object). Entities model the data and behavior of business constructs that have entities. DTOs model the data of messages. These messages may coincidentally resemble the data modeled in a given Entity.

DO NOT define methods or behaviors on your DTOs. Behavior on a DTO is a good smell that you’re moving expanding past the pattern’s intent and maybe confusing the DTO with the Entities.

DO NOT develop DTOs test-first. In my opinion it’s a complete waste of time and misapplication of the practice. Properly test-driving the design of the Service Layer that consumes/produces the DTOs will ensure they get coverage and the benefit of the test suite safety net.

Comments (7) left to “The Smart DTO”

  1. Evan wrote:

    awesome post! I especially like the idea of having a DSL and using the attributes for validation.

  2. Javier Lozano wrote:

    Pretty nice post, David. Here’s one thing if your DTO is adorned with WCF’s DataContractAttribute class, and since all WCF proxies exchange contracts not types, how will you persist the “logic” out of your SmartDTO base-class?

    This will work great if you actually pass the type (and all related info) across the wire (this actually works really well with COM+/Enterprise Services). But when you have to create a proxy and corresponding message classes, that “intent” is removed.

  3. Dave wrote:

    @Evan - Thanks! I wrote a very, very simple one that takes the format (top part) and produces the output (bottom part). I’m kind of debating how to integrate that into the IDE so it builds (right now it’s a command line app). Ideas?

    @Javier - No logic in the DTO. The validation is simply declarative and the logic lives in a commonly distributed assembly. The DTO is read in Good points. Clarifying: I use my SmartDTO only where I own end to end (e.g. applications that need to get across a firewall). You would need to have [DataContract] on each implementation too; it doesn’t inherit does it?

  4. Udi Dahan wrote:

    When defining DTOs for messages as I describe here (http://udidahan.weblogs.us/2007/03/31/tasks-messages-transactions-%e2%80%93-the-holy-trinity/) I don’t think that you’ll find a very good reason to databind anything to them. For instance - CustomerMovedMessage.

    There may be some DTOs that do represent things that are shown to the user, but their design is more dictated by the messages that contain them making them less relevant for users to interact with directly.

    In these cases, which I submit are a significant portion of our DTOs, using the SmartDTO base class does not appear to add value.

    Other than that, me likes :)

  5. Matthieu MEZIL wrote:

    You can factorize all the OnPropertyChanged with a RealProxy.

  6. Dave wrote:

    @Udi - I’m coming from the perspective of using them for a single Application. I agree with your viewpoint if the service boundary is the application boundary (the service is the app, etc.) Our application has a very “Entity Oriented” kind of metaphor: pick a claim or a set of claims and work through some lifecycle actions/commands.

    @Mattheu - RealProxy? I’ve looked at doing injecting this behavior (INotifyPropertyChanged and external declarative validation ala the Validation Block) with Castle’s DynamicProxy library. Is that along the same lines?

  7. Javier Lozano wrote:

    @RealProxy: http://msdn2.microsoft.com/en-us/library/system.runtime.remoting.proxies.realproxy.aspx

    It’s a nice abstraction you attach to your MarshalByRef objects to perform actions on them as they’re about to be sent through the wire. However, I don’t know how you can use this within WCF.

Post a Comment

*Required
*Required (Never published)