- PR -

Try の中

投稿者投稿内容
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-03-06 20:01
まず、例外が THROW されないように、設計します。
それでも発生してしまう例外があります。つまり、本当に例外的な状況です。

THROW する側の考え方になります。
データを保持するクラスを作ります。「繰り返し回数」プロパティを例とします。繰り返し回数なので、負数はありえません。では、セットアクセッサの先頭で負数を弾くか?いえいえ、符号なし整数を使えばすみます。
例えば、10回以上繰り返しをしたくない。この様に、型で弾けない制約は、チェックメソッドを作ります。開発者がこのチェックメソッドで弾いてくれていることを前提に、セットアクセッサでは例外を送出します。


この様に、例外以外の方法で検査できるものは全て検査します。
ファイルを開にしても、ファイルがなければ例外が発生しますが、先に存在チェックをしていれば、発生させずにすみます。
しかし、他のプロセスが排他的に開いていると、存在しているが開けず、例外が発生します。これは、そういう状態がシステムとしてありえる状態かどうかで、受ける受けないを決めます。発生する可能性があるから受けるのではありません。
Azulean
大ベテラン
会議室デビュー日: 2008/01/04
投稿数: 123
お住まい・勤務地: 大阪府
投稿日時: 2008-03-06 23:58
#本筋に入っていない突っ込みで申し訳ない。

引用:

indigo-xさんの書き込み (2008-03-06 10:24) より:
標準的なアプローチはApplicationException辺りを継承して

識別する例外を作ります。(引数も作ればさらに詳細も入れれます)


確かに.NET Framework 2.0が出た当時はそうだったようです。
http://msdn2.microsoft.com/ja-jp/library/system.applicationexception(VS.80).aspx

しかし、最近はExceptionクラスから派生させることが推奨されています。
http://msdn2.microsoft.com/ja-jp/library/system.applicationexception(VS.85).aspx
引用:

アプリケーションを設計するときに固有の例外の作成を必要とする場合は、カスタム例外を Exception クラスから派生させることをお勧めします。当初は、カスタム例外を ApplicationException クラスから派生させる必要があると考えられていましたが、実際にはあまり有用ではありませんでした。詳細については、「例外処理の実施」を参照してください。

よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2008-03-07 00:59
細かい突っ込みばっかりで恐縮ですが。

引用:

Jittaさんの書き込み (2008-03-06 20:01) より:
ファイルを開にしても、ファイルがなければ例外が発生しますが、先に存在チェックをしていれば、発生させずにすみます。



Jittaさんはわかった上で敢えて書いてらっしゃると思いますが、念のため。
先に存在チェックしていても、チェックからファイルを開く間にそのファイルが削除されれば、例外が発生する可能性はありますね。
ファイルを開く処理に関して言えば、開けなかった場合の対応として
ユーザーがリトライできるようにするなどの配慮が必要だと思います。

さらに細かい突っ込みですが、
引用:

Azuleanさんの書き込み (2008-03-06 23:58) より:
#本筋に入っていない突っ込みで申し訳ない。

引用:

indigo-xさんの書き込み (2008-03-06 10:24) より:
標準的なアプローチはApplicationException辺りを継承して

識別する例外を作ります。(引数も作ればさらに詳細も入れれます)


確かに.NET Framework 2.0が出た当時はそうだったようです。
http://msdn2.microsoft.com/ja-jp/library/system.applicationexception(VS.80).aspx



そのドキュメントは.NET Framework2.0以前からの記述がそのままなだけだと思います。
アプリケーションで規定する例外は本来はApplictionExecptionクラスから派生させる
予定だったと思われますが、.NET Frameworkクラス内部で間違ってApplicationExceptiopnクラスから派生をしているクラスがあるため、
実質使い物にならなくなっています。

この辺とか。
http://msdn2.microsoft.com/ja-jp/library/kw9wwk34(VS.80).aspx

この点については、書籍の「プログラミングMicrosoft .NET Framework」で言及されています。
Azulean
大ベテラン
会議室デビュー日: 2008/01/04
投稿数: 123
お住まい・勤務地: 大阪府
投稿日時: 2008-03-07 07:40
引用:

そのドキュメントは.NET Framework2.0以前からの記述がそのままなだけだと思います。
アプリケーションで規定する例外は本来はApplictionExecptionクラスから派生させる
予定だったと思われますが、.NET Frameworkクラス内部で間違ってApplicationExceptiopnクラスから派生をしているクラスがあるため、
実質使い物にならなくなっています。


情報ありがとうございます。
VS 8.0のバージョンのドキュメントを呼び出したときに記述が異なったのであのように判断していました。

しかし、ApplicationExceptionから派生しているクラスがあるんですね…。
indigo-x
大ベテラン
会議室デビュー日: 2008/02/21
投稿数: 207
お住まい・勤務地: 太陽の塔近く
投稿日時: 2008-03-07 07:47
Azuleanさん、よねKENさん

そうなんですか 、知らなかったです。

私ラッキーにも、いつも、層毎に層BaseExceptionを挟んでいたのでよかったです。
(でもなおしとこ)

コード:
public DB層BaseException : ApplicationException
{
}

public DBキー重複Exception : DB層BaseException 
{
}



