東方算程譚

Oriental Code Talk ── επιστημηが与太をこく、弾幕とは無縁のシロモノ。

目次

Blog 利用状況

ニュース

著作とお薦めの品々は

著作とお薦めの品々は
東方熱帯林へ。

あわせて読みたい

わんくま

  1. 東京勉強会#2
    C++/CLI カクテル・レシピ
  2. 東京勉強会#3
    template vs. generics
  3. 大阪勉強会#6
    C++むかしばなし
  4. 東京勉強会#7
    C++むかしばなし
  5. 東京勉強会#8
    STL/CLRによるGeneric Programming
  6. TechEd 2007 @YOKOHAMA
    C++・C++/CLI・C# 適材適所
  7. 東京勉強会#14
    Making of BOF
  8. 東京勉強会#15
    状態遷移
  9. 名古屋勉強会#2
    WinUnit - お気楽お手軽UnitTest

CodeZine

  1. Cで実現する「ぷちオブジェクト指向」
  2. CUnitによるテスト駆動開発
  3. SQLiteで組み込みDB体験(2007年版)
  4. C++/CLIによるCライブラリの.NET化
  5. C# 1.1からC# 3.0まで~言語仕様の進化
  6. BoostでC++0xのライブラリ「TR1」を先取りしよう (1)
  7. BoostでC++0xのライブラリ「TR1」を先取りしよう (2)
  8. BoostでC++0xのライブラリ「TR1」を先取りしよう (3)
  9. BoostでC++0xのライブラリ「TR1」を先取りしよう (4)
  10. BoostでC++0xのライブラリ「TR1」を先取りしよう (5)
  11. C/C++に対応した、もうひとつのUnitTestFramework ─ WinUnit
  12. SQLiteで"おこづかいちょう"
  13. STL/CLRツアーガイド
  14. マージ・ソート : 巨大データのソート法
  15. ヒープソートのアルゴリズム
  16. C++0xの新機能「ラムダ式」を次期Visual Studioでいち早く試す
  17. .NETでマンデルブロ集合を描く
  18. .NETでマンデルブロ集合を描く(後日談)
  19. C++/CLI : とある文字列の相互変換(コンバージョン)
  20. インテルTBBによる選択ソートの高速化
  21. インテルTBB3.0 によるパイプライン処理
  22. Visual C++ 2010に追加されたSTLアルゴリズム
  23. Visual C++ 2010に追加されたSTLコンテナ「forward_list」
  24. shared_ptrによるObserverパターンの実装
  25. .NETでマンデルブロ集合を描く(番外編) ── OpenCLで超並列コンピューティング
  26. StateパターンでCSVを読む
  27. 状態遷移表からStateパターンを自動生成する
  28. 「ソートも、サーチも、あるんだよ」~標準C++ライブラリにみるアルゴリズムの面白さ
  29. インテルTBBの同期メカニズム
  30. なぜsetを使っちゃいけないの?
  31. WPFアプリケーションで腕試し ~C++でもWPFアプリを
  32. C++11 : スレッド・ライブラリひとめぐり
  33. Google製のC++ Unit Test Framework「Google Test」を使ってみる
  34. メールでデータベースを更新するココロミ
  35. Visitorパターンで遊んでみたよ
  36. Collection 2題:「WPFにバインドできる辞書」と「重複を許す検索set」
  37. Visual C++ 2012:stateless-lambdaとSQLiteのぷち拡張
  38. 「Visual C++ Compiler November 2012 CTP」で追加された6つの新機能

@IT

  1. Vista時代のVisual C++の流儀(前編)Vista到来。既存C/C++資産の.NET化を始めよう!
  2. Vista時代のVisual C++の流儀(中編)MFCから.NETへの実践的移行計画
  3. Vista時代のVisual C++の流儀(後編) STL/CLRによるDocument/Viewアーキテクチャ
  4. C++開発者のための単体テスト入門 第1回 C++開発者の皆さん。テスト、ちゃんとしていますか?
  5. C++開発者のための単体テスト入門 第2回 C++アプリケーションの効率的なテスト手法(CppUnit編)
  6. C++開発者のための単体テスト入門 第3回 C++アプリケーションの効率的なテスト手法(NUnit編)

AWARDS


Microsoft MVP
for Visual Developer - Visual C++


Wankuma MVP
for いぢわる C++


Nyantora MVP
for こくまろ中国茶

Xbox

Links

記事カテゴリ

書庫

日記カテゴリ

ぴーびーしー

ネタ元 → オブジェクト指向のコードが追いにくい理由

ここでちらっと触れられてる 契約プログラミング(Programming By Contract) なんだけども。

関数の提供者と利用者との間に交わされる「契約をお互いに守りましょう」
ってダケのこと。ここでの契約とは:

- 事前条件(pre condition)
 関数を呼ぶ側で守らなければならない条件。
 たとえば平方根を求める関数 sqrt ならば、"引数が負であってはならない"とか。
- 事後条件(post condition)
 関数がその終了時に守らなければならない条件
 sqrt の"戻り値の二乗は引数に十分近くなくちゃならん"とか。
- 不変条件(invariant)
 関数呼び出しの前と後とで保持されるべき条件
 たとえばコレクションの"検索によって要素数が変化しちゃならん"とか。

EiffelやDでは上記の条件を満たしているかの検証を言語がサポートしてくれます。
不変条件はちょっくら面倒なんだけど、事前条件/事後条件はC/C++だと簡単。
ぶっちゃけ assert 一発です。

int square_root(int x) {
  assert( x > 0 ); // 事前条件
  ...
  assert( result*result <= x ); // 事後条件-1
  assert( (result+1)*(result+1) > x ); // 事後条件-2
  return result;
}

.NET だと Debug.Assert 使えばいいか。

...流行りませんねぇ。事前条件だけでも埋め込んでおけば
バグったとき"俺のせいじゃねぇ。間違ってんのはお前の方だ!"って
主張できるから原因の切り分けが楽なのにねぇ。

投稿日時 : 2008年6月23日 0:38

コメントを追加

# re: ぴーびーしー 2008/06/23 1:00 通りすがる

組込みの人ですが,「何かの間違えで」異常値が来たときにNDEBUGで通過されると困るので,結局チェックしてますねぇ.
ええ,大半は無駄だとは思うのですが...

# re: ぴーびーしー 2008/06/23 1:43 れい

> ここでちらっと触れられてる 契約プログラミング(Programming By Constact) なんだけども。

Contractかな。

> ...流行りませんねぇ。

あんまり使わないなぁ
なんでだろう?

粒度が大きい関数だとチェック項目が増えてめんどくさい。

粒度の小さい関数の場合
ライブラリなんかが多くて、
その場合リリースでも動いて欲しいので
assertじゃ間に合わない。

あんまり巨大なプロジェクトを扱わないからかなー?

# re: ぴーびーしー 2008/06/23 1:53 επιστημη

っく、typoです。修正しますたー

> その場合リリースでも動いて欲しいので
> assertじゃ間に合わない。

あー...うん。
catchされない例外飛ばすなんてーことやってもいぃかもですねー
# throw/catchされなければ例外のコストは大したこと
# なかったと思うけど、実際のとこどーなんだっけ。

# re: ぴーびーしー 2008/06/23 6:44 Fujiwo

> その場合リリースでも動いて欲しいので
> assertじゃ間に合わない。

うーん…
契約違反のコードは、呼び出し側のバグなので、リリース時に動くということは、バグが出荷されちゃったということですね。
本来は、リリース時には動かないのが前提とすべきだと思います。

例外は、正規の異常系処理なので、リリース時に動いても問題ないけれど。

でも、確かに .NET 系のライブラリは、契約違反の呼び出しでも例外の throw になる場合が多いですね。C/C++ 系だと「鼻から悪魔がでても文句を言うな」系が多いのですけれど。

# re: ぴーびーしー 2008/06/23 7:03 Hirotow

.NETであれば、
ArgumentExceptionとか、
ArgumentOutOfRangeExceptionとかを使います。

Javaでも似たような例外があります。

