Data Transfer Object
1. 目的
- 複雑なドメインオブジェクトをDBに永続化する処理で楽をしたい
2. 課題
- 複雑なドメインオブジェクトをRDBにデータを格納するのは面倒
- 別のインスタンスやインスタンスのリストを内包しているなどするので、安易にシリアライズするだけではRDBに保存できない(RDBに適した構造に組み替える必要がある)
3. 解決策
- 登録対象のテーブル構造を表現したプロパティとアクセサだけを持つ振る舞いを持たないオブジェクト(以下DTO)を定義し、DBへ永続化する際はDTOにデータを詰めてデータ登録処理へ渡す
- Pythonだと↓のような感じ(コンストラクタとプロパティのみ、メソッドなし)
# ItemテーブルはIDと名前と価格を持つテーブルという想定
class ItemDto:
def __init__(self, id_, name, price):
self.id = id
self.name = name
self.price = price
- RDBのテーブル構造に合わせたDTOにデータを保存し、データ保存処理に渡すという考え方
4. メリット
- データベース保存処理クラスでドメインモデルから必要なデータを取り出す処理を記述するより、データ登録に必要なデータのみパッケージされたオブジェクトを渡す方がデータ保存処理側の処理が簡単になる
- ドメインモデルそのものはドメインを表現したものとしてそのまま扱うことができる
5. デメリット
- モジュールの数が増える
- DBのテーブルの数が増えるごとにDTOの種類も増える(DTOにデータをパッキングする処理も増える)
6. 注意事項
DTOはJSONで代替可能
- DTOが考案された当時にはJSONは存在しなかった上、想定されていた言語もJavaだった為、DTOはクラスを前提として語られているが、現在においてはレイヤー間のデータのやりとりはJSONで行えば十分に目的も果たせる上、無用なモジュール数増加も起きない
- この点からDTOは現代的なプログラミング設計で検討に上るものではない
ActiveRecordが完全に代替している
- Ruby on Railsなどで採用さているActiveRecordをベースにしたO/RマッパーがDTOが必要とされた課題を完全に解決している
- この点からもDTOをあえて使う理由はない
オブジェクト指向プログラミングの観点からもよいものではない
- DTOのようなクラスはオブジェクト指向設計の中ではデータクラスとして忌み嫌われる存在である
- 何故なら、クラスが振る舞いを持たないということは本来クラスが持つデータに関する振る舞いが余所のクラスに流出していることを示し、カプセル化違反/単一責任違反などオブジェクト指向設計における逸脱が起きている可能性が高いからである
- したがって、(あえてDTOを採用するならば)DTOはあくまでDBへ永続化するためだけの限定利用に留めるべきである
参考資料