凪瀬 Blog
Programming SHOT BAR

目次

Blog 利用状況
  • 投稿数 - 260
  • 記事 - 0
  • コメント - 46991
  • トラックバック - 192
ニュース
広告
  • Java開発者募集中
  • 経歴不問
  • 腕に自信のある方
  • 富山市内
  • (株)凪瀬アーキテクツ
アクセサリ
  • あわせて読みたい
凪瀬悠輝(なぎせ ゆうき)
  • Java技術者
  • お茶好き。カクテル好き。
  • 所属は(株)凪瀬アーキテクツ
  • Twitter:@nagise

書庫

日記カテゴリ

 

どんなものにも例外はある…。そうこの命題にも。

冗談はさておき、本題です。だっちダッチさまが 例外処理のテストは厄介という 興味深い話をされております。
しかし、ちょっと不思議に思ったところがあったので突っ込ませてもらいましょう。

件のサンプルコードは

Dim sw As StreamWriter
Try
' ファイルに書き込む処理
Catch ex As IOException
' IOException 時の対策
Finally
sw.Close()
End Try

といったもので、任意の場所で例外をthrowするツールを利用してテストを行うとした場合、 Finally部分のClose()で例外がthrowされるケースをもらすのではないかという話でした。

件のサンプルコードはJavaで書くと以下のようになります。