# re: ぴーびーしー 2008/06/23 8:40 melt

4 とか入力で入るとアサートが出そうな気配が……。

# re: ぴーびーしー 2008/06/23 9:06 επιστημη

> リリース時には動かないのが前提
ですよねー
とはいえお客さんとこでコケたとき遺書が残るのはありがたいんですよね。
原因不明で客死すると骨拾うのに苦労します。
再現性が薄いとなおさら。

> 4 とか入力で入るとアサート
ヒギィ
× assert( result*result < x ); // 事後条件-1
○ assert( result*result <= x ); // 事後条件-1
修正しました。
# ついでに return result; も抜けてました(てへ

# re: ぴーびーしー 2008/06/23 9:34 ネタ好き未記入

デバッグテクニック徹底解説の愛読者として契約プログラミングはいいと思うのですが、本当にはやっていませんよね。
D言語のように言語仕様に含まれていたらもっとはやると思います。ただ、これらの契約はまだ表現が不十分なので、もっと表現力がアップしないと本格的には流行らないと思います。

# re: ぴーびーしー 2008/06/23 9:42 ネタ好き未記入

オブジェクト指向が追いにくい件についてですが、私はオブジェクト指向の習得にさほど抵抗感がなかったので、自分の感覚を自分に問いかけてみたところ次の感覚が浮かび上がってきました。

1:常に頭の中でコード動かしていたこと。これにより静的でも動的でもあまり変わりません。
2:拘らない。細かいことを気にしなくても、デスマーチで数万行ぐらい打てば誰でもマスターできます。
3:Lisp使いが「括弧?そんなものあったよな」というのと同じ感覚。
4:重複や無駄を憎む心。オブジェクト指向もコードの重複を減らすための手段と考えれば理解しやすいです。
5:Lisp使いが再帰コードを理解するのと同じ感覚。つまりコードの○○オブジェクトではなく、抽象的な何かと捕らえる。

こんな感じです。
みんなはどのように感じたら習得できましたか?
それを掘り下げると面白いと思います。

# re: ぴーびーしー 2008/06/23 9:47 シャノン

> バグったとき"俺のせいじゃねぇ。間違ってんのはお前の方だ!"って
> 主張できるから原因の切り分けが楽なのにねぇ。

「やかましい。落ちてるのはお前のコードだ。
『落ちない』が前提条件だ。ガタガタ言うのはその後だ。
だいたい、何でわざわざ落ちるようなコードを書くんだ。直せ!」

# re: ぴーびーしー 2008/06/23 9:49 ネタ好き未記入

ショノンさん、それ生々しすぎるw

# re: ぴーびーしー 2008/06/23 9:50 ネタ好き未記入

そういえば私も同じ事を言われたことがありますw

# re: ぴーびーしー 2008/06/23 10:09 επιστημη

> オブジェクト指向が追いにくい件
そいつはネタ元でやらかしてください。

# re: ぴーびーしー 2008/06/23 10:24 επιστημη

>『落ちない』が前提条件だ。

切り崩すならココからかな ^^;
バグの特定は原因と現象とが近いほど楽。
# メモリの開放忘れが厄介なのは原因と現象とが遠く離れちゃうから
マズいことが起こったのを取り繕うとそれだけ現象の発現を
先延ばしにするわけで、傷口を広げる結果になるます。

...なんて説得しても聞く耳持たんのだろなー

# re: ぴーびーしー 2008/06/23 10:26 ネタ好き未記入

>そいつはネタ元でやらかしてください。

すいません。
では契約プログラミングについてどこが不十分なのか述べます。私が不十分と思うのは次の点です。

1、呼び出し元や動作環境を全て想定できない。
2、オブジェクトの実装隠蔽機能によりコードが暗黙的条件を要求しすぎる。

この点を考慮すると、普及しない理由には文法の問題や性格だけでなく、人間の能力の限界もあると私は思います。

# re: ぴーびーしー 2008/06/23 10:34 επιστημη

>1、呼び出し元や動作環境を全て想定できない。

