DTOとは

 WebアプリケーションをMVCモデルで本格的に作ることになると、しばしば耳にする不思議な言葉があります。

DTOとは

 Data Transfer Objectの略であり、その名の通り、データを運ぶだけのオブジェクトです。

なぜDTOが必要なのか

 例えば、ログイン処理を例にしてみましょう。

public (型) doLogin(String id, String pass){
  ログイン処理...

  if(ログインOK){
    return 名前、性別、年齢、ログイン日時;
  }
  return null;
}

さて、返す型は何でしょうか。

 通常ならMapでしょうか?Stringに詰めて送るという手段も無いわけではありません。しかし、いずれにしても、中身が分かりづらく、チーム開発では得策ではありませんよね。

 また、MapやStringで貰ってきた値をせっかく解析して各変数に格納できたとしても、次に呼び出すメソッドへ渡す際の引数が問題で、いちいち全て引数で定義している場合の改修コストは計りしれませんし、Mapなどに詰めて渡したとして、呼び先でそのキーを特定する作業がまた必要になってきます。ExcelにKeyValue対応表を作るのでしょうか。どう考えても割に合いません。

 それなら、分かりやすく変数をまとめたオブジェクトを作ってしまおう、と考えました。

 全ては、コードをより読みやすくし、改修コストを出来るだけ抑えるためです。

DTOの実装

 では、先ほどの例をもとにDTOを定義してみましょう。

public class User{
  public int id;
  public String name;
  public String gender;
  public int age;
  public Date loginDate;
}

 賛否ありますが、ここでは全ての変数を敢えてpublicで持っています。勿論、JavaBeansなどのように、private変数とアクセサを定義しても間違いではありません。

 変数を集めただけの只の箱、これがDTOです。

 オブジェクト指向では、オブジェクトにメソッドを持たせることが多々ありますが、ただの箱であるDTOには基本的にアクセサ以外のメソッドを持たせてはいけません。

 概念的な話になりますが、値を箱詰めするのは、コントローラーやモデルの役目です。箱から手が伸びてきていろんなものを自分に入れる、なんてことはしませんよね。

DAOとの関連

 名前が似ているので、関連しているものと思われる方もいるかもしれませんが、全く別のものとして認識してください。

 DAOは、Data Access Objectの略で、その名の通り、データにアクセスするオブジェクトです。通常は、RDBMSなどに接続する際の仲介役を担います。

 アプリケーションは、このDAOに問い合わせを行い、DTOを貰います。その情報を、View上で情報表示や、計算などに利用するわけです。

 DTOは、専らDAOとの受け渡しをするためだけのものと捉えられがちですが、そうではなく、クラス間の受け渡しや、クライアントサイドjavascript、つまりJSONなどとの橋渡しの役目を持つこともあります。

 DAOとDTOはセットになっていなければならない、というのは大きな誤解です。

DTOの使いどころ

 何にでも使えますが、以下に一例を示します。

  • データベースから取得してきた情報を表示する場合
// 仮想のDAOからユーザー情報を取得し、数え年にして表示するメソッド

// bad
Map<String, String> user = dao.findUserById(1);
String userName = user.get("userName");
int age = Integer.parseInt(user.get("age")) + 1;
System.out.println(userName + " (" + age + ")");

// good
User user = dao.findUserById(1);
System.out.println(user.userName + " (" + (user.age + 1) + ")");
  • 引数が多岐に渡る場合、またはそれが予測される場合
// ユーザー登録メソッド

// bad
public void createUser(String firstName, String lastName, String firstNameKana, String lastNameKana, int age, ...){
  ...
}

// good
public void createUser(User user){
  ...
}

 どうでしょうか。このように、DTOをひとつ介するだけで、非常に読みやすく、扱いやすいものになりました。

最後に

 デザインパターンは、様々な知恵の結晶です。具体的な使いどころは難しいですが、適切に使って、効率的な美しいプログラムを書きたいものですね。