トップ «前の日記(2006-07-17) 最新 次の日記(2006-07-19)» 編集

jFD開発したりしなかったり日誌

2004|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|
2006年
7月
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31

2006-07-18 [長年日記]

_ 新ソフトアイディア

日曜の真夜中、やっと終わった作業結果をメールで送信した。

既に終電も行っちゃって帰れないし、ゲームで遊んだりして時間を潰してたが、

ふとひらめいた。

メールの送信のタイマー予約が出来るソフト欲しいかも。

大変さをアピールするために、午前2時半とかにメールを送信するように

設定して18時半に家帰るとか。

ただし、その18時半から2時半の間に状況が変化して、つじつまが合わなくなったら

困るので、メール経由で送信中止が指示できるようになってるとなお良し。

ソフト名はアリバイメール。

誰か作ってそうだなあ。

_ 遠方に想いを馳せる

言い換えると現実逃避中。

このプロジェクトが終わったら、夏休み+代休でどこか遠くに行く。

今年は北海道に行きたかったが、休みが取れる頃には夏が終わって寒くなってしまう。

九州か四国か。

東北も悪くないか。

Chokujin師匠に会いにいく旅とか。

_ 例外処理のコツ

Javaの例外処理について。

どーもわかってない人が多いのでまとめておく。

まず、やっちゃいけないことから。

_ 1,catchの中が空

これをやったら今すぐ自分の首を絞めて死んでください。

さあ遠慮無く。

catchの中が空ということは、例外が発生してもすべての情報を

握りつぶして何事もなかったように動作を継続する、ということです。

一見ちゃんと動いているようで、実は内部的には洒落にならない

不整合を起こしていて、さらにどこで問題が起こってるか不明、

という最悪な状況になります。

問題が発生してるのに動いてるのは、問題が発生して落ちるよりも

悪い状況というのを理解してください。

ただし、本当に例外が起きても起こらなくてもよいシチュエーション

(後処理とか)ではこの限りではありません。

_ 2,例外が起こる処理を一つずつtry〜catchで囲む

読みにくいっての。

まとめて大きく囲ってください。

_ 3,後処理をtryやcatchの中に書く

例えばストリームを開いて何らかの処理を行う場合、後処理でストリームを閉じる

必要があります。

ストリームの処理はIOExceptionが投げられる可能性がありますが、

そうなると処理が分岐するので、すべての分岐の最後に後処理を書いてくれる人が

未だにたまにいます。

また、途中でreturnが呼ばれる場合も、そこに後処理を書いてくれたりします。

こんな感じ。

InputStream is = null;
try {
  is = new FileInputStream("text.txt");
  while((int i = is.read()) != -1) {
    // 	適当な処理
    if(xxx) {
      try {
        is.close();
      } catch (IOException e) {}
      return;
    }
  }
 
  try {
    is.close();
  } catch (IOException e) {}
} catch (IOException e) {
  try {
    is.close();
  } catch (IOException e) {}
}

_ 投げられる例外の種類が多かったり、returnの数が多かったりすると

もっと悲惨なことになります。

信じられないことに未だに理解してない人が多いですが、

finallyはtryの中で例外が投げられようが、

returnが呼ばれようが、スレッドが生きてる限り必ず実行されます。

こういうのは最後にまとめてfinallyの中に書きましょう。

InputStream is = null;
try {
  is = new FileInputStream("text.txt");
  while((int i = is.read()) != -1) {
    // 	適当な処理
    if(xxx) {
      return;
    }
  }
} catch (IOException e) {
  // 例外処理
} finally {
  try {
    is.close();
  } catch (IOException e) {}
}

_ ちなみにC++の例外処理にはfinallyがありませんが、信じられないです。

なんであんな文法の博物館みたいな言語にfinallyくらい便利な物が

無いんでしょうか?

_ 次、やるべき事

1,例外は大きく囲う

やっちゃいけないことの2と繋がりますが、メソッドの頭にtryがあって、

最後にcatchがあるくらいでいいです。

finallyを使って後処理をきちんとやれば、大体はそれで済みます。

_ 2,積極的にメソッドの外に例外を投げる。

例えばDBを操作するプログラムで、処理に失敗したらfalseを返す、

なんてメソッドを見かけます。

こんなシグネチャで。

public boolean doXXX();

こういうのは、

public void doXXX() throws SQLException;

とした方がよいです。

戻り値で成功か失敗かを判定する場合、呼び出し元は

if(!doXXX()) {
  // 	エラー処理
}

_ なんてのを書かされますが、無駄です。

例外を利用したコードにしておけば、正常系のコードだけ書いておいて、

処理の全体を大きくtry〜catchで囲ってやるだけで済みます。

_ 3,例外クラスを賢くする

例外も一つのクラスなので、いくらでも拡張が出来ます。

Exceptionを継承して、コンストラクタを上書きしただけの例外クラスを

書く人がいますが、例外クラスに機能を持たせることでコードを大きく

簡略化できることがあります。

たとえばよくあるパターンで、エラーコードを例外クラスに持たせて、

catchした側がそのエラーコードからエラーメッセージを調べて表示する、

なんてコードを見かけます。

そういうのは、エラーメッセージを調べる機能を例外クラスに持たせれば

コードを簡略化できます。

public class SampleException extends Exception {
    public SampleException(int errorCode) {
        // 初期化処理
    }
 
    public String getErrorMessage() {
        // リソースからエラーコードを元にエラーメッセージを取得する
    }
}

_ エラーメッセージを例外が知っていることは自然ですよね?

綺麗なプログラムを書くコツの一つは、使う側より使われる側に機能を持たせる

ということです。

良いコードは使い回しが効くので、使われる側が1に対して、使う側が複数あります。

なら数の少ない使われる側に機能を持たせた方がコードがすっきりするのは

自然なことです。

_ あと、番外編

このコードを書く人が他に居ると思えないんで番外編。

これ書いた人、まだ業界に居るんだろうか。

try {
  // 適当な処理
} catch (Exception e) {
  if(e instanceof IOException) {
    // IOException用処理
  } else if(e instanceof NullPointerException) {
    // NullPointerException用処理
  } else if(e instanceof InterruptedException) {
    // InterruptedException用処理
  }
}
本日のリンク元
その他のリンク元
検索