今回学んだこと
・orElseThrowによるエラーページのリファクタリング
・Contorollerクラスからのデータの所得
・その他のリファクタリング
リファクタリング前後のコードの変化
- リファクタリング前
- リファクタリング後
- リファクタリング前(主な動作)
- リファクタリング後
- 重要なパターン
@GetMapping("/{id}/editForm")
public String showEditForm(@PathVariable("id") long id, Model model) {
var taskEntity = taskService.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Task not found"));
var form = new TaskForm(taskEntity.summary(), taskEntity.description(), taskEntity.status().name());
model.addAttribute("taskForm", form);
return "tasks/form";
}
@GetMapping("/{id}/editForm")
public String showEditForm(@PathVariable("id") long id, Model model) {
var form = taskService.findById(id)
.map(TaskForm::fromEntity)
.orElseThrow(TaskNotFoundException::new);
model.addAttribute("taskForm", form);
return "tasks/form";
}
解説
前提としてContorolerクラスは見やすくわかりやすく書く,意識として↓
理由 | 内容 |
---|---|
💡 役割が限られているから | 接続役としてだけに専念するべき |
🧹 責任を分けたいから | サービスやリポジトリと分業 |
🔧 メンテしやすいから | 見通しが良くなり、バグも見つけやすい |
🔁 変更に強いから | 他の層に影響を与えずに変更できる |
まず@GetMapping("/{id}/editForm")でurlが指定された時にGetするメソッドとして定義する。
まず@GetMapping("/{id}/editForm")でurlが指定された時にGetするメソッドとして定義する。
editFormを作るためのメソッドなのでString型のshowEditFormとして@PathVariableを使ってurlのidを変数として受け取り、さらにmodelでビューに返す(Tymeleafを使用しているのでJsonで返すときは別)
リファクタリング前でtaskEntityを定義してサービスクラスのfindByIdを呼び出しDBからidを所得している
.orElseThrow(() -> new IllegalArgumentException("Task not found")でOptional型が返された時にidが違った場合、Task not foundを返す文である。
model.addAtributeで"taskForm"がビュー側で呼び出された場合formというDBにアクセスしたいのでtaskEntityからデータを取り出し画面表示用のTaskFormをnewしている
主な変化として定義する変数をformひとつにし、.mapを使うことで可読性が高い文章になっている
.map(TaskForm::fromEntity)の役割としてTaskEntity → TaskForm に変換する 静的メソッド(static method) である。リファクタリング前のTaskFormに書いてあった引数をTaskFormの性的メソッドの中にTaskForm fromEntityと定義することで簡潔に書いている。
.orElseThrowの中はTaskNotFoundExseptionという例外クラスを作ることで簡潔に書いている
外伝:例外クラス
@ResponseStatus(HttpStatus.NOT_FOUND)
public class TaskNotFoundException extends RuntimeException{
}
・@ResponseStatus(HttpStatus.NOT_FOUND) → この例外が発生したときに HTTPステータスコード「404」 を返すように指示してる
・extends RuntimeException
→ チェックされない例外(Unchecked Exception) として扱うことで、throws 書かなくてOK
まとめ
それぞれの役割ごとにクラスを分けて書くことでエラーに対処しやすくなり可読性が高いプログラムになることが理解できた。tymeleafを使うか使わないかで大きな差が出るが3層アーキテクチャの考え方は重要であることがわかった。なるべく変数は少なくコードは短く!!
(文字多くてごめんね)