オブジェクト指向は失敗だった

オブジェクト指向プログラミングは失敗だった――以前から思っていました。

okuranagaimo.blogspot.com

オブジェクト指向プログラミング (OOP) が人類にとって早すぎたか、人類には OOP が向いていなかった。世の中の Java で作られたプログラムのほとんどは、Java に付属する OOP っぽい機能を使うことで余計に複雑になっているように思います。ここでいう複雑さとは、頭が整理されていない状態、頭が構造化されていない状態のことです。例えば、インスタンスなんて作らずに全部 static メソッドでベタ書きされた方がよっぽどわかりやすいのに、それができてしまうからという理由で要らぬ副作用、すなわちオブジェクトの状態の変化が入りこんで、おかしなことになっている様子に出会ったことは何度となくあります。

おそらく原始的で単純な OOP で作られたプログラムはそこまで問題ではない。データ構造があって、その操作がメソッドになっている―― 例えば toString() みたいなデータ構造を変換する操作をデータ構造に集めることはおかしなことではなくて、toString() みたいな共通化された I/F が問題をシンプルにするのは疑いようのないことだと思います。そのデータ構造を文字列化したものが欲しいときに、toString() メソッドを呼ぶだけで済んだら、話は簡単になりませんか。

問題はそもそもデータ構造だけでは世界は表現できないことと、「継承」という要らぬものが導入されたことだと思います。

オブジェクト指向プログラミングでは、現実世界の森羅万象をプログラムに表現できるなんて言説をどこかでみたことがあります。しかし、それは無理です。クラスという表現の形式は、現実世界をモデル化するには十分な表現力をもっていない。そもそもプログラムとは何かを「する」ためにあるものです。何かをすることを私たちはしばしば処理といいますが、処理すらクラスで表現すると難しくなります。

ただのサブルーチン(関数)だけの方がクラスよりよっぽど処理の表現として優れています。処理をクラスで表現しようとするから、-er みたいな名前のクラスができて、処理だけするクラスの中にフィールド変数が現れて、処理の中でそれを触ったりすることが行われる。単一責任の原則にしたがって、1個の処理だけする -er みたいなクラスとは、要するに関数オブジェクトです。こんなもの作るなら、ただの関数の方がよい。

継承も同じことで、処理をする部品(メソッド)を共有したかったら、関数を別に切り出して共有すればいいだけだ。クラスである必要がない。また、階層構造のモデルで、問題を表現しきるのが難しいというのはリレーショナルデータベースを使ってたら知っているはずなのに、どうしてオブジェクトの関係を階層構造で表現したいと思うのでしょう。継承なんていらない。処理だけ欲しければ関数の方がいい。

動的に処理を切り替えたければ関数を切り替えればよい。デザインパターンっぽいものは、要するに処理を関数オブジェクト化してクラスとして切り出したら、切り替えられて便利だよねってだけのはなしです。つまり、出来の悪い関数プログラミングです。関数を値として渡せたらそれで十分だ。でも、それも下手に使われるよりはベタ書きの方がずっといい。

処理と呼ぶものは関数で事足りる。クラスはデータ型とその操作のための I/F としての役割で十分だ。

プログラミングというのはただやりたいことを順序立てて書くだけのもので、それ以外のことを考えないようにしたい。処理をオブジェクトで表現するにはどうしたらよいのだろうとか共通化するにはどうしたらよいのだろうなんて無駄なことを考えなければならない OOP は、不完全な枠組みだったと思います。