何故プログラムの再利用というのが難しかったのか、という話をしていたら、「えっ?別に難しくないですよね?」とkzysに言われて、ちょっとその辺の話をしてみたくなった。
個人的にソフトウェアの再利用が一般的と感じられるようになったのは、JavaでJakartaが有用なライブラリを揃え始めた頃からだ。 再利用される方の話は現代の普通の話なので良いと思う。 ではそれ以前の何が難しかったのか、と思うと、CやC++の難しさが多い気がしてきた。
C++の再利用が何故難しいのか、という話をすると長くなる上に今更なので、 今のプロジェクトでさしあたってうまく行かないと感じる、今、目の前の問題だけを書いてみたい。
共通のプリミティブが無い難しさ
例えばスレッド周りの何かのライブラリを再利用したい、と考えたとする。 この時、Win32 APIの同期プリミティブとQtの同期プリミティブとSTLの同期プリミティブとpthreadの同期プリミティブは、同じ機能を提供するが、相互に取り替えて動く保証が無い(あるかもしれないし幾つかの組み合わせはある事も知っているが、一般にあるか無いかを判定するのはかなり難しいし、幾つかの組み合わせは怪しいのも知っている)。 QtでGUIとタイトに相互作用するような所で使いたい場合、 Qtの並列プリミティブで無いと困ってしまう。
その結果、いろいろな環境で動く、スレッドプールを前提としたノンブロッキングなFuture、 みたいなライブラリを作るのは、なかなか難しい。STLのスレッド前提のものは作れるのだけれど。
Win32 APIやQtが、現在のSTLを元に作られていれば、こういう問題はなかったとは思う。 でもどちらもSTLのスレッドより以前から作られていた物だし、そういう物はまだまだ世の中多い。
STLにまだ入ってない物も多い。今更filesystem周りが入った、という事からもそれがわかる。
Javaや.NETなどの環境や、pythonなどの普通のLLには、 ベースと出来る範囲がずっと広く、それらに依存した物は普通にどこでも動く。 言語の標準となる機能の範囲がC++は狭い。特にどの環境でも使えるC++のバージョンに限定すると、さらに狭い。
歴史をなかなか無かった事に出来ない
そろそろVSもXcodeもNDKもQtもすべての環境がCMakeになって、 最初からconanをサポートして、 最新のSTLにあるものはSTLを、boostにあるものはboostを使ってくれて、 STLのスレッドや並列周りもfollyの奴くらいにいい感じのになってくれればいいのでは、 という気はするのだけれど、今からそうはなってくれない。(なってくれていいのよ?)
過去の歴史はそのままに、CMakeでもプロジェクトファイルが生成出来ます、 みたいなのだと、どうしてもバージョンアップなどのトラブルで後手に回ってしまう。 残念な事にC++が相手にするような環境のうちの幾つかは十分なサポートがされてなく、 自分たちでどうにかせざるをえない事も多い。 こういう時に何かが一段その環境のネイティブな仕組みの間に挟まってると、 メンテがすごく大変になる。 公式の側がCMakeになってくれればそういう問題も無いのだが…
手元のコードベースの側も、過去のいろいろなプラットフォーム上での様々な固有事情を踏まえたプロジェクトファイルやらビルドの仕組みを内包していて、全てを新しい仕組みに移動するのもなかなか大変。
本来は最新版だけがきっちりサポートされてればいいはずなのだけど、メジャーバージョンアップをするとめちゃくちゃ不安定になって特定のバージョンで止めなきゃいけないみたいなくされ環境があり、 その環境がサポートしているコンパイラはちょっと古くて最新のC++機能が使えなかったりとかがあり、 いろいろな事情でVC2008もサポートしないと駄目とかがあり、 内輪の事情で特定のRHELでビルド出来ないと駄目とかもあり… みたいな、プロジェクト固有の事情からもなかなか脱却出来ず、 「本来はこうあるべき」という姿になかなか出来ない。
他への依存をみんなしたがらない
おのおのが歴史を持ったプロジェクトに使ってもらう事を考えると、ライブラリ作者は使う側のビルド環境などを想定出来ないので、他のライブラリへの依存の仕方も難しい。 「このライブラリを動かす為には、ライブラリAとライブラリBとライブラリCを適切に設定してパスをXXXで通るようにしてください」 みたいな事をお願いすると、使ってもらうのもきびしい。
なので複数のライブラリに依存したライブラリを使ってもらうのはすごく大変。
結果として、STLとboostのヘッダオンリーな物あたりだけに依存したライブラリくらいしか使いたくない。
コデックとかflatbuffersとか他への依存が少ない小粋なライブラリは使えるのだけれど、 ノンブロッキングなfutureを返すhttpのライブラリ、 とか、ノンブロッキングなfutureを返すノンブロッキングioなファイル周りのライブラリ、 のように、他の結構大きな物に依存するライブラリは全然ない。
そもそもライブラリが言うほど無い
「iOSならGCD、WindowsやQtならシステムのスレッドプール、 AndroidならSTLあたりで書かれた自前実装のスレッドプールを使ったExecutor」程度のライブラリも存在しない。
Windowsのフルな機能にアクセス出来る、Direct2DあたりをベースにしたモダンなGUIライブラリ、程度のものも無い(xi-editor retrospectiveでも、There is no such thing as native GUIと言っている)。WTLをforkして自前で作るか?と思うくらい無い。
WindowsのAsync IOとOS XのDispatch SourceとLinuxのepoll周りを吸収してよ、くらいでも普通に無い(このくらいなら頑張って探せばあるかもしれない、自分は見つけられなかったが)。
「インテリセンスを壊さない」UnitTestライブラリ、程度でも見つけられなかった(仕方ないので自作した)。
みんな似たような物作っているくせに、全然再利用出来るものが無い。