Sunday, December 24, 2006

What should DTO contains

Martin Fowler define DTO as object that carries data between processes in order to reduce the number of method calls. DTO is offen used to transfer data between remote client and server therefore serialization/deserialization mechanism on both side are required. The question is what should a DTO contains and what should be the structure of a DTO ? The general consensus is that DTO should be simple acyclic structure and contains only primitive data type (e.g. string, number, etc.) or other DTO. My view is that such restriction will make DTO easy to write/read to/from dictionary structure like map. Using map as data structure for transfer data between client and server will make client less fragile more torerant to any change of DTO (e.g. adding new field ) on sever side. In the following example, PersonDTO class to contains non primitive types
class Sex {
   private String code;
   private String name;

   private static Map map = new HashMap();

   public static Sex MALE = new Sex("M","Male");
   public static Sex FEMALE = new Sex("F","Female");
   public static Sex UNKNOWN = new Sex("U","Unknown");
   
   private Sex(String code, String name){
      this.code = code;
      this.name = name;
      map.put(code,this);
   }

    public String getCode() {
        return code;
    }

    public String getName() {
        return name;
    }

    public static Sex valueOf(String code){
      return map.get(code) != null ? (Sex)map.get(code) 
             : UNKNOWN;
   }
}

class PersonDto {
   private Sex sex;
   private Calendar birthDate; 
   private String name;

   public PersonDto(Sex sex, Calendar birthDate, 
      String name) {
        this.sex = sex;
        this.birthDate = birthDate;
        this.name = name;
   }

    public Sex getSex() {
        return sex;
    }

    public Calendar getBirthDate() {
        return birthDate;
    }

    public String getName() {
        return name;
    }
}
We can refactor PersonDto to contains only primitive type
class PersonDto {
   private String sexCode;
   private long birthDateInMillis;
   private String name;

   public PersonDto(Sex sex, Calendar birthDate, 
     String name) {
        this.sexCode = sex.getCode();
        this.birthDateInMillis = 
            birthDate.getTimeInMillis();
        this.name = name;
   }

    public Sex getSex() {
        return Sex.valueOf(sexCode);
    }

    public Calendar getBirthDate() {
        Calendar result =  new GregorianCalendar();
        result.setTimeInMillis(birthDateInMillis);
        return result;
    }

    public String getName() {
        return name;
    }
}

No comments: