独自ライブラリの問題点

独自ライブラリの最大の問題点、それは google できないところwww
自社で作っているライブラリとか、google しても当然ヒットしない。するわけない。
そうなると、使い方がわかんなかったり、潜在的なバグがあったりしたら、
ライブラリのソースの中まで追いかけて見るしかない。

それがオブジェクトを継承しまくったり、委譲しまくったりして超深い階層をなしていたりすると最悪。
俺は機能を開発しているのか、ライブラリのデバッグをしているのかといいたくなる。

プログラムにはバグがつき物。だから、ライブラリにも当然バグはある。
だったら、変にこりまくって深いつくりにするより、より薄く簡単に解析できる構造を作るべきではないだろうか。

俺が考えるに、ライブラリは2つの系統に分かれると思う。
1つは、フレームワークや基本的な部分を提供する層。
2つは、便利な関数、機能層。

たいてい問題を起こすのは、最初のフレームワークや基本的な部分だ。
なぜか?
後者は、大抵がAPIをラップするぐらいの簡単な構造になっていることが多く、
前者は、複雑な構造になっている場合が多いからだ。
C++でがんばって、javaみたいなストリームを提供してめちゃくちゃになったり、
ヘタに多段構造をやってめちゃくちゃになる。

そして、いざバグを見つけて修正しようとも、いろんなところで使われているから下手に直せない。
自動テスト等あれば変更も容易なんだろうが、そうではない環境が大半だろう。

たいていの場合、ライブラリなどの幹線機能をバージョンアップできるのは、開発初期から中期にかけてぐらいだろう。
終盤で問題が出ても間に合わないし、いまさら変更できない。
開発初期から中期だったら、まだ何とかなるだろうし、今後来るであろう検証フェーズでどうにかなるかもしれない。

だから、バグを抱えた部分をライブラリ以外の場所で強引に吸収する。
コピペしたり、継承したりして MyLib とか強引に使い始める。
こうやって、ライブラリは fork していき、だんだんライブラリの意味を成さなくなる。
このライブラリは意味あんの?って話になる。


こんな不幸にならないために、ライブラリアンはどうライブラリを設計すればよいのだろうか。

ひとつは、多段の層を成しているのがまずいのだから、なるべくフラットに構造にする。
ひたすら薄く、薄く、KISSな感じに実装するべきだ。
機能をしぼりまくって、APIを軽くラップしたぐらいに収めるべきではないだろうか。
実装が簡単になればなるほど、バグが発生する確率は低くなるはずだ。
それに、ライブラリがバグっていたとしても解析はしやすいはずだ。


次に、エラーを握りつぶさないことと例外以外のエラー通知を考えること。
エラーを握りつぶされるとそれを使うプログラムは細かなエラーハンドリングができなくなりる。
なるだけエラーを握りつぶさずに上位層に伝えるようにしよう。

また、悩ましい問題が例外だ。
どこまでが例外かをはっきりさせよう。例外以外でもエラーをトラップできる仕組みを設けよう。
たとえば、ファイルクラスがあったとする。こいつが fopen に失敗するのは例外か、それともそうではないのか。

class File
{
  public:
     bool Read(const string & inFilename)
     {
        FILE * fp = fopen(inFilename.c_str() ,"rb");
        if (fp == NULL)
        {
        	//↓これがありかどうか。
        	throw Exception(string() + "ファイル" + inFilename + "が開けませんですた");
        }
        //skip
     }
};

個人的には、例外を発生させないでファイルがあるかどうか判別できればありだと思う。

class File
{
  public:
  	 //ファイルの存在判定!
     bool IsExist(const string & inFilename) const
     {
     	return 0xFFFFFFFF != GetFileAttributes(inFilename.c_str());
     }
     bool Read(const string & inFilename)
     {
        FILE * fp = fopen(inFilename.c_str() ,"rb");
        if (fp == NULL)
        {
        	throw Exception(string() + "ファイル" + inFilename + "が開けませんですた");
        }
        //skip
     }
};

IsExist を呼び出せば、ファイルがあるかどうかを判別できる。
これがあれば、 Read でファイルがなくて例外でもいいだろう。

なぜか?

もし、 IsExist がなければ、ファイルがないことをプログラムが知ることが非常に困難になるからだ。

File f;
try
{
    f.Open("さくらたんの得ろ画像.jpg","rb");
}
catch(Exception &e)
{
     //ファイルがなかったのかー
     //ファイルがない場合は新規に作成する。
 
}

そもそも例外はフラグではない。
上の例だと例外をフラグのように扱うしかファイルの存在を知る方法がない。
これでは、上のようなダーティーな構造を使うか、独自で isExist を実装することになるだろう。
そうやって、ライブラリは forkしていく。


次に、便利なものは自作しないで取り入れて、ネストを少なくしよう。
std::string に不満があるからといって、 std::string を自作する必要があるだろうか。
自作すればするほどライブラリはでかくなって、複雑で奇怪でバグだらけなものになっていく。
std::string と 独自 String が入り乱れるようなソースコードなど誰が望むだろうかwww


まとめ!
自作ライブラリの問題点は Google しても答えが出てこないところ。
自作ライブラリのバグはアプリケーションに重大な影響を与えるので大変。
ライブラリは薄く、KISSな感じで作るとバグも少ないし、利用するプログラマもハッピーぢゃね?
エラーは握りつぶさないこと。
例外以外でのエラートラップの仕組みをちゃんと提供すること。
std::string を自作するアホは市ね。