2014/12/29

すべてのソースコードが手元にあるのに不要な抽象化を行うのはよくない

「よい」とされているプログラミング手法のひとつに差分プログラミングがある。クラスを継承して親クラスとの差分だけのコードを書けば、親ですでに実装されている機能はそのまま使えて、かつカスタマイズもできるというやつだ。

たとえばGUIのボタンをカスタマイズしてマウスオーバーするとなにかちょっと特殊なことを行うボタンを作りたいとしたら、ボタンクラスを継承して、マウスオーバーのイベントハンドラをちょいちょいとカスタマイズしてやればよい。差分プログラミングは大変素直でよいプログラミング手法のような感じがする。

よいのはよいと思う。

しかしこういういい例だけをみてそれをどこでも真似しようと思ってしまうと、不必要な抽象化を積み重ねる困ったプログラマになってしまう(そういう人は結構たくさんいる)。自分でプログラムを書く場合には、よくできたクラスライブラリやフレームワークをお手本にして抽象化を行うのは、ほとんどの場合むしろよくないことだと思う。

なぜかというと、よくできたクラスライブラリは不特定多数のプログラマが使うことを前提に設計されているので、いろんなところでうまく継承関係などをつかって、必要十分な(ライブラリ作者には未知のニーズも満たせる)柔軟性を提供するようにできているからだ。

一方で、自分のすべてのコードが自分の管理下にあるのなら、そのような柔軟性は不要というか過剰だ。不要な抽象化を行って素晴らしいクラス構造を作ってもコードの量が増えてしまうだけだ。外部のクラスライブラリやフレームワークと違って自分のコードは自分で変更できるのだから、新規の変更でも必要に応じて既存のコードを変更すればよい。逆に言うと、あとで既存のコードはいくらでも変更できるのだから、最初から凝ったことはしないほうがよい。

新しい変更が一箇所にまとまる、というのは別にコードの良さという観点では大して重要ではない。全体として素直なコードになっているほうがずっと重要だ。(新しい機能が新しいクラスを定義するだけで実装できるというのは、特にソースコードのついてこないクラスライブラリだと必須条件だが、自分でコードを管理している場合は関係がない。)

「クラスライブラリを使うときにクラスライブラリのほうのコードを変更する機会はない。メジャーなクラスライブラリはよい設計だとされている。従って自分でクラス階層を作るときにもそれと同じようなものを作るべきだ」という考え方は誤謬だ。自分の具体的なプログラムはクラスライブラリやフレームワークのような抽象的なものとは違う種類のプログラムだ。考えすぎるのをやめて、必要なことを素直なやり方で直接実装するのがよいと思う。

Rui Ueyama @rui314