ざっくりForm/DTO/Entityの違い

新人教育用およびふとした時にわからなくなった場合用
Data Transfer Objectとかそういうのどうでもいいから他の人がどう使い分けているのか知りたい人向けです

# Form/DTO/Entityとはなんぞや
見た目は似ているが使い道が違う

## ざっくり言うと
最悪、これだけわかればOK
##### Form：ユーザーが入力する（した）値の入れ物
##### DTO：ユーザーが入力した値やDBから取得した値を、システム用に使いやすくしたもの
##### Entity：DBから取得した値やDBに保存する値の入れ物

## ざくざくっというと
わかんない言葉はググってね
 * 全部Java Bean（プライベートなメンバがあってGetter/Setterがあって…）
 * キホン的にFormはコントローラーでしか、EntityはDAO（または、DBと直接やりとりをするクラス）でしか使わない
 * 全部MVCモデルで言うとM


# 実際どのように使い分けているのか
 * Formは画面・コントローラーでしか、EntityはDAO（DBと直接やりとりをするクラス）でしか使わない
 * DTOはDAO以外いろんな場所に出現する
 * ユーザー入力がない場合（情報を表示するだけの画面とか）ならFormはいらない

以下、「フロント」って言葉がわかる人は「画面」を「フロント」に読み替えてください
## 「新規登録画面からの登録」の例

1. ユーザーが画面上の<font color="blue">Form</font>に情報を入力し、送信ボタンを押す
2. 画面が、<font color="blue">Form</font>に詰まった情報をコントローラーに送信する
3. コントローラーが、<font color="blue">Form</font>の内容をチェックして<font color="Orange">DTO</font>に変換する
4. コントローラーが、<font color="Orange">DTO</font>をサービスに渡す
5. サービスが、ロジックに基づいてあれやこれやした後<font color="Orange">DTO</font>を<font color="green">Entity</font>に変換する
6. サービスが、<font color="green">Entity</font>をDAO（DBと直接やりとりするクラス）に渡す
7. DAOが<font color="green">Entity</font>の情報をDBに渡す


## 「会員情報変更画面の表示」の例
1. DAOがDBから取得した情報を<font color="green">Entity</font>に詰める
2. DAOが<font color="green">Entity</font>を<font color="Orange">DTO</font>に変換してサービスに渡す
3. サービスがロジックにロジックに基づいてあれやこれやした後<font color="Orange">DTO</font>をコントローラーに渡す
4. コントローラーが<font color="Orange">DTO</font>の内容を<font color="blue">Form</font>に詰めて画面表示する
※4.の「DTOの内容をFormに詰める」はコントローラーじゃなくてHTMLでやる場合もある


## 「会員情報参照画面の表示」の例
1. DAOがDBから取得した情報を<font color="green">Entity</font>に詰める
2. DAOが<font color="green">Entity</font>を<font color="Orange">DTO</font>に変換してサービスに渡す
3. サービスがロジックにロジックに基づいてあれやこれやした後<font color="Orange">DTO</font>をコントローラーに渡す
4. コントローラーが<font color="Orange">DTO</font>の内容を面表示する
※「会員情報変更画面の表示」から「Formに詰める」がなくなっただけ。ユーザー入力がないからFormがいらなくなった。



# なんでわざわざ使い分けるの。ひとつでよくない？
**「ユーザーに入力してほしいデータ」「システムで使いたいデータ」「DBに保存したいデータ」が異なるからです**

逆に言えば
「ユーザーに入力してほしいデータ」「システムで使いたいデータ」「DBに保存したいデータ」が完全一致するシステムなら使い分ける必要はありません

が、その3つが一致することはほぼありません
（2つだけ一致することはまあまあある。とくに「システムで使いたいデータ」「DBに保存したいデータ」は同じ場合があるのでEntityをDTO代わりにしているシステムはよくある）

## FormとEntityの使い分け

「年」「月」「日」で入力するテキストボックスを分けている画面を想像してみる（よくありますね）

この場合

まずFormは『ユーザーに入力してもらう値』と一致させるため、birthYear, birthMonth, birthDateの3項目を用意します

birthYearは4桁の数字、birthMonthは12以下、birthDateは……とかいろいろチェックします

しかし、DBには「birthday」という1項目しかないとします

その場合EntityはDate型の「birthday」を定義する必要があります

これでまずFormとEntityは使い分けが必要であるとわかりました

## FormとDTOの使い分け

さきほど言った通りFormは「年」「月」「日」に分かれているためbirthYear, birthMonth, birthDateの3項目が必要です

でも実際システム的にはDate型のほうが使いやすいです。
Date型にすることによって「成人か？」などのチェックがやりやすくなるし、「YYYY年MM月DD日」を「YYYY/MM/DD」で表示することも容易です

なので入力値チェックが終わったらさっさとDate型に変換してサービスに渡しましょう
サービスにデータを渡すときにはDTOに変換するんでしたね

よってDTOでも生年月日はDate型の「birthday」を定義しましょう

これでFormとDTOも使い分けが必要であるとわかりました

## DTOとEntityの使い分け
生年月日に関して言えばDTOもEntityもDate型のbirthdayで一致するので、別の項目について考えましょう

例えばこのシステムが通販システムで、
登録してから3年以上経過＆年間100,000以上お買い物しているユーザーを「太客」と判定し
専用のキャンペーンに誘導したり送料が無料になったり割引が適用されたりするとします

さらに、DBの項目に「太客フラグ」は存在しないとします

専用のキャンペーンに誘導したい時、送料を計算する時、値段を計算する時
毎回DBを呼んで計算することもできますが、そのたびに通信するのは面倒ですよね[^1]

[^1]: 毎回DBを呼んで計算するほうが正確だとは思うので、本物の通販サイトなら毎回DB呼んでいるのかもしれません。もうちょっといい例えがあったら教えてください。

そんなときは最初の一回だけDBを呼んで登録日とお買い物金額を取得＆太客かどうかを判定し、
DTOに「太客フラグ」を設定しておきます

後はDTOの太客フラグを参照すれば毎回DBを呼ぶ必要はありません

太客フラグはユーザー入力値ではない＆改ざんされたら困るのでFormには設定しないし、DB項目にもないのでEntityにも設定しません
というわけでEntityともFormとも使い分けられます



### さらに言うと

#### 絶対改ざんされたくない情報はFormに定義しない
HTMLで\<input>タグに載せた情報は改ざんされる恐れがあります　type="hidden"にしてもダメです

しかしForm定義していない項目ならHTMLに書いたところで受け取れません

「それならForm定義だけしといてHTMLに書かなければよくない？」甘いな アナタがHTMLに載せなくても誰かがするかもしれないからだ
そもそもFormに定義されていなければ「なんでFormにないんだ？ 入力されちゃダメなのか？」って思ってくれる（かもしれない）


# おわりに

こんなに書いておいてなんだけど結構プロジェクトによって違ったりするから、実際にはプロジェクトのルールに従ってください


# 参考

https://qiita.com/mtanabe/items/c879d233d297eda288d4