(こそっとApplicationExceptionをExceptionを書き換えます
ugaya
会議室デビュー日: 2006/08/03
投稿数: 18
投稿日時: 2008-03-07 09:21
あくまでも指針の話をします。
Jittaさんが繰り返し指摘されている通り、元来例外はスローするべきではないし、Try〜Catchが頻繁にコード上に現れるのも適当ではないです。
javaの様に検査例外の考え方がない.netではシステム例外と業務例外を区別して表現する例外を持ちません。
.netの例外は常に非常にコストが高いものとして表現されます。

その上での話しですが、Throwで止まるとはどういうことでしょうか?
例外がスローされ、ハンドリングされていないためクラッシュしていると言う事でしょうか?

ThreadExceptionのイベントハンドラに処理コードを記述しておけばクラッシュは普通ありえません。
ThreadExceptionのイベント処理を行うということ、は乱暴な表現ではありますが一番上のレイヤでコード全体をTry〜Cactchで囲んでいるようなものです。

ログの話ですが、エンドユーザーにどのメソッドで例外が発生しているかを見せる必要は普通ありません。
ユーザーに判りやすいメッセージを表示させると同時に障害解析用に例外情報を記録すればよいのです。
それはログファイルかもしれませんし、イベントログかもしれません。
ですのでログメソッドは一概に表現できません。

LANVINさんのコードはSqlExceptionをcatchされていますが、これはどういう状況で発生すること想定したものでしょうか?
何度も繰り返していますが、業務フロー上想定される異常系は引数を増やしてでも戻り値として表現するのが指針です。トランザクション制御が不適切であったり、LANケーブルが抜けていたりする状態をシステム的に考慮するならばSqlExceptionをcatchし、戻り値として上位のメソッドに返します。
業務フロー上想定外のものであるならこのレイヤでcatchする必要はありません。なにせ想定されていないのだから一番上のレイヤで汎用的に不明なエラーとして処理すれば澄むことです。

Jittaさんのお話でもありますが、ファイルの読み書き時の話は要件によって判断がわかれます。
ユーザーが対象ファイルの読み書きを想定しているなら、ファイル読み書き時の例外をcatchし、業務例外として戻り値で表現するべきですが、ユーザーが触らない前提のファイルなら業務フロー上異常系はありえないのでcatchしません。

すべてのTry〜Catchをなくすかどうかは指針に従った上でも要件しだいです。
指針に従った場合は運用設計なども含めて想定される異常系、想定されない異常系をきちんと区別していないと正しく実装はできません。

ただ仕事ですので、現場によっては設計者がJavaしかやったことがない人で設計書にすでに異常系処理の指針が記述されており、なおかつ上位の設計書に遡及できない状況だったりして実装フェーズで入れ子のTry〜Catchを書かなければならなかったりしなければならないこともないとは言い切れません。
その場合は仕方ない・・・ですね。
後で苦労するだけです。
よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2008-03-07 10:31
ごめんなさい。以下のツッコミはこのスレの文脈を考えるとズレたツッコミでした。

引用:

よねKENさんの書き込み (2008-03-07 00:59) より:
細かい突っ込みばっかりで恐縮ですが。

引用:

Jittaさんの書き込み (2008-03-06 20:01) より:
ファイルを開にしても、ファイルがなければ例外が発生しますが、先に存在チェックをしていれば、発生させずにすみます。



Jittaさんはわかった上で敢えて書いてらっしゃると思いますが、念のため。
先に存在チェックしていても、チェックからファイルを開く間にそのファイルが削除されれば、例外が発生する可能性はありますね。
ファイルを開く処理に関して言えば、開けなかった場合の対応として
ユーザーがリトライできるようにするなどの配慮が必要だと思います。



ファイルという言葉だけに反応してしまいましたが、
このスレで例として挙がりそうなのはINIファイルの読み込み処理でしょうから、
システム都合で用意しているファイルが削除された、といったような場合では、
ユーザはリトライできないので、想定外のエラーとしての扱いでよいですね。
的外れな指摘で申し訳ないです。

以下のugayaさんのフォローで気づきました。ありがとうございます。

引用:

ugayaさんの書き込み (2008-03-07 09:21) より:
Jittaさんのお話でもありますが、ファイルの読み書き時の話は要件によって判断がわかれます。
ユーザーが対象ファイルの読み書きを想定しているなら、ファイル読み書き時の例外をcatchし、業務例外として戻り値で表現するべきですが、ユーザーが触らない前提のファイルなら業務フロー上異常系はありえないのでcatchしません。

ugaya
会議室デビュー日: 2006/08/03
投稿数: 18
投稿日時: 2008-03-07 18:15
いえいえ普通、よねKENさんのおっしゃる通りだと思っています。

LANVINさん、追記です。
どこかでも書きましたが例外でお悩みなら、

.NETエンタープライズWebアプリケーション 開発技術大全vol3
(@itの記事に一部抜粋があります。)
http://www.atmarkit.co.jp/fdotnet/entwebapp/index/index.html

の4.4例外処理を立ち読みでもなんでもされた方が良いと思います。
例外処理についての設計指針とその実装について50ページ近く費やされています。
読めば指針については一発で理解されるのではないかと思います。
書名にはWebアプリケーションとかいてありますが、例外処理については汎用的に説明されています。

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