ライブラリの評価 (2)

あるライブラリをプロジェクトで使用するかどうか決める場合、まずはそのライブラリの合目的性や実績、サポート、ドキュメントの充実度、ライセンス、提供次期、価格などを検討しますが、私はその後で、そのライブラリの "C++ライブラリとしての素性の良さ" を検討することにしています。素性の良いソフトウェアかどうかを先に検討することで、

  • 作成するアプリケーションの設計/実装に本来不要な制約をもちこまない
  • 挙動不審なライブラリを採用しない

ことを可能にします。


なるべく客観的に評価したいので、次のようなチェックリストにしています。人材の採用や賃貸物件探し等と同様、条件を付けすぎるとヒット0件となってしまうので、ここだけは譲れない、というものを中心にリスト化してあります。


C++APIレベルの、少々泥臭い検査になりますが、それでも形式化しておいてイベントにしておく意味はあると思います。だってある規模以上のベンダさんの書くような、薔薇色の売り文句を見たら、中身がクソかどうかを確認する間もなくそのライブラリ、無条件で欲しくなっちゃうじゃん。


【チェックリスト1】
理由・目的:ライブラリがアプリケーションの設計・実装に制限を与えないことを確認


Requirements:

  1. 例外安全性について考慮された設計・実装である
  2. マルチスレッド環境での使用について考慮された設計・実装である
    • 最低限、局所的静的変数を使用していない
    • MT-unsafe なリファレンスカウントを行っていない
    • etc..
  3. 型安全性について考慮された設計・実装である
    • 最低限、総称ポインタを使用しない設計・実装である
  4. メンバ関数自体、およびメンバ関数の引数が、適切にconst指定されている
  5. LP64環境での使用について考慮された設計・実装である
  6. 標準C++との親和性について考慮された設計・実装である
    • 標準C++のコンテナを使用可能である (NG: 独自のコレクションクラスの使用を強制)
    • 標準C++イテレータを使用可能である (NG: 配列の先頭アドレスと要素数による指定のみ)
    • 関数オブジェクトを使用可能である (減点: 関数ポインタのみ)
  7. 非局所的静的変数を使用していない
    • ライブラリ使用者を "static initialization order fiasco" に巻き込まない
  8. 広域名前空間を汚染しない


【チェックリスト2】
理由・目的:ライブラリ使用者が、ライブラリの挙動を読みやすいかどうかを確認


Requirements:

  1. 例外を投げるなら、その仕様が明記されている
  2. 時間のかかる処理については、処理のオーダーが明記されている*1
  3. メモリ使用量が明記されている
  4. 限界値付近での挙動が明記されている
    • 数の数え方が一貫している(符号有無、ビット幅)
    • インデクスの付け方が一貫している(符号有無、ビット幅、0 or 1オリジン)
  5. オブジェクトが状態遷移するなら、その仕様が明記されている
    • 「メソッドBはメソッドAを呼んだ後でないと呼べない」ならマニュアルに明記されている、デバッグモードでは違反時に実行時エラーで止まる
    • 状態遷移しないならなおよい


【チェックリスト3】
理由・目的:ライブラリの設計者・実装者のスキルを確認*2


Requirements:

  1. テストがきちんと行われている事が見込める
    • メソッドの結合度が低く、凝集度が高い*3
    • ソースツリーに自動単体テストが含まれている
  2. 設計書に、次が記載されている
    • データ構造(list, hash ...)、あるいは処理のオーダー
    • メモリ使用量
  3. セキュリティホールがないことが見込める*4
    • 危険な関数の使用を機械的に検査*5し、問題がない
    • 「パーサ」があるならレビューし、状態遷移ベースでないパーサ*6がかかれていない
    • 整数オーバーフローが考慮されている
  4. メソッドの事前条件、事後条件、クラスの不変条件が書かれている


如何でしょう。実際には、「Effecive C++ に書かれているような『常識』を全く知らない人が書いたライブラリは即刻却下」などの主観も交えてしまっているのが、多少悩ましいところではあります。

*1:O(N), O(NlogN) ...

*2:設計文書やソースコードが閲覧可能な場合のみ

*3:クラス間の関連や、メソッドの呼び出し関係を観察し、各メソッドの結合度・凝集度を確認。結合度が高すぎたり、凝集度が低すぎたりするメソッドが多ければ、単体テストがあまり行われていない可能性がある

*4:「insecureならばunstable」はほぼ常に真。insecureなライブラリを採用すると安定性でも苦労する

*5:RATS, QAC++ 等を使用

*6:パーサジェネレータを使用しておらず、かつ一文字づつ読まない、strchr関数やstrtok関数を使ったような、悲惨なパーサー