これは、「誰から呼ばれようが/どんな状況で呼ばれようが
確実にassertできる条件は限られるため、やったところで
(限定的な)条件しか明記できない」てーことですか?

>2、オブジェクトの実装隠蔽機能によりコードが暗黙的条件を要求しすぎる。

ごめんわかんない。

# re: ぴーびーしー 2008/06/23 10:35 ネタ好き未記入

>...なんて説得しても聞く耳持たんのだろなー

そうなんです。私はオブジェクト指向が普及していない職場でオブジェクト指向を言ったところ、「そんなのは注意してコピペしたら済む話だ」と一喝されました(笑)
ヒューマンエラーを直すプログラミング言語が欲しいです・・・

# re: ぴーびーしー 2008/06/23 10:40 ネタ好き未記入

>(限定的な)条件しか明記できない」てーことですか?
その通りです。

>ごめんわかんない。
言葉足らずですみません。既存のコードを利用する際にはassertをリリースビルドで取り除いてしまっていますし、たとえベンダがサボって十分にチェックしていない場合がありえます。
でも、呼び出す側にしてみれば開発者が考えている条件なんて分かりませんし、全てのコードを覗くわけにもいきません。
それで私達一般開発者は、十分な契約を設定できないと思うのです。

# re: ぴーびーしー 2008/06/23 10:51 επιστημη

> 十分な契約を設定できない

わかります。
ただまぁ、100%完璧を期待できないから"使えない"と断じるよりは
"大したコストをかけずに(たとえば)10%救えるから採用"するってユルさも必要かと思うですよ。

そもそもバグを一掃できる"銀の弾丸"はどこにもないんだから。

# re: ぴーびーしー 2008/06/23 10:52 επιστημη

> 注意してコピペ

その注意が"できないのが人間様"なんですけどねー

# re: ぴーびーしー 2008/06/23 11:05 ネタ好き未記入

>"大したコストをかけずに(たとえば)10%救えるから採用"するってユルさも必要かと思うですよ。

仰るとおりですね。
生真面目な人が多すぎのが流行しない理由かもしれませんね。

# re: ぴーびーしー 2008/06/23 12:34 Fujiwo

そうそう。「銀の弾丸じゃないから使わない」ってのは、IT技術者にあるまじき態度だと思います。

契約プログラミングは基本だと思います。その上、手間もかからず効果的です。

# 基本をやった上で更にバグをなくせる工夫があるんだったら、それはそれでやったらいいと思いますが、それはまた別の話。

# re: ぴーびーしー 2008/06/23 14:20 επιστημη

銀の弾丸じゃないんで百発百中ピチューンはムリだけど
そこそこ当たるやつで弾幕はって"かすりボーナス"
積み重ねればいぃぢゃん、みたいな。

火力はなくとも霊夢の誘導弾はザコ敵には有難いし。
# よくわかんないんですけどね、無縁ですから。

# re: ぴーびーしー 2008/06/23 14:36 凪瀬

契約が守られる前提でなら、契約先に任せちゃえばいいんで、その先のことを考えなくてよくなるんですよね。
契約の成否を検出することは、この信頼性の担保として重要です。しかしJavaも1.4からassert追加になってるけど普及していない気がするなぁ…。

# re: ぴーびーしー 2008/06/23 19:02 れい

>> リリース時には動かないのが前提

ライブラリが製品の場合もありますし、
部分的に使いまわす際には
ソースを見ないで使う人もいるので
リリース時にもチェックは必須かな。
なので、事前条件はthrowを使ってます。

事後条件はassertでもいいんですが、
入れる手間に見合わないことが多いかなぁ

事前条件が全部ちゃんと入っていれば
そこで引っかかるので…

# re: ぴーびーしー 2008/06/24 8:25 ネタ好き未記入

そうそう。assertとthrowの使い分けが難しんですよね・・・
皆様はどういう風に使い分けていますか?

# re: ぴーびーしー 2008/06/24 19:42 シャノン

> # よくわかんないんですけどね、無縁ですから。

いい加減、それはどうかと思うぞ。

タイトル
名前
URL
コメント