byte[] buffer;
OutputStream out;
try {
  out.write(buffer);
catch (IOException e) {
  // IOException時の処理
finally {
  try {
    // ストリームの後始末
    out.close();
  catch (IOException e) {
    // 外のtry-catchのExceptionを生かすためにここでは敢えて握りつぶす
  }
}

finallyでclose()をするわけですが、close()メソッドがまたIOExceptionをthrowするため、try-catchが2重になります。
IOExceptionはチェック例外のため、try-catchで処理するか、 このコードが書かれているメソッドがさらに上にthrowするようにメソッドの宣言を記述するかしなくてはなりません。

Javaで一番使われているであろうIDEのEclipseには任意の場所で例外を発生させることが出来ます。 しかし、件のコードでfinallyのclose()時に例外が発生するケースは当然ながら入れ子のtry-catchとなっているため、 テストを漏らす事は考えにくいのです。

私の手元の環境には.NETの開発環境は入っていないのですが、VBはclose()で未チェック例外をthrowするのでしょうか?

問題外のケース

そもそもきっちりと正しい例外処理がされていない状況では、任意の場所で例外をthrowし、カバレッジを通そうとも潜在的にバグが残ります。

public void hoge() throws IOException {
  byte[] buffer;
  OutputStream out;
  try {
    out.write(buffer);
  finally {
    // ここで例外が発生すると本来の例外に成り代わって
    // close()時の例外がthrowされてしまう
    out.close();
  }
}

このあたりはtry-catchの落とし穴の部分であることは確かです。 きっちり例外処理を書くとかなりブロックの入れ子が深くなりますし、行数も多い。 しかも、普段は問題なく動くのだから適当な例外処理コードが書かれていても気づかないことが多いでしょう。

件のソースでカバレッジが通っていてもバグが検出できないのではないか?という疑問は そもそも例外処理が正しく行われているか?という問題に帰着するのではないでしょうか。 そして、そういった危ういコードはFindbugsなどのバグパターン検出ツールでサーチ&デストロイというのが 正しい対処ではないでしょうか。

投稿日時 : 2007年8月5日 22:39
コメント
  • # re: 例外処理ではあるけれど…
    シャノン
    Posted @ 2007/08/06 0:07
    ちょっと論点ズレてるかもしれないけど…

    > 外のtry-catchのExceptionを生かすためにここでは敢えて握りつぶす

    ということは、writeで例外が発生しなくて、closeで発生した場合は、それが検知できないということですよね。
    例外を握り潰したということは、トータルで見れば(リカバリ出来て結果オーライだった場合も含め)処理が正常に完了したということですよね。
    closeでファイルの内容を書き込む時に発生した例外を握り潰してしまうと、全体としてはファイルに正しく書き込めたということになると思いますが、実際にはデータ喪失が起きています。
    起きても問題ないというならば別ですが…

    そもそもが、「後始末処理では例外を発生させてはいけない」が鉄則のはず。
    なのにcloseが例外を投げ得るという、それがそもそもの問題点です。
    その原因は、パフォーマンス向上のためにライトキャッシュを使うという、業務仕様とは無縁のOSの都合です。
    ディスクやネットワーク等の外部I/Oが絡む場合、例外の予測はぐっと困難になります。

    この件で言えば、正常系の(tryブロックの)うちに明示的にflushしておけば、closeでの例外は握り潰せる…でしょう、か?
  • # re: 例外処理ではあるけれど…
    凪瀬
    Posted @ 2007/08/06 0:37
    なるほど、正常系で通過し、close()だけで例外がおきたケースですか。
    感知したところでやれることが何もないので気にしていませんでしたが、確かにその指摘はもっともです。

    flush()を呼ぶことで、バッファにあってまだ書き出しが出来ていないデータの書き損じが起こることは防げるでしょうが、このレベルの抽象概念で語れない可能性がありますね。もっと低いレベルでのI/Oを考慮に入れないといけないかもしれない。ファイルの書き終わりにフックしてOSが何かやっている可能性(たとえばタイムスタンプ)とか否定できないですし。

    問題が露呈したのは喜ぶべきことですから素直にこの問題に向き合おうと思います。
  • # re: 例外処理ではあるけれど…
    渋木宏明(ひどり)
    Posted @ 2007/08/06 1:06
    >VBはclose()で未チェック例外をthrowするのでしょうか?

    実は明文化されていません。

    Stream.Close() は virtual であり、どんな例外が起きるかは実装クラス依存です。

    にもかかわらず、FileStream.Close() 固有のヘルプトピックは MSDN Library には存在せず、FileStream クラスのメンバ一覧から Close() メソッドのヘルプを参照しようとすると Stream.Close() のヘルプページに飛ばされます。

    普通に考えると

    >そもそもが、「後始末処理では例外を発生させてはいけない」が鉄則のはず。

    であることが期待され、僕も比較的それをあてにしたコードをよく書きます。

    ですが、厳密に明文化された情報だけを頼りにコードを書くなら .NET でも2重に try ~ xxx で括るべきでしょう。(C# の場合 using があるので見かけ上 try ~ xxx を1段減らせますが)

    実際、.NET 1.x の頃の FileStream.Close() は例外を投げるケースがありました。(.NET 2.0 で修正されたようです)
  • # re: 例外処理ではあるけれど…
    シャノン
    Posted @ 2007/08/06 11:12
    .NETのヘルプトピックは、投げ得る例外に関してはまったく信頼できません。書いてないのが平気で飛んできます。
    しかし、Javaの検査例外を取り入れることはおそらくないでしょう。Java内でも異論はあるようですし。
    検査例外とまでは行かなくとも、投げ得る例外をメタデータ化してドキュメントを強制する仕組みは欲しいところです。

    …DLR上で動く動的言語になると、例外は今以上に不明確になってしまうのだろうか。
  • # 完璧な例外処理
    凪瀬 Blog
    Posted @ 2007/08/06 18:04
    完璧な例外処理
  • # re: 例外処理ではあるけれど…
    凪瀬
    Posted @ 2007/08/06 18:09
    >渋木さま

    .NETには疎いのですが、なるほど、そういう背景事情があるのですね。
    そうとなると元のエントリでの問題提起も「それって杞憂じゃないの?」とは言えない訳ですね。

    >シャノンさま
    書いてないのが平気でって…。
    例外の階層とかも関係なくなんですか?恐ろしい…。
  • # re: 例外処理ではあるけれど…
    渋木宏明(ひどり)
    Posted @ 2007/08/06 21:30
    >しかし、Javaの検査例外を取り入れることはおそらくないでしょう。

    でしょうねぇ。トップデザイナが嫌ってますからw

    「保護例外があれば100%安心」てモンでもない(そのくせ「おしつけがましい感が高い」)ので、僕も好きではありません。

    リフレクションや、I/O 系の抽象クラスを扱う場合、検査例外では明らかに不十分ですし。
  • # re: 例外処理ではあるけれど…
    凪瀬
    Posted @ 2007/08/06 22:02
    例外処理はまだまだ発展途上なのでしょうか。
    しかし、検査例外なしなんて、私の感性で言えば怖すぎる…。
    そりゃ、検査例外では不十分かもしれないけど、それすらないって戦々恐々ですけども。
  • # re: 例外処理ではあるけれど…
    大合院
    Posted @ 2008/03/01 21:47
    正直 close() が失敗してもファイルは正しく作成できると勘違いしていました。。。
    検査例外ですが、個人的にはあってもなくてもいいと思っています。
    大切なのは、チームが例外処理のルールを守ることだと思っています。
    どんなに素晴らしい例外機構や思想があっても、守られないケースがありますよね。。。
  • # Hello, i think that i saw you visited my web site thus i came to “return the favor”.I'm attempting to find things to enhance my site!I suppose its ok to use a few of your ideas!!
    Hello, i think that i saw you visited my web site
    Posted @ 2019/05/04 14:16
    Hello, i think that i saw you visited my web site thus i came to “return the favor”.I'm attempting to find things to enhance my site!I suppose its ok to use a few of your
    ideas!!
  • # Hello mates, how is all, and what you would like to say concerning this post, in my view its actually remarkable in favor of me.
    Hello mates, how is all, and what you would like t
    Posted @ 2019/05/08 16:58
    Hello mates, how is all, and what you would like to say concerning this post, in my view its actually remarkable in favor of me.
  • # At this moment I am going to do my breakfast, afterward having my breakfast coming over again to read further news.
    At this moment I am going to do my breakfast, afte
    Posted @ 2019/05/11 13:13
    At this moment I am going to do my breakfast, afterward having my breakfast coming over again to read further news.
  • # Hi there, the whole thing is going well here and ofcourse every one is sharing information, that's in fact good, keep up writing.
    Hi there, the whole thing is going well here and o
    Posted @ 2019/05/14 19:48
    Hi there, the whole thing is going well here and ofcourse every one is sharing information, that's in fact good, keep up writing.
  • # DovpOniWCOKxrDva
    https://docdro.id/3Beer8Q
    Posted @ 2021/07/03 1:44
    Major thankies for the article post.Much thanks again. Fantastic.
  • # pqZySEgezPdxIRSG
    https://amzn.to/365xyVY
    Posted @ 2021/07/03 3:12
    Really appreciate you sharing this article.Really looking forward to read more. Awesome.
  • # Superb, what a website it is! This webpage provides useful information to us, keep it up.
    Superb, what a website it is! This webpage provide
    Posted @ 2021/07/11 1:32
    Superb, what a website it is! This webpage provides useful information to us, keep it up.
タイトル
名前
Url
コメント