Skip to content

Instantly share code, notes, and snippets.

@gintenlabo
Created July 8, 2013 15:07
Show Gist options
  • Select an option

  • Save gintenlabo/5949639 to your computer and use it in GitHub Desktop.

Select an option

Save gintenlabo/5949639 to your computer and use it in GitHub Desktop.

assert 使用のガイドライン

大原則

  • assert で示されている条件は,正しくプログラムが書けている場合,必ず成立する
  • 状況次第で失敗する可能性のある条件を assert にかけてはならない
    • 例として,ユーザ入力や設定ファイルの妥当性検証を assert で行なってはならない
  • 例外にするべきか assert にするべきか迷った場合には,とりあえず例外を使うことを検討する
    • どの例外を投げるのが相応しいかを考える過程で,思考が整理されることが期待できる
      • 思考整理ができなかった場合には,その旨をソースコードや pull req. のコメントに残す
    • 例外送出を assert にするのは容易だが,逆は容易でない

assert を使うべき局面

  • ローカル変数, private メンバ変数,ファイルスコープ変数など, アクセスできる範囲が「閉じている」ものに対して不変条件のチェックを行う場合
    • それらの変数は,単体テストで不変条件をチェックしにくいため, assert を使ってチェックすることが望ましい
    • 例として,二つのポインタを管理しているクラスで,それらのポインタは 常に同時に(非 NULL の値に)設定され,常に同時に NULL にクリアされるような場合には, 片方のみが NULL になることは ありえないため, assert を使ってチェックすることが望ましい
  • バグの存在を,もみ消されることなく 即座に検出したい場合
    • 例として,外部ライブラリの関数を呼び出した結果に対し,何らかの条件の成立が期待される場合, 期待した通りにならないケースでは,その関数の仕様を勘違いしている可能性が高いため, assert を使って即座に勘違いを検出できるようにすることが望ましい. (もちろん,状況次第では失敗することが期待され,失敗すると処理を続行できない場合には, assert を使わずに runtime_error を投げることで失敗を通知することが望ましい)
  • コメント代わりに使うことで,コーディング上の不安を取り除きたい場合
    • 例として, sqrt(x) を呼ぶ際,「バグがなければ必ず x は 0 以上になるが,その事実は パッと見では分からない」ような場合には, // x >= 0 のようなコメントを書くより assert(x >= 0); と書いたほうがよい(ASSERT_GT のようなマクロがあれば,それを使う)
    • 同様に,関数末尾に // this function never returns というコメントを書きたくなった場合, assert(!"this function never returns"); のように書く方がよい(ASSERT_UNREACHABLE のようなマクロがあれば,それを使う)

assert ではなく例外を使ってもよい局面

  • ある関数を呼び出す際に必要な事前条件のチェックには, assert を使ってもいいし,例外を使ってもいい
    • 比較的単純な条件であり,かつ その関数が呼ばれる頻度が高い場合には, assert を使う
    • 条件が複雑であり,事前にチェックするより「試しに実行してみる」方が楽である場合には, 例外か,もしくは optional 的なものを使ったほうがスムーズになる
  • その他,例外を使った方が処理の見通しが良くなるケースには,例外を使う

assert を使うべきではない局面

  • 失敗する可能性のある assert は assert ではないので書いてはいけない
    • 失敗する可能性のある処理には,例えば malloc がある. その結果は assert してはいけない
  • if (x <= 0) { throw 〜; } に続く assert(x > 0); のような,書く必要のない assert は原則として書かない
    • ただし,条件をチェックする部分と assert を書きたくなった部分が 同じ画面に入りきらないくらい離れている場合は,その限りではない
  • assert を書かないと不安になる程度に 複雑で入り組んだコードの場合は, assert より むしろ条件分割や関数化によって簡潔で分かりやすい条件に落とし込めないかを考える
@suma

suma commented Jul 10, 2013

Copy link
Copy Markdown

使うべき・べきでない点についてしっかり書けていると思います。

逆にいえば、使用する上でのガイドラインではあるのでassertを使う目的・効果に関する記述ではなく、assertをチームのメンバーへ布教するには積極的に利用するメリット・モチベーションが感じられないと思います。
例えば以下のような観点から、チームでどのようにassertを利用していくとよいか、どうやったらassertを使うことで得たい効果を達成できると思いますか?

  • 利用する目的・期待する効果・モチベーションは?
  • assertと比べて、近い・同じ目的・効果のある、優先度が高い項目はあるか?(例:テスト)?
    • あったとしたらどちらを優先していくべきか。それとも並列してやっていくべきか? その理由は?
  • どうassertを使いつつ、どんな開発体制で回していくと効率的か? 普段のビルド・単体テストと併用? CI?

@suma

suma commented Jul 10, 2013

Copy link
Copy Markdown

assert ではなく例外を使ってもよい局面
ある関数を呼び出す際に必要な事前条件のチェックには, assert を使ってもいいし,例外を使ってもいい

仕様として事前条件チェックしないのであれば、assertを使ってもよいでしょうし、逆にチェックが必要なら例外なりエラー処理をしなければならない所ですね。この表現だと、どっちでもよいのかと、誤解を招くかと思いました。

@gintenlabo

Copy link
Copy Markdown
Author

Jubatus での assert 方針は https://gist.github.com/gintenlabo/effa71baf26cb6114e0c で.

@gintenlabo

Copy link
Copy Markdown
Author

assert ではなく例外を使ってもよい局面
ある関数を呼び出す際に必要な事前条件のチェックには, assert を使ってもいいし,例外を使ってもいい

仕様として事前条件チェックしないのであれば、assertを使ってもよいでしょうし、逆にチェックが必要なら例外なりエラー処>理をしなければならない所ですね。この表現だと、どっちでもよいのかと、誤解を招くかと思いました。

いえ,文字通り,どっちを使っても良い,という意味で書きました.

もちろん, assert を使う場合には,事前条件を明確に提示する必要がありますし,
例外を投げる場合は,どのような場合にどのような例外が投げられるかをドキュメント化するべきですが,
assert を使うか例外を使うかは基本的には設計者の裁量しだいかと思います.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment