- PR -

C# 戻り値の型を動的に変更することは可能ですか?

投稿者投稿内容
nanbu
大ベテラン
会議室デビュー日: 2004/08/19
投稿数: 178
投稿日時: 2005-05-08 22:14
南部です。

引用:

ずっと気になっていたんですが「業務エラー」とは何なのでしょうか。業務エラー以外には、どのようなエラーがあるのでしょうか。nanbu さんが考えているエラーの種類を列挙していただいて分類していただけると、私にも理解できるかもしれないです。


例外と業務エラーの分類は
・業務エラー
 業務設計で想定されている範囲で処理が分岐する正常終了でないケース。
 ⇒戻り値として表現

・アプリケーション/システムエラー
 業務設計で想定しない異常のため正常終了できないケース
 ⇒例外で表現

ですが、じゃ、どこから「想定しない異常」なの?というのは、
私の中でも明確ではなく感覚です。
恐らく、Jittaさんや未記入さんは、
システムエラー的なことまで、「想定」してしまうでしょう。

引用:

私は「入力欄の文字がすべて数値で構成されている」とか「文字列がメールアドレスの書式を満たしている」などの検査ロジックは、業務依存性が低く「業務エラー」とやらには該当しないと勝手に思い込んでいたんですが…。どうやら違うっぽい。


メールアドレスを入力させる業務フローがあった場合、
入力者が書式を間違えたり、別の入力項目と勘違いしたりして不正な値が、
入力されることは想定されることであり、それが起こった時、どのような
フローにするのか想定・設計するので、業務エラーです。

引用:

引用:
業務エラーであるとした場合、業務エラーを表現するために「例外」を使用しませんので


では、どのようなエラーを表現する場合に「例外」の使用が適切なのでしょうか。前に、「アプリケーションエラー」「システムエラー」という言葉が出てきていますが、私はこれらを、かなり致命的な障害(Java の Error 相当)でキャッチすべきではない(==フローへの復帰が困難な)ものと認識していました。この認識がそもそも間違っているのかな?


「フローへの復帰が困難なもの」という認識で間違いないと思いますが、
「かなり致命的な障害(JavaのError)」だけではなく、
「業務設計上想定されていない例外(JavaのRuntimeException)」も含まれています。
(NullPointerExceptionからの業務フロー復帰、、設計しませんよね)

引用:

引用:
それとも、クラスライブラリとしてパラメータ引数が有効であることをチェックしたときのアプリケーションエラーでしょうか。


この文脈からすると、アプリケーションエラーはそれほど致命的な状態をあらわすものではないような気もしてきます。


いえ、Goodsクラスの内部状態が不正になることは、
Goodsクラス本人(?)からしてみれば致命的です(いいすぎかも)。

引用:

引用:
クラスライブラリとしてのパラメータチェックであれば、呼び出しメソッド側(クラスライブラリを使用するビジネスメソッド)で、範囲外例外を業務エラーとして切り替えることで実現します。


なぜ、わざわざ水際で例外をキャッチして、戻り値方式などに切り替える必要があるのでしょうか。例外をキャッチできるということはプログラマが例外がスローされることを理解しているのだから、(チェック例外でなくても)正しく扱えそうな気がしますが…。そもそも常に水際で例外をキャッチして戻り値方式に切り替えるくらいなら、汎用ライブラリ自体が例外を投げずに戻り値方式を採用していたほうが良くないですか? なぜ、標準ライブラリは例外を投げているのでしょうか?


クラスライブラリが例外を投げるのは、以前、未記入さんも記述していましたが、
次の利点があるためでしょう(本当のところわかりません)。
--- MSDNより抜粋 --
リターン コードなどの他のエラー通知方法に比べ、例外を使用したエラー通知方法には多くの利点があります。エラーは必ず通知されます。エラー発生後に無効な値がシステム内に反映されません。リターン コードを確認する必要がありません。例外処理コードを簡単に追加でき、これによりプログラムの信頼性が向上します。ランタイムでの例外処理は、Windows ベースの C++ 例外処理よりも高速です。
-------------------
しかし.NETの例外は、Javaの検査例外のように呼び出し元に対し業務フローの分岐を強制させる、つまり、「この例外をスローするから、適切な業務エラールートに進んでね。」みたいなことはできませんので、「例外」は業務フローから出るときに使用し、業務ルートの分岐には戻り値を使用する、つまり、「例外」が起きない限り、業務フロー内であるというデザインなのです。

引用:

引用:
私は、モデルの意味合いが強そうなGoodsクラスは業務フローから切り離したいと考えますので、後者を選択します。


モデルとは何ですか? MVC のモデルですか? MVC のモデルだとした場合・・・モデルは業務フローから切り離したいと考える理由はなんでしょうか? 私は MVC に関係なく Goods と命名されたクラスは業務依存性が高そうなので、業務フロー(設計)と密接な位置に置いておくほうがいいかな、と思いました。

また、ここで後者(アプリケーションエラー?)を選択すると「例外の使用が正当化される」というのも良く分かりません。


GoodsクラスのDiscountRateプロパティを「割引率を設定する」という
業務フローに依存し、SetDiscountRateメソッドにすることが
「しっくりこなかった」ためです。
例えば、Goodsを一括登録するためCSVからデータを読み込むWindowsアプリケーションを
作成した場合、
CostPrise = XXX;
Prise = XXX;
SetDiscountRate(XXX); //ええ!?なんでメソッドなの?
すみません、くだらない理由で、、、
モデル内に業務フローに依存したメソッドがあることで、
混乱するような気がしただけです。

また、「例外の使用が正当化される」というか、
Goodsクラスは不正な値が設定されることが業務エラーかどうか
意識しない、でも不正であることは必ず通知したいということです。

nanbu
大ベテラン
会議室デビュー日: 2004/08/19
投稿数: 178
投稿日時: 2005-05-08 22:41
引用:

noderaさんの書き込み (2005-05-08 19:27) より:
こんにちは。

南部さんが使う言葉がちょっとあいまい(言葉の定義において南部さんの認識と他者の認識が一致していない)なんで誤解を招いているのだと思いますよ。自分も業務フローや業務エラー、ビジネスメソッドという言葉がどの辺りを指しているのか、何度も読み返してなんとなく判ってきたところです。



引用:

自分も南部さんにひとつたずねたいのですが、「CLRのデザインルール」ってのは具体的のどのドキュメントのどの部分を指しているのでしょうか?それを読めば、南部さんの言わんとしていることがもうちょっと理解できるかな。
ちなみにburton999さんが最初に貼り付けたリンク先には、「.NET の世界ではエラー処理が "エラー コード" を使用するスタイルから、 例外を使用するスタイルに移行している」と書いてあります。


本当に申し訳ないと思っております。
(きっと、以前の自分の投稿見たら、何言ってるんだろうって思うんだろうな、、)
これは、
.NET エンタープライズ Webアプリケーション開発技術大全Vol.3
の4.4例外処理に記述されています。

未記入
ぬし
会議室デビュー日: 2004/09/17
投稿数: 667
投稿日時: 2005-05-08 23:14
引用:
.NETの例外は、Javaの検査例外のように呼び出し元に対し業務フローの分岐を強制させる(中略)ことはできませんので、「例外」は業務フローから出るときに使用し、業務ルートの分岐には戻り値を使用する


話が最初のところに戻ってしまうんですが、例外のキャッチが強制されないという技術的な制約があると「例外の使用を控えるべき」となってしまうのはナゼでしょうか。

そもそも、Platform SDK では、リファレンスが手元にないと正常なフローを維持することなんてできないですよね。正常終了は ERROR_SUCCESS だっけ? それとも 0 以外の値が正常値だったかな? いや -1 以外は正常のはず・・・。ってな感じになるわけで。私は Platform SDK でプログラムを組むときは常にリファレンス(オンラインですが)を手元に置き慎重に if文を記述して、正常なフローを維持することに腐心していました。

結局のところ、戻り値方式であってもリファレンスがないと正常なフローを維持するのは困難なわけですから「発生する例外が(リファレンスを確認しないと)分からない」というのは、(戻り値方式に比べて)使用を控える積極的な理由にはならないと思うのです。いままでの話の流れでは「Java と違って使いにくいから・・・」という意見が多かったですが、本当に比較すべきは Java ではなく従来の戻り値方式ですよね。で、リファレンスの確認を必要とする点では戻り値方式も例外も同じなんじゃないかとふと気づいたわけです。

どうでしょう? 私はリファレンス必須でも例外を積極的に使っていくメリットは大きいと思うのですが。
nanbu
大ベテラン
会議室デビュー日: 2004/08/19
投稿数: 178
投稿日時: 2005-05-09 07:48
引用:

Jittaさんの書き込み (2005-05-08 21:43) より:
 想定されている例外が「業務エラー」なら、たとえば数値を入力するところで、「ここには『数値を表すラベル』を付けているのだから、数値以外の入力はない」と思いこんでいれば、想定されない例外が発生します。そして、プログラミング初心者は、そういうコーディングをよくするでしょう。
 しかし、「どんなリードの仕方をしても、ユーザは何を入力するかわからない」という前提に立てば、想定された例外が発生します。
 とすると、設計者やコーディング者の経験や知識によって、変わるのでしょうか。


南部です。

そうですね。
設計者やコーディング者の経験や知識によって変わると思います。
Javaでも初心者のコードでは
public void login(引数)throws Exception
のようなインターフェースを見かけます(かわいいでしょ)。

引用:

未記入さんの書き込み (2005-05-08 23:14) より:

話が最初のところに戻ってしまうんですが、例外のキャッチが強制されないという技術的な制約があると「例外の使用を控えるべき」となってしまうのはナゼでしょうか。
(略)
どうでしょう? 私はリファレンス必須でも例外を積極的に使っていくメリットは大きいと思うのですが。



そうですね。
折角、ApplicationExceptionとかありますし、、ね。
コーディングのスタンダードは変化していくかもしれませんね。

でも、業務フローの制御のために、try〜catchを「きざむ」コードは
あまりみたくないよーな、、、
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2005-05-09 22:50
引用:

nanbuさんの書き込み(2005-05-09 07:48)より:

そうですね。
設計者やコーディング者の経験や知識によって変わると思います。


 だとすると、ルールやデザインガイドとしては不適切ではないでしょうか。いろんな経験をした人はたくさんの検査メソッドを置く、初めての人はシステムが生成する例外だけで対応しようとする(まさに‘かわいい’状態)。。。同じプロジェクトに2人が携わると、コードに差が出ます。2人が別個のクラスライブラリを設計すれば、混乱するのは使用者です。
