今でもこの記事にコメントを頂くことがあり大変有難いのですが、実は、現在はまたもや異なる見解、というか捉え方をしています。(何度もすみません…)
といっても、「業務エラーは戻り値で表すべき」という考えになったというわけではありません。
以前は業務エラーは「戻り値」で表すべきか「例外」で表すべきかについて悩んでいましたが、今の僕は、そもそも業務エラーを表すのはこのどちらでもないと考えています。
まず、
- 戻り値は、メソッドが結果を返すためのものです
- 例外は、メソッドが例外的事象を通知するためのものです
そして、これが全てです。
戻り値も例外も、業務エラーを表すためのものではないのです。
これだけじゃイマイチ伝わらないかもしれませんね。
ではここから、ドメイン駆動設計 (DDD) という設計思想を例に取ってみます。
書籍「ドメイン駆動」によると、DDD プロジェクトの典型的なレイヤ分割では、次の 4 つのレイヤに分割されるとしています。(直接的にはあまり深く語られていないので、以下は僕なりの解釈です。)
[ User Interface レイヤ ]
その名の通り UI に関するレイヤです。MVC における View に相当します。
テキストボックスの入力値を取得したり設定したり、ラベルの表示・非表示を切り替えたり、といった直接的な UI 操作のみを行います。
[ Application レイヤ ]
アプリケーションとしての動作に関するレイヤです。MVC における Controller に相当します。
User Interface レイヤ、Domain レイヤ、Infrastructure レイヤを操作します。アプリケーションとしての中核を担います。
例えば、図書館の貸出管理システムにおいて、貸出画面で複数の図書を一度に貸出できるようにするのか、一冊ずつしか貸出できないようにするのかは、アプリケーションの仕様に左右されます。一度に複数の貸出ができるようにするために、図書オブジェクトを一時的にコレクションに格納するといったロジックは、「アプリケーションとしての動作」のためのものです。(*1)
[ Domain レイヤ ]
ドメインモデルに関するレイヤです。MVC における Model に相当します。
例えば、貸出期限や貸出可能図書数などは図書館の貸出規定として決められていることです。貸出可能図書数を超えてしまう場合は貸出できないようにするといったロジックは、アプリケーションとしての動作とは無関係なドメインロジック (ビジネスロジック) です。
[ Infrastructure レイヤ ]
データアクセスや周辺機器の制御などに関するレイヤです。
DDD において、業務エラーを表すのは Application レイヤだと僕は考えます。なぜなら、業務エラーは「アプリケーションとしての動作」の一種だからです。
Application レイヤが色々な手段で「業務エラーにすべき状況の検出」をし、「業務エラーとしてユーザーに通知」するわけです。
業務エラーにすべき状況を検出する手段には、例えば次のような手段があります。(*2)
- UI への入力値の妥当性を検証しその結果を見て検出
- ドメインモデルの検証用メソッドを実行した結果を見て検出
- ドメインモデルの状態プロパティを見て検出
- ドメインモデルのメソッドを実行した結果例外が発生するかを見て検出
- データアクセス時に例外が発生するかを見て検出
繰り返しますが、これらはあくまでも検出するための手段 (*3) であり、業務エラーそのものではありません。
業務エラーの検出後は、User Interface レイヤに対して、業務エラーをユーザーに通知するように指示を出します。この指示はメソッド呼び出し等 (*4) で行います。
ということで、最初に書きました通り、例外も戻り値も業務エラーを表すために使うものではないと主張します。特に、「本来例外を投げるべきところ」で「業務エラーは戻り値で表さなきゃいけないから戻り値にする」という考えには賛同できません。
今回、例として DDD を選びましたが、必ず DDD を適用しろとか、必ず Application レイヤで業務エラーを表せと言っているわけではありませんので注意してください。
また、ここで僕が述べたことは、他の設計思想においても当てはまるかもしれませんし、当てはまらないかもしれません。
*1:これは場合によっては Domain レイヤで行った方が適切だったりするかもですが、良い例が浮かばなかったので…
*2:これは決してボトムアップ設計を示唆しているわけではありません。
*3:"検出" を "選定" と置き換えた方が伝わりやすいかもしれませんね。
*4:まだ触ったことないですが ASP.NET MVC なら ViewData プロパティを使用するんですかね。
トラックバックURL↓
http://csharper.blog57.fc2.com/tb.php/236-a6c38b6f