- PR -

Javaコードスタイル

投稿者投稿内容
hatena
会議室デビュー日: 2002/02/14
投稿数: 14
投稿日時: 2002-02-23 15:08
以下

FileReader fr = null;
try {
fr = new FileRader("xxx");
// 処理

return X;
catch(IOException ioe) {
}
}finally {
if ( fr != null ) {
fr.close();
}
}
kaho
会議室デビュー日: 2001/08/14
投稿数: 12
投稿日時: 2002-02-23 17:28
なんだか私すごい素人だと思われているんですかね・・・・

今回の場合、多数の条件分岐のifブロックをどう書くか、というスタイルの問題から
始まってるわけですが、私はifブロック内でreturnして値を返すのは避けてローカル
変数に値を代入するといっているから当然

int x;
if ( cond1 ) {
x = 1;
} else if ( cond2 ) {
x = 2;
} else {
x = 3;
}
return x;

という書き方を好んでいる、といっているわけです。これならifブロックの前で
確保したリソースを解放するのにreturnの前でやっておけばよくなります。
最初の設計からストリームを開いてやるような場合、try-catch-finallyでリソースの
解放を保証すればよいですが、後からの変更でリソースを参照するようになった
場合の安全性はこの方が高いです。また、複雑な処理が必要でなく、また例外
によらない場合分けで返り値を変更するのにtryブロックは意味があるのでしょうか?

hatenaさんの書き方だと返り値のあるメソッドの場合結局return文を複数書く
ことになりますよね?それは最初から私がやりたくないと書いていることです。

で、もし私がtry-catch-finallyを知らないような初心者だと思われているので
はと思い書き込みましたが、hatenaさんの例は(そのままではコンパイルでき
ないのでcatch文の前に括弧があるものとして言えば)ifブロックとは何の関係も
ない基本的なtry-catch-finallyの使用法で、文脈的なつながりもわかりません。

もし私が誤解している部分がありましたら教えていただけると有り難いです。
まりり
ぬし
会議室デビュー日: 2001/12/05
投稿数: 329
投稿日時: 2002-02-24 00:28
>kahoさん
気を悪くされているのなら申し訳ありません。
あくまで、リソースの操作に関連する場合についての指摘です。

例に出されたストリームを扱うというようなリソース操作の場合、
ストリームを開く際には必ずtryブロックがありますから、
そのtryの最後でreturnさせておいて、ストリームを閉じるのは
必ずfinallyブロックでやりましょうと。

例外を送出しないもので、と軽く書かれているようにも見えますが、
リソース管理の場合は確実に例外を送出するように思います。
そうでないのはリソース管理の設計がとっても怪しい気がします・・・


リソース管理のためにif文のスタイルを決めるというのは、
Cならともかく、Javaではそう意味があるように思えません。
それならば素直にtry-finallyを利用したほうが個人的には
意味がとりやすいかなと思います。

とはいえ、kahoさんのスタイルを否定するわけではありません。
当然、リソース管理が関係なければtry-catch-finallyなんていりません。

hatenaさんの意図は、想像ではありますが、
kahoさんのおっしゃるストリームのクローズなどのリソースの後始末を
returnの直前でやるのではなく、そこから離してfinallyでやったらどうかと
いうことではないでしょうか。(結果として初歩的なコードにはなります)
先に書いた私の、リソース管理のためにスタイルを決めるのは意味がないのでは?
という意見には合致するのかな、と思っています。
kaho
会議室デビュー日: 2001/08/14
投稿数: 12
投稿日時: 2002-02-24 01:55
まりりさんのおっしゃることは分かりました。
ストリーム処理と具体的に言い過ぎたのが悪かったかもしれません。
そういう教科書的なケースが全てではなくて、例えばstaticフィールドに大きなオブジェクトを
入れておくような場合、returnする前にnullを代入してGCに後処理を任せておきたいような場合も
あるわけです。
ストリームなら開くときに例外処理を求められますが、それ以外でもGUI関連でdispose()を
呼んだ方がよい場合はいくらでもあるので、そのようなケースを考慮に入れてリソース管理と
言ったつもりなのに例外処理の話になっているので理解できませんでした。
例えばあるオブジェクトからパラメタをとっていたメソッドを同じインターフェースを継承し
ているダイアログからの入力に変更した場合などです。new java.awt.Frame()は大量のリソースを
確保しますが、例外は投げません。

振る舞いについて完全に把握できているコードや単純な処理の判断については私が示したような
スタイルはタイプ量を増やすだけで意味はありません。メンテナンス期間が長くなったり多人数で
同じコードを扱ったりするときの安全性のために多少複雑なメソッドではreturnを複数書くのは
私は避けているのですが、それは慎重すぎるのだろうか?というのは自分でも思っていることで
すのでご意見を伺えたら、と思っている次第です。
miki
大ベテラン
会議室デビュー日: 2001/09/21
投稿数: 174
お住まい・勤務地: 東京都八王子市
投稿日時: 2002-02-25 10:07
私は、主に例外状況をメインのロジックから除外したい場合に、メソッド内で複数のreturnを使います。理由は単純で、例外状況で即座にreturnをすれば、それ以後の記述が簡単になるからです。デバッグをするときもreturn以降を見る必要がありません。H2さんの最初の投稿の「後者」を支持したのは、elseを使わないことでブロックがひとつ減るからです。

コード:
if (例外条件1) {
  return x;
}
if (例外条件2) {
  return y;
}

// 本来の処理



H2さん、
すいません、返信のタイミングを逸してしまいました。

引用:

H2さんの書き込み (2002-02-22 20:58) より:
うーん、ちょっと気持ち悪いけど、cut&pasteは楽そうですね。でもtry..catch..final文はどうですか?
コード:
try {
   ...
} catch(Exception ex) {
   ...
} finally {
   ...
}


で一続きになってないと嫌じゃないですか? おもいっきり主観が入りまくりですけど。


次のやりかたでも一続きだと思っていますが...

try {
...
}
catch (Exception ex) {
...
}
finally {
...
}

つまり、XXX {} という形式のすべての文は、
コード:
XXX  {
}


で統一的に書けるということです。
XXXの部分はclass, static, switch, while, if, else などなんでもありです。
H2
ぬし
会議室デビュー日: 2001/09/06
投稿数: 586
お住まい・勤務地: 港
投稿日時: 2002-02-25 10:50
おお、ちょっと見ぬ間にいろいろと熱くなっていますね。

引用:

mikiさんの書き込み (2002-02-25 10:07) より:
つまり、XXX {} という形式のすべての文は、
コード:
XXX  {
}


で統一的に書けるということです。
XXXの部分はclass, static, switch, while, if, else などなんでもありです。


確かにそれは言えますね。ただ、私が思うに、
コード:
XXX {

} YYY {

} ZZZ {

}


と書くほうが、
コード:
XXX {

}

YYY {

} 

ZZZ {

}


と書くよりもより鮮明に各ブロックの関連性が見えると思います。XXX、YYY、ZZZ各ブロックがまったく関係のないことであれば後者でもよいと思うのですが、パッと見た瞬間前後の連合性がよくみえるのは前者 かな? でもif..else.. 文を使ったらどう書こうと前後の関連性なんてすぐ分かりますよね( )やっぱりこういう所は個人の嗜好が入ってしまいますね。

引用:

kahoさんの書き込みより (2002-02-22 22:40):
私はメソッド内にreturn文を複数書くのは避けています。

kahoさんの書き込みより (2002-02-24 01:55):
メンテナンス期間が長くなったり多人数で同じコードを扱ったりするときの安全性のために多少複雑なメソッドではreturnを複数書くのは私は避けているのですが、それは慎重すぎるのだろうか?というのは自分でも思っていることですのでご意見を伺えたら、と思っている次第です。


実は私もです。基本的にreturn文はメソッド内に一つ。慎重すぎることはないと思います。mikiさんのおっしゃるようにreturn文を即座にメインロッジク外でだすのは良いと思うのですが、ロジック内でがんがん使われているのは嫌ですね。時と場合によりますが、私はメソッドの最初のほうで引数を調べてすぐに返値を返せる場合にはreturn(もしくは例外送出)をし、その後の処理ではローカル変数に収納して最後にreturnをするようにしています。

上の例は冗長な表現の場合はみなさんはどうされるのか興味があったのでわざとif..else if..else文に複数のreturn文を書いています。
hatena
会議室デビュー日: 2002/02/14
投稿数: 14
投稿日時: 2002-02-25 14:32
> kaho wrote
>で、もし私がtry-catch-finallyを知らないような初心者だと思われているので
>はと思い書き込みましたが、hatenaさんの例は(そのままではコンパイルでき
>ないのでcatch文の前に括弧があるものとして言えば)ifブロックとは何の関係も
>ない基本的なtry-catch-finallyの使用法で、文脈的なつながりもわかりません。

とある所で、アクセスしていたので、説明なしでした。
初心者と勘違いで、気分を害したみたいですね。
すみません。

> Kaho wrote
>メンテナンス期間が長くなったり多人数で
>同じコードを扱ったりするときの安全性のために多少複雑なメソッドではreturnを複数書くのは
>私は避けているのですが、それは慎重すぎるのだろうか?というのは自分でも思っていることで
>すのでご意見を伺えたら、と思っている次第です。

慎重なのは別に問題がないと思います。
自分の場合は、try-finallyでメンテナンス性を解決します。処理コストはあまり気にしません。
処理コストで、気にするのは、文字列の連結ぐらいです。
システム上のボトルネックは、プロファイラーで調査しないと正確に把握できない。自分の思い込みで修正しても、思った以上のパフォーマンス・アップに成らないことが多々あります。
それは、俺だけかな?
まりり
ぬし
会議室デビュー日: 2001/12/05
投稿数: 329
投稿日時: 2002-02-25 22:57
returnが複数あるというのは私自身も好きではないです。
下手な使い方をすれば悪名高きgoto相当のことが出来てしまいます。
同様にcontinue乱発も避けて欲しいところだなと思ったりもします。

不勉強にしてGUI関係でのJavaの経験がないのですが、
staticに大きなオブジェクトを入れながら、
nullでオブジェクトを消しに行くようなケースがあるのですか?
(純粋な興味です)
ぱっと聞いただけだととても怖いことをしているようにも見えたりしますが、
大丈夫なのかな・・・?

私の考えているリソースはファイルだったりDBだったりソケットだったり、
典型的なものなので、使いはじめに例外をちゃんと投げてくれます。
リソースへのアクセスをするクラスはこうあってほしい(こうあるべき)と
強く思っているので、前のようなはっきりした物言いになっています。

kahoさんのいう、慎重すぎるのか?に対してはそうでもないのではないかと思います。
プログラムを書いていて慎重すぎるということはないように思います。

ただし、returnすべき変数に値をセットしてもなお、
さまざまな処理(妥当性のチェックなど)が走るような場合には
無駄なのでやめて欲しいと感じますね。
私はmikiさんのようにメソッドのトップで引数のチェックをやるときに
この手の無駄なチェックを良くやってしまい、すっきりしない!と
ひとり腹を立てたりしています。

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