(そういう人の配置をするのが問題、というのは、ひとまず置いておく)

 そうではなく、経験に左右されずに同じような設計/コーディングができるように策定されたのがガイドラインであり、ルールではないでしょうか。だとすると、どこまでを「想定の範囲」とするか、明確にする必要があると思います。

 結局、私が落としどころを見つけられなかったのはこの問題なのかもしれない。「範囲が明確にできないなら、全部例外にしてやれ」ってことです(^o^;

_________________
nodera
大ベテラン
会議室デビュー日: 2003/09/08
投稿数: 200
投稿日時: 2005-05-10 10:38
こんにちは。

引用:

nanbuさんの書き込み (2005-05-08 22:14) より:

例外と業務エラーの分類は
・業務エラー
 業務設計で想定されている範囲で処理が分岐する正常終了でないケース。
 ⇒戻り値として表現

・アプリケーション/システムエラー
 業務設計で想定しない異常のため正常終了できないケース
 ⇒例外で表現



ここは自分の考えとは違うところです。
「例外」=「エラー」と考えて無いでしょうか?例外をエラー(業務エラーでもシステムエラーでも)かどうか判断するのは、呼び出す側であって、呼び出される側(スローする側)では無いと思います。

呼び出された処理は与えられた条件により、ある暗黙の前提(型や引数の範囲等)にしたがって処理を行います。例外をスローするということは、呼び出し側に対し、前提に違反しているということを通知することであり、呼び出された処理にとってはエラーではなく、予定された処理の一部なのです。

なので、呼び出される側が「エラーを通知しよう」という意識にたって結果コード(あえてエラーコードといわない)や、例外を取り扱うのはおかしいかなと思います。
nanbu
大ベテラン
会議室デビュー日: 2004/08/19
投稿数: 178
投稿日時: 2005-05-10 11:01
引用:

Jittaさんの書き込み (2005-05-09 22:50) より:

 そうではなく、経験に左右されずに同じような設計/コーディングができるように策定されたのがガイドラインであり、ルールではないでしょうか。だとすると、どこまでを「想定の範囲」とするか、明確にする必要があると思います。


「想定の範囲」は結局アプリケーションに依存するためでしょう。
データベースを使用するWebアプリケーションの業務フローでの
「データベースに接続できない」と
データベースを監視するアプリケーションでの
「データベースに接続できない」は違います。

ガイドライン・ルールは、確かにアプリケーションの品質を確保するために
必要なものでしょう。しかし、それだけでは高い品質とは言えないでしょう。

#経験に左右されずに同じような設計/コーディングができる、、、
#これだと、私の給料は上がりません。
nanbu
大ベテラン
会議室デビュー日: 2004/08/19
投稿数: 178
投稿日時: 2005-05-10 12:33
南部です。

私から見ると、noderaさんの意見の私の意見は、そんなに違っていると
感じないのですが、、、、

引用:

noderaさんの書き込み (2005-05-10 10:38) より:
こんにちは。

引用:

nanbuさんの書き込み (2005-05-08 22:14) より:

例外と業務エラーの分類は
・業務エラー
 業務設計で想定されている範囲で処理が分岐する正常終了でないケース。
 ⇒戻り値として表現

・アプリケーション/システムエラー
 業務設計で想定しない異常のため正常終了できないケース
 ⇒例外で表現



ここは自分の考えとは違うところです。
「例外」=「エラー」と考えて無いでしょうか?例外をエラー(業務エラーでもシステムエラーでも)かどうか判断するのは、呼び出す側であって、呼び出される側(スローする側)では無いと思います。


例外=アプリケーション・システムエラー
と定義しています。

そして、例外を業務エラー、業務エラーを例外に切り替えることは、
呼び出す側、呼び出される側というより、切り替える責任を持つところで行います。
(後者はあまりないかも知れませんが)
例外を業務エラーに切り替えるということは、例えばクラスライブリラリを使用した場合に
スローされた「例外」が「想定された範囲」にある場合で、かつ、正常に終了できない
場合に、ビジネスフローに対して「エラールート」に進んでほしいことを通知します。
そしてこのメソッドは、ビジネスフローから「呼び出される」メソッドで、クラスライブラリを
「呼び出す」メソッドです。

引用:

呼び出された処理は与えられた条件により、ある暗黙の前提(型や引数の範囲等)にしたがって処理を行います。例外をスローするということは、呼び出し側に対し、前提に違反しているということを通知することであり、呼び出された処理にとってはエラーではなく、予定された処理の一部なのです。


はい、クラスライブラリにおけるパラメータ引数のチェック時の例外とかですね。

引用:

なので、呼び出される側が「エラーを通知しよう」という意識にたって結果コード(あえてエラーコードといわない)や、例外を取り扱うのはおかしいかなと思います。


呼び出される側が、業務的責任がない(というか業務エラーを想定すべきではない)場合、
呼び出される側は、自分の責任範囲で「例外」をスローすればよいと思います。

スキルアップ/キャリアアップ(JOB@IT)