車輪の再実装

「俺のソースだから」というプログラマは死んだらいいのに - 神様なんて信じない僕らのために に関連して,Twitter で「車輪の再発明」の意義について少しやり取りをしていました.

プログラマが避けて通れない道の一つに「車輪の再発明」があります.私自身が公開している CLX C++ Libraries を見ても「それ Boost で(ry」の嵐で,あの時は勢いで公開してしまった.正直,後悔している.できればなかった事にしてリストから消してしまいたいと言うものもたくさんあります.

このように数多くのプログラマが「車輪の再発明」の罠に悩まされているのですが,車輪の再発明(より正確に言うと,車輪の再実装)にはそれなりに意義もあります.そこで,リンク元の記事の意図とはずれそうですが,今回は車輪の再実装の意義について.

再実装は背景を理解する作業

車輪の再実装の利点の一つとして,既存の実装(のインターフェースなど)がなぜそうなっているのかを理解できる事が挙げられます.

私は,大学で数年間プログラミングの講義,演習を受けてきましたが,(条件分岐,ループなどの基本的な概念は理解できましたが)正直あまり実にはなりませんでした.周りの友人・知人に聞いても同様の回答をする人が多いように思います.この原因の一つに,「何か良く分からないけどそう言う風に記述するもの」で終わってしまうからと言うものがあるように思います.

個人的な例だと,Java の演習のときにファイルからデータを読み込むコードを書いたのですが,最初にファイル入出力周りのサンプル・コードを見たときに非常に「気持ち悪い」と感じました.

FileInputStream is = new FileInputStream("file.txt");
InputStreamReader in = new InputStreamReader(is, "SJIS");

私は,当初,上記の FileInputStream を挟む理由が分かりませんでした.「何故,InputStreamReader("file.txt", "SJIS"); ではダメなのだろう?」と感じ,無意味なものとすら感じていました.この設計の意味には,C++ で streambuf と stream を(それぞれ継承したクラスを)自分で実装する事でようやく気付く事ができました.

実際に俺俺ライブラリ作ってる身としては、自分でライブラリ設計して実装してみるってのは、車輪の再発明であったとしても勉強になると思うんだが。無論、個人的に学習するなら、だけど

http://twitter.com/SubaruG/status/7116880954

「あるプログラミング言語を理解する事」は,基本的な部分を終えるとその後は,標準で提供されているライブラリなどが,なぜそう言う形を取っているのかを理解する作業になるように思います(開発者達の思想を理解する作業に近いか?).この経緯を知る作業を手助けする方法の一つとして,「再実装してみる」と言う手段は有効なのではと感じます.

他人のソースコードを読むのはやはり難しい

なぜソースを読んだり使ってみたりして理解しないのか?

「俺のソースだから」というプログラマは死んだらいいのに - 神様なんて信じない僕らのために

自分で書かずに既存のソースコードを読んで理解しろ,と言う主張は一理あると思います.ただ,やはり現実的な問題として立ちはだかってくるものとして,他人のソースコードは読みにくいと言うものがあります.私も Boost のソースコードを読もうとすると物によっては挫折するのですが,既存のソースコードを読んで理解すると言う作業は,自分で(取りあえず)実装してみるよりもはるかに多様な知識を要求されます(その言語自身への理解,アルゴリズム,エラー,etc).

この要因の一つに,既存のコードには「核となるアルゴリズム」と「様々なケースに対応するためのエラーチェック」が同時に含まれているから,と言うものがあります.

結局のところ、自分で実装してないときには万能に見えるアルゴリズムも、自分で実装してみれば欠点がたくさんあることに気づきます。そこで、自分で実装していれば、その欠点との折り合いのつけ方、用途が決まったときに機能を限定することでの欠点の解消、別のアルゴリズムの開発へのモチベーションと、「次」へ続いていきます。

「車輪の再発明をするな」の流行は孔明の罠

個人的な経験ですが,既存のコードよりも優れたものを再実装できるケースは稀であると思います.多くの場合は,まず始めに「核となるアルゴリズム」を実装してみて,その結果発生した問題へ順次対応していった結果,既存のコードと同じ形に終息したという例が多いように感じます.

しかし,この過程を踏む事によって,そのコードにおいて「どこが核となる部分か」を理解する事ができます.もちろん,既存のコードを読んでそれらを理解できれば文句ないのですが,覚えたての頃ではそれは至難の業です.「車輪の再実装」は,これらの一連の作業を段階を追って少しずつ理解できると言う利点があります.

「俺のソースだから」の話、自前で作っちゃうのは状況にもよるけどそれなりに理にかなってると思うんだけどなぁ。特にSTLみたいなものって実は自分で同様のものを作ってみた経験がないとまともに使うのってかなり難しいだろうし。

http://twitter.com/wraith13/status/7117006102

車輪の再実装時に注意する事

ここまで「車輪の再実装」の利点を述べてきましたが,やはり「車輪の再実装」を行う際には注意する事があります.今回は,個人的に注意しておいた方が良いと思う事をいくつか列挙して終わろうと思います.

1. 「既に誰かが実装しているはず」と言う疑いを持つ事

「車輪の再実装」を行うときに最も重要なのは,自分が車輪の再実装をしている事をきちんと認識している事だと思います.

車輪の再発明」という言葉は、目の前を車がぶーぶー走っているのに「俺車輪なんてすごい仕掛け思いついちゃった。天才じゃね?」と言っているアホに投げつけるべき言葉じゃないのかと。

車輪の概念を再発明してもしょうがないわけで - novtan別館

自分が「車輪の再実装」を行っている事をきちんと認識できていれば,既存のコードを参考にしようとしたり,既に発覚している問題点を探そうと言う意識も生まれます.また,場合によっては「再実装はしない」と言う選択肢も取れるようになります.

しかし,きちんと認識していない場合,ひたすら暴走を続けてしまい,しかもほとんど得るものはなかったと言う結果になる危険性が高まります.

2. 「既存の実装には何かしらの意味があるはず」という意識を持つ事

プログラミングを理解する上でまずい事の一つに,自分の理解の及ばないコードに遭遇した際にそのコードを「ダメなもの」と決めつけてしまう,と言うものがあります.

加えて「C++ってこういうところが糞だよね」っていう事が多く、それは理由があってそうなっているんだよね、ということを理解しない。多くの場合、全ての言語機能には「理由」があるのだが、それに対して「なぜ」ではなく「糞」と片付けてしまう。

あくまで「自分が使って不都合だと感じたらその機能は糞」なのだ。他の理由があってそうなっているとしても。

「俺のソースだから」というプログラマは死んだらいいのに - 神様なんて信じない僕らのために

「なんでこんな訳の分からない実装になってるんだ・・・こうやった方が絶対に簡潔に記述できるはずなのに」と言う疑問にはたびたび遭遇します.しかし,多くの場合,必ずそれには理由が存在します.何かしらの別の問題が存在しており,それら全てを考慮した結果として,そう言う「めんどくさい」実装になっています.

そう言った種々の問題は,一見しただけでは分かりません(気付かない).そのため,自分で再実装してみる際には,この「必ず何かしらの理由があるはず」と言う意識を持つ事が必要となります.

3. 時と場所を選ぶ事

最後に,「車輪の再実装」も良いけど,時と場所をきちんと選んで他人は巻き込まないようにしましょう(w