コード設計
UseCaseのエラーハンドリングについて
UseCaseの実装をしていると使う側でエラーの場合の処理を分けるという要件は割とラフに出てきます。
例えばレコードが見つからない場合は404、それ以外なら500のステータスにするなど。
そんな時にUseCaseでエラーを返却するときにメッセージやErrorを返却するだけでは実現するのが難しいです。
そこでどうすればUseCaseのエラーで処理を分岐できるのか考えてみました。
前提
今回の記事はTypeScriptでResult型が使えるneverthrowを使っています。
- TypeScript
- nevertthrowを使用
シンプルなUseCase実装例
例えばユーザーのidを引数にして、Repositoryからユーザーを取得するパターン。
もしユーザーが見つからない場合はneverthrowのerrorでメッセージを返却することで使用す る箇所からも参照することができます。
domain/user/usecases/GetUserUseCase.ts
1 2 3 4 5 6 7 8 9 10 11 12 13
import { ok, err } from 'neverthorw' class GetUserUseCase { async execute(userId) { const user = await this.userRepository.findById(userId) // userRepositoryはcontructorから注入にする想定 if (!user) { return err('User not found') } return ok(user) } }
この実装でいける場合もあるけど、困るパターンがエラーの種類によって使用する側で処理を変える必要がある場合です。
UseCaseからは別のメッセージを返却できるのでそのメッセージからどういうエラーか判定することは可能です。
でもメッセージは容易に変更されうる要素だし、メッセージを比較してエラー種別を判定するのもかなり微妙。
エラータイプを定義してメッセージと一緒に返却する
エラーメッセージだけでエラーの種別を判定するのが微妙となると、エラータイプを定義してメッセージと一緒に返却するのことで随分わかりやすくなります。
例えばこんな感じのエラータイプを定義。
domain/user/errors/UserErrorTypes.ts
1 2 3
export const UserErrorTypes = { UserNotFound: 'UserNotFound', }
UseCaseからは先に載せたerrの部分と違いメッセージとエラータイプのオブジェクトを返却するようにします。
domain/user/usecases/GetUserUseCase.ts