読者です 読者をやめる 読者になる 読者になる

車輪の再発明をしなければならなくなる時

http://d.hatena.ne.jp/tt_clown/20091228/1261996214
http://d.hatena.ne.jp/Isoparametric/20091230/1262134418

なんか昨年末の話で、反応するには少々遅い気がするけど、個人的に車輪の再発明をするに至る場合や理由について考えてみる。


勉強のために既にあるものを自分で書くのよくある話というか、そうしなきゃ勉強にならないから当たり前として、*1それ以外の理由について考えてみる。

  • コーディングスタイル
  • ライセンス
  • 巨大すぎるライブラリ

ほかにもあるけど、関連エントリで内容がかぶってしまっているものもあるので、とりあえず上記の項目についてだけ書いてみる。

コーディングスタイル

他人のソースコードを自分のソースコードに取り込む際、そのソースコードのスタイルが自分がいいと考えるものと懸け離れていて採用したくない場合があるかもしれない。コーディングスタイルは一貫しているのが望ましいが、もしかしたらコーディングスタイルの一貫性を保つために大幅な修正が必要になるかも知れない。ただ、これが原因で車輪の再発明をしてしまうケースは希だと思う。(そういったのに厳しい開発コミュニティや企業だと話は変わってきそうだが)

ライセンス

自分が書いたソフトウェアのソースコードを配布する際、そのソースコードに何かしらのライセンスを適用することはよくあるだろう。なんとなくGPLにしてみたという人もいればMITやBSDライセンスようにGPLに比べて若干緩いライセンスを好んで採用する人もいる。ソースコードGPLで配布するなら問題ないが、それ以外の場合だと、他人のソースコードを取り込む際はそのソースコードのライセンスがGPLかどうかよ〜く確かめなければならない。GPLソースコードを取り込んだ場合、あなたが取れる選択肢は一つしかない。配布するソースコードのライセンスをGPLにすることだ。プロプライエタリなソフトウェアを開発している企業のみならず、個人でも自分が開発したプログラムをGPLではなく、MITやBSD、LGPLなどのライセンスで配布したいはかなりいるだろう。そういう人はGPLソースコードを取り込むのはあきらめ、非GPLソースコードを取り込むか自分で車輪を再発明するしかない。そして前者が見つからず後者を選択せざるを得ないケースはある。

巨大すぎるライブラリ

例えば、あなたが配布するソフトウェアをソースコードからビルドするのにBoostが必要だとしよう。Boostは超巨大なC++のライブラリでsourceforgeで配布されている圧縮されたものでも33.3MBもある(バージョンは1.41)。もし、自分が書いた数十KB程度のソースコードに数十MBのライブラリがくっついてくるとしたらどう思うだろう?

自分で使うプログラムを書いたり、あるいはバイナリを配布する分には、boost を使ってもまったく問題ないんですが、非C++プログラマむけにソースコードを配布してコンパイルしてもらう前提だと、boost への依存は避けたいな、と思っています。今回は、そもそもそういうプログラムを書いていて、その中で使える簡単な JSON ライブラリを求めていたのでした。
C++ を書いていて boost に依存したくない理由

Q4Mに必要なBoostのライブラリはヘッダファイルのみで構成されているので、これで解決できるが、Boost::RegexやBoost::Serializationのように別途ビルドが必要なものを使う場合は話がややこしくなり、ライブラリ自体を配布するソースコードに含めて一緒にビルドしてしまうか、ユーザに自分でビルドしてもらうかになる。開発者はそれでいいかもしれないが、ユーザは嫌がるかもしれない。Boostを使ったオープンソースC++プログラムをあまり見かけない理由は上記に起因するところが多いと僕は思っている。事例がQ4Mだけだと十分じゃない?じゃあもう一つ紹介しよう。以下はmonotone*2に含まれるNEWSのファイルを部分的に切り取ったものだ。

- Monotone now uses the Perl-Compatible Regular Expression
(PCRE) library for all regular expressions, instead of the
boost::regex library. This means that external Boost
libraries are no longer required to build or use Monotone.
If building from source, you will still need the Boost headers
available somewhere. See INSTALL for details.
(Monotoneは正規表現のためにboost::regexのかわりにPCREライブラリを使用することにした。
これが意味するのはMonotoneを使用したりビルドするのに外部のBoostライブラリは
必要ないということだ。ただ、ソースからビルドするのであれば、
まだBoostのヘッダファイルがあちこちで必要になる。詳細はINSTALLを見てくれ。)

Boostのようにいくら既にあるライブラリが便利でも大きすぎて採用するのに気が引けてそれが原因で必要最低限の処理ができるライブラリを再発明するケースは結構あるのではないかと思う(↑だと別のライブラリを採用することで解決しているが)。ほかだとQtとか。

具体的な事例

最後に、巷でよく使われているであろうソフトウェアで、「車輪の再発明(実装?)」がされているものをいくつか挙げておこう。ただ、何故「車輪の再発明」がされているのかについてはあまり述べないでおく。(というか知らないし)

MySQL

MySQLC++で書かれている。しかし、std::stringは使われておらず、独自のStringクラスを持っている。それどころかlibstdc++にさえリンクしていない。(単に移植性重視?)

Apache

Apacheはapr(Apache Portable Runtime)というクロスプラットフォームライブラリを持っている。これにはCの標準ライブラリにはないメモリプール、ハッシュ、動的配列といった便利なユーティリティの他にスレッドやファイルシステム、ネットワークなどに関連する処理における各種OS間の差異を吸収し、aprがサポートするどのプラットフォームでも一貫した動作をさせるという役割がある。そしてApacheとaprは昔は別々に配布されておらず、元々両者は一つだった。*3aprと似たような機能を提供するライブラリとしてglibcがある。あと、nginxのコードを見たらaprの機能と類似する機能がたくさんあった。少なくとも自前でメモリプール、ハッシュ、動的配列を実装しているのは確認した。(しかも実装アイデアがすごく似ていた)

Subversion

Subversionはその昔、diffの処理を実行する際、CVSと同じく外部のdiffツールを呼び出していた。(例えばGNU diffutils)理由は知らないがその後、Subversionの開発者達は外部のライブラリを採用せず自前のdiffエンジンを書いた。

*1:そもそも情報系の学生が授業で毎年大量の車輪の再発明を行っているだろうに

*2:分散型バージョン管理システムの一つ

*3:正確にはaprはApacheの一部だった