- PR -

プログラムの書き方でご指導お願いします。

投稿者投稿内容
がるがる
ぬし
会議室デビュー日: 2002/04/12
投稿数: 873
投稿日時: 2005-11-08 18:07
どもです。がるです。

引用:

S_Tatsuさんの書き込み (2005-11-08 17:00) より:
今回は例外処理系で仕様変更も可能性があるのでぜひ参考にさせてい
ただきます^^


多分楽できると思うので(笑
もしいけそうならじゃかすか使っちゃってください ^^

引用:

権兵衛さんの書き込み (2005-11-08 17:17) より:
これって、chackA()とchackB()がエラーのときにfalseでなく例外を返す仕様の場合であればって話ですよね?それぞれのメソッドがなんらかのチェックメソッドでエラーが例外でないのであればこの方法は使えません。chackA()、chackB()が例外をthrowするように変更すると、falseを返したときに何か処理をするって要件があると困るかもしれません。


です。なので「例外処理系なら」っていう断り書きを入れてるです。

で、例外処理とreturn falseが混在するような処理は、知っている
限りではあんまりないと思うです。
ってか、あると混乱するので。
なので、もし「falseを返したときに何か処理をするって要件」に
近しいものがあるとすると
・もしそのfalseで処理を止めたいならcheckメソッド内で処理してからthrow
・もしそのfalseで処理を続行したいならcheckメソッド内で処理してからreturn
のいずれかのチョイスで片付くと思うですが。
どんなもんでしょうか?
権兵衛
ベテラン
会議室デビュー日: 2002/09/24
投稿数: 50
投稿日時: 2005-11-08 19:21
>がるがるさん

そもそもfalseを返す状態がそのメソッドにとって必ず異常系かってのを考慮しとかないとあとあと困るかなと。
たとえばクレジットカードの与信処理とかサーバと通信してのユーザ認証とかだと、OKならtrue、失敗ならfalse、なんらかの事象でチェックすらできない状態だったら例外、といった使い分けになると思うのですよ。わかった上で例外もfalseに丸めるのであれば問題ないんですが、例外処理が何かよくわかってない人が見ると記述を簡略化するチップスみたいに見えてしまうんじゃないかなと思ったしだいです。

>S_Tatsuさん
例外を捕まえて処理することで戻り値をみる代わりとすることもできますが、その状態が例外的な状況でなければ読みにくいコードになってしまいます。booleanの戻り値とは別に例外がある場合にその例外処理の中に正常なコードが埋もれてしまうので必要がないかぎりそういう書き方は避けたほうがいいかと思います。

[ メッセージ編集済み 編集者: 権兵衛 編集日時 2005-11-08 20:09 ]
がるがる
ぬし
会議室デビュー日: 2002/04/12
投稿数: 873
投稿日時: 2005-11-08 19:40
どもです。がるです。
なんとなく「例外処理について」の汎用的なやり取りと
化しつつあるような気がしないでもないのですが。
まぁ「そのあたりがプログラムの書き方にとっても重要だ」
ってことで。

引用:

S_Tatsuさんの書き込み (2005-11-08 18:01) より:
と書いていた所を
try{
 chack();
}
catch(ExceptionA exA){
 ・・・処理・・・
 throw exA;
}
catch(ExceptionB exB){
 ・・・処理・・・
 throw exB;
}


ですが。もし「ExceptionA」や「ExceptionB」のcatch句の処理が
checkAやcheckBに固有のものなら、chackAとかのメソッドのほうに
記述してしまったほうが分散せずに読みやすくなるかもしれないです。
このあたりは個人差や好みもあるとは思うのですが。

引用:

権兵衛さんの書き込み (2005-11-08 19:21) より:
そもそもfalseを返す状態がそのメソッドにとって必ず異常系かってのを考慮しとかないとあとあと困るかなと。


これはそうだと思うです。

引用:

たとえばクレジットカードの与信処理とかサーバと通信してのユーザ認証とかだと、OKならtrue、失敗ならfalse、なんらかの事象でチェックすらできない状態だったら例外、といった使い分けになると思うのですよ。


これは微妙ですね。っつか「人による」という言い方もあるのですが。
取り合えず
「なんらかの事象でチェックすらできない状態だったら例外」
については、多分だれも異論はなかろうか、と。
問題は「認証がNGであるというのはどのように判断するか」
なのですが。
ちなみに私がよくやるのは
コード:
  // インスタンス生成
  credit_auth cobj = new credit_auth;

  // 適当なパラメタの設定
  cobj.set(ほげほげ);

  // チェック
  // XXX 異常が発生したらthrow
  cobj.check();

  // 判断
  if (cobj.is_true()) {
    // 承認OK
  } else {
    // 承認NG
  }

  以下、処理は続くよどこまでも


こんな感じです。
個人的には「戻り値で判断」をあまりしていない、のかも
しれないです。
まぁ実際「trueとfalseで括れない」戻り値に仕様変更されたり
することもありますし(クレジットでは存在しない…と思いたい
のですが)。

なので
引用:

わかった上で例外もfalseに丸めるのであれば問題ないんですが、例外処理が何かよくわかってない人が見ると記述を簡略化するチップスみたいに見えてしまうんじゃないかなと思ったしだいです。


上述の例の場合、丸めるのはいろいろと危険もあろうかと思うです。
あと、個人的には例外処理はある程度「記述を簡略化する」ために
用いられる側面ってあると思うので。
簡略化による弊害が出ないのであれば、よいのではないかと思ってます。
# より厳密には「記述の集中化」だと思ってますが。

ただまぁ、この話ってある程度以上進むと「宗教論争」状態に
なりそうな気はするのですが :-P
取り合えず「ある程度論理的整合性がある」考え方でやりつつ、
問題点が明示的に発生するなら改善する、という程度に柔軟な
捉え方でもよいのかなぁ、と、個人的には思ってます。

以上、雑感でした。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-11-08 21:11
引用:

個人的には「戻り値で判断」をあまりしていない、のかもしれないです。


これには反対ですね。
取得したい戻り値とは別にエラーステータス持つ場合は仕方がないですが、今回はそういった例ではないですね。

検証メソッドなのですから、その時点で結果が欲しいわけです。
結果が渡されるまでの距離が離れれば離れるほど危険性は増します。
今回の例では当然すぐ下で判断を入れるのでしょうけど、
直感的でないため、その間に修正を入れる方がいるかもしれません。
(ちなみに、戻り値を変数に入れてというのも避けるべきらしいですね)

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
未記入
ぬし
会議室デビュー日: 2004/09/17
投稿数: 667
投稿日時: 2005-11-09 01:29
デジャビューのような気もするけど。

boolean による true/false の二値表現だと仕様変更に弱いので例外を積極的に使うべきだとかいう人はバカかね。そんな意見がまかり通っていたら、そもそも言語仕様に boolean など盛り込まれていないよ。

boolean ではなく例外を用いることで、多くの状態を表現できる、あとから状態を追加するのも容易という意見も間違い。そんなのは設計ミスであってコードを汚くするだけ。正常系フロー制御に例外を使うべきではないです。

なんでもかんでも「可能性」のヒトコトで汎用性ばかり持たせるというのは美しい設計だとは思えない。割り切って適用範囲をキッチリ読み切る設計こそ美しい。「もしも」ばかり言ってたら設計なんてできないと思うけど。

認証OK なら true、認証NG なら false、認証成否を判定できない(正しいユーザー名・パスワードでもはじかれる)ような異常事態なら例外という権兵衛さんの意見を支持します。
がるがる
ぬし
会議室デビュー日: 2002/04/12
投稿数: 873
投稿日時: 2005-11-09 11:07
がるです。微妙にそれてしまいそうなので、少しだけ。

引用:

じゃんぬねっとさんの書き込み (2005-11-08 21:11) より:
引用:

個人的には「戻り値で判断」をあまりしていない、のかもしれないです。


これには反対ですね。
取得したい戻り値とは別にエラーステータス持つ場合は仕方がないですが、今回はそういった例ではないですね。


んっと。どちらかというと「複数のステータスを持つ戻り値」の
心配をしています。

引用:

検証メソッドなのですから、その時点で結果が欲しいわけです。
結果が渡されるまでの距離が離れれば離れるほど危険性は増します。


はい。これはとても理解できるのですが。
同時にその「結果」自体が仕様的にゆれてしまう可能性もあるので。
特にboolean値の場合はっきりと2パターンしか返せないので、
時として「仕様変更に耐えられない」っていうケースを何度も
体験してます(苦笑

引用:

未記入さんの書き込み (2005-11-09 01:29) より:
boolean による true/false の二値表現だと仕様変更に弱いので例外を積極的に使うべきだとかいう人はバカかね。そんな意見がまかり通っていたら、そもそも言語仕様に boolean など盛り込まれていないよ。


これには同意です。
一応念のため。私は仕様変更に対しては「別途判断用メソッドを実装」
とは書いてますが「例外で処理」とは書いてないと思うです。
もしなにか私の書き方の問題などで誤解を招いていたらお詫びいたします。

引用:

boolean ではなく例外を用いることで、多くの状態を表現できる、あとから状態を追加するのも容易という意見も間違い。そんなのは設計ミスであってコードを汚くするだけ。正常系フロー制御に例外を使うべきではないです。


これも同意。
というか「正常処理」で例外使われるとわけがわからなくなります(苦笑
# でもあるなぁそういう実装のメンテナンスの経験…

引用:

なんでもかんでも「可能性」のヒトコトで汎用性ばかり持たせるというのは美しい設計だとは思えない。割り切って適用範囲をキッチリ読み切る設計こそ美しい。「もしも」ばかり言ってたら設計なんてできないと思うけど。


これについてはある程度同意しますが(XPとか好きですし)。
ただ、現実には「ありえないと叫びたいほどの仕様変更」が
あるのも事実なので。
個人的には「技術的美しさ」よりも「現実への対応能力」の
ほうがより一層興味があるところです。

以上、ちょっと話が大本からそれてしまって恐縮ですが。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-11-09 11:19
引用:

がるがるさんの書き込み (2005-11-09 11:07) より:

んっと。どちらかというと「複数のステータスを持つ戻り値」の
心配をしています。


了解。
これなら、それらをメンバに含むインスタンスを返してからになりますね。

引用:

同時にその「結果」自体が仕様的にゆれてしまう可能性もあるので。


メソッドの戻り値自体が変更されることは少ないので、その時に対応するようにしています。
定義を書く時間で少し取られますが、10 分もかかるような作業じゃないですからね。

そもそも「変数のバインディング タイム」のような概念をメソッドに押し付けるのがまずかったかな。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
未記入
ぬし
会議室デビュー日: 2004/09/17
投稿数: 667
投稿日時: 2005-11-09 11:55
引用:
一応念のため。私は仕様変更に対しては「別途判断用メソッドを実装」とは書いてますが「例外で処理」とは書いてないと思うです。


その判断用メソッドというのは、void getStatus() throws StatusException ですか?

引用:
個人的には「戻り値で判断」をあまりしていない、のかもしれないです。


という記述があったので、正常系状態遷移に積極的に例外を利用しているような印象を受けました。

引用:
特にboolean値の場合はっきりと2パターンしか返せないので、時として「仕様変更に耐えられない」っていうケースを何度も体験してます


何度も体験しているのだとしたら、それは設計ミス・設計能力の問題かもしれませんね。ふつー、成否や有無などの二値表現に boolean を使います。それが仕様変更に耐えられないというのは、根幹を揺るがすほど大きなシステム変更ではないでしょうか。

初期設計時に二値だからといって適当に boolean を使ったりはしていないですよね? たとえば性別属性を「男(true)」「女(false)」と boolean で設計するのは間違い。顧客は「子供」は別に集計したいなどと平気で言い出しますからね。

引用:
ただ、現実には「ありえないと叫びたいほどの仕様変更」があるのも事実なので。


ならば「ありえない」と言いましょう。システムの根幹を揺るがすような変更であれば、それなりのリスク(再検証コストなど)も伴いますし、十分な説明を行ってシステム変更費用を取れるように努力しましょう。

戻り値の範囲というのは、なるべく狭いほうがシステムが平易になります。汎用性のヒトコトで広げるべきものじゃない。

たとえば、状態の追加を想定して int を使って次のように設計したとしましょう。
 int STATUS_NG = 0
 int STATUS_OK = 1

なんとなく STATUS_HOGE = 2 など状態を簡単に追加できそうな錯覚に陥りますが、話はそんなに簡単じゃないです。STATUS_OK, STATUS_NG 前提の判定コードが書かれていたらどうなることか・・・。やはり、関連部分の広範な再検証が必要になるのです。

初期段階から 0, 1 だけでなく 2 が追加される可能性も考慮してコードを書けばいい、と思うかもしれませんが、そんなことをやっていたら、やはり開発コストの増加につながりますよね。ないかもしれない変更を想定して「汎用性」「汎用性」と言っていたら、それこを開発コスト増が、顧客のデメリットにつながります。

割り切った設計も顧客のメリットになります。過剰な設計で顧客は喜んだりしませんよ?

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