̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ IT ニュース&コラム 2013/10/14 通巻641号 技術版 ソフトウェアデザイン館 Sage Plaisir 21  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ assert を禁止にするな - リーダブル・コード(12) assert は、「表明」をするためのマクロまたは関数です。 表明とは、 真となるべき条件をソース・コードに埋め込むことで、条件を満たして いるかどうかを実行中にチェックすることです。 assert は、デバッグ版 (またはテスト版)と呼ばれる開発中だけ使用するプログラムでのみ チェックします。 多くのプログラミング言語で使うことができます。 リリースするプログラム(リリース版)でもチェックするときは、 エラー処理や例外処理と言います。(ただし、文脈によっては、こちらも 表明と呼ぶことがあります。) リリース版でも条件を満たしているかどうかをチェックした方が安全です。 これはあたりまえですね。 でもなぜデバッグ版しかチェックしない assert が存在するのでしょうか。 それは、前にチェックしたことを 再度チェックすることなど、不要なチェックによってプログラムの 処理速度が遅くなることを防ぐためです。 しかし、不要であることの証明は難しいので、チェック漏れの原因になる ことがあります。 そのため、安全じゃないから単純に assert を禁止 にするルールが作られることがあるのですが、それを作ってしまうと、 プログラムが遅くならないように、条件式を書かないようになってしまい、 「契約プログラミング」や「形式手法」によって安全性を高めることを しなくなったり、問題を早期に発見できなくなったりして、品質や 開発効率が落ちます。 安全性と処理速度のトレードオフの対処法については、コードの読みやすさとは 関係ないので、今回は以上で割愛させていただきます。 assert はデバッグ版だけチェックを行い、例外処理はデバッグ版とリリース版 の両方でチェックを行うことですが、どちらも条件を満たしているかチェックする ことに使うことができます。 しかし、assert は、真となるべき条件式を書くのに対し、例外処理(する前の if 文)では、逆に偽となるべき条件式を書きます。 つまり、リリース版でも チェックするかどうかによって、条件式が逆なのです。 ややこしいですね。 表明: assert( a >= 1 ); 例外処理: if ( a <= 0 ) { return ERROR_CODE; } 不等号が逆になることだけではありません。 真となるべき条件式では、 a >= 1 の 1 のように条件を満たしている値を書く方が読みやすいですし、 偽となるべき条件式では、a <= 0 の 0 のように条件を満たさない値を 書く方が読みやすくなります。 (比較する値が浮動小数のときは、 < か <= かによって条件を満たしている値か満たさない値のどちらかしか 選べないため、この手法を使って読みやすくすることはできません。) 真となるべき条件式を書く方が分かりやすいので、そちらに統一した方が いいと考えるかもしれませんが、上記のように浮動小数のときや、 条件を満たさなかったときに処理をするブロックがある程度の規模があるときは、 偽となるべき条件式を書いた方が分かりやすいため、 すべてのプログラムで統一することは実質不可能です。 なるべくどちらかに統一するぐらいの方が読みやすくなります。 条件式を統一するためには、たとえば、次のマクロを用意します。 表明(デバッグ版のみチェックする): ASSERT_D( a >= 1, return ERROR_CODE ); リリース版でもチェックする表明: ASSERT_R( a >= 1, return ERROR_CODE ); 第2引数は、条件を満たさなかったときに実行する「文」です。 デバッグ版では 条件を満たさなかったときにそこでブレークすることができますが、リリース版 ではブレークができないことと、適切なエラーコードを返す必要があるために、 第2引数が必要になります。 第2引数は、return の代わりに、関数の中の終了処理部へ goto すること もあります。(例外処理ができない C言語のみ) ASSERT_D( a >= 1, e = ERROR_CODE; goto fin ); 予期しないエラーの場合は、エラーコードを厳密に選ぶ必要はありません。 システムとして予期された異常に対する処理があるときは、エラーコードを 適切にする必要があるかもしれません。しかし、ほとんどの場合、予期されても プロセスの停止やシステムの再起動で済むため、エラーコードが曖昧であっても あまり問題ではありません。 そのため、私は E_OTHERS(その他のエラー)という エラーコードを使っています。 世の中の関数は、よく「引数エラー」を返しますが、 それはその他のエラーと同じく、例外処理をするための情報は何もありません。 引数エラーは、適切なエラーコードを常に返すべきという単純なルールを適用 しようとする原理主義者に対する対策でもありますが、乱用されたりもします。 ASSERT_D と ASSERT_R は、設定によってブレークしたりしなかったりする ことができると便利です。 ブレークした方が問題が発生した近くの状況を 確認することができるためデバッグの効率がよくなりますが、ブレーク しなければテストが中断しないため、テストを実施する効率がよくなります。 目的に応じて使い分けるのです。 偽となるべき条件式を書く場合でも、デバッグ版では条件を満たさなかったときに 設定によってブレークしたりしなかったりすることができる if 文を用意すると、 デバッグの効率が上がります。 デバッグ版(テスト版)だけチェックする例外処理: IF_D ( a <= 0 ) { return ERROR_CODE; } 例外処理: IF ( a <= 0 ) { return ERROR_CODE; } ASSERT_D などは、Snap Note 開発記 2013年03月10日 の記事から ダウンロードできます。 参考: Wikipedia - 表明 Wikipedia - 契約プログラミング MET01-J. メソッドの引数の検証にassertを使わない http://www.jpcert.or.jp/java-rules/met01-j.html 注目ニュース 一覧 ◇ チャレンジせよ、ユニークであれ、話をうのみにするな。任天堂岩田社長の経営哲学。 http://japan.cnet.com/news/business/35038193/ … 顧客志向が良くない会社もある。 ◇ グーグルの歩みを振り返る。創設からの15年とユーザーに与えた影響。 http://japan.cnet.com/news/commentary/35037874/ … 批判に立ち向かう姿勢は評価できる。 ◇ 海外からの音楽・電子書籍配信に消費税課税へ。Amazonなどとの不公平感是正。 http://www.itmedia.co.jp/news/articles/1310/07/news038.html … 消費税の分だけ関税を安くすればいい。関税ゼロなら消費税を付けるべき。 ◇ Google Glass がアップデート。乗り換え案内機能などを追加。 http://japan.cnet.com/news/service/35038202/ … 公共の場で使う勇気はない。 ◇ Google Calendar と同期するレゴの壁掛けカレンダー。 http://japan.cnet.com/news/offtopic/35038185/ … ロボットがレゴ製カレンダーに付けた予定を変えるわけではない。 ◇ 日本の省庁などへ水飲み場型攻撃。IEのゼロデイを突き、8月に起きていた。 http://internet.watch.impress.co.jp/docs/news/20131010_618941.html … ターゲットの省庁が訪問したときだけ発動するため、発見しにくかった。 ◇ 笠原一輝のコードマスターズ「F1 2013」をやってみた。 http://car.watch.impress.co.jp/docs/special/20131010_616918.html … テレビと全く見た目が同じ。伝説のドライバーのチョイスも渋い。 ソフトウェアデザイン館 Sage Plaisir 21 ホームページ >>> http://www.sage-p.com/ メルマガ >>> http://www.mag2.com/m/0000083983.html ブログ >>> http://blog.livedoor.jp/sage_p/ ツイッター >>> http://twitter.com/Ts_Neko ダウンロード >>> http://www.sage-p.com/freesoft.htm サポート掲示板 >>> http://www.sage-p.com/kg_ban09/z6037C8.cgi 東日本大震災 >>> http://www.sage-p.com/saigai.html メール >>> ts-neko◇sage-p.com ←◇を@に変えてください 緊急メールは件名に「うどんメール」を付けてください。 このメルマガの登録・解除 - http://www.mag2.com/m/0000083983.htm