#どう違うのか。
初心者から見たらどちらもよくわからないと思う。僕もその一人だ。オブジェクト指向の本当の利用価値はまだ僕の中では測れないし、関数型もいろいろな人が言っているようにプログラミングがしやすいのかも計り知れない(例えば、副作用がないとかプログラミングがオブジェクト指向に比べて楽だとかだ)。議論を始める前に、どちらの性質を理解してない限り、議論をすることもできない。
だから、まずは初心者を含めた読者に対しても同様に、どう違うのかを見ていこう。
#オブジェクト指向について
オブジェクト指向とはなんぞや、という質問に関してはいくつかの答えがネットでは用意されている。主な答えというのは「哺乳類の分類」だ。哺乳類の分類とは、哺乳類をいう物を親として、それの特性(恒温動物である)を引き継いで、犬は「人間に従う」という機能をつけて、猫には「自由気ままに生活する」という機能をつける。
だが、こんな説明だと普通はわからない(現に僕も大学のときこういう説明を受けて、理解できなかった)。今回はロボットで説明をしてみる。
今回扱うロボットは「轟轟戦隊ボウケンジャー」のロボットだ。ボウケンジャーには「ゴーゴービークル」という乗り物を大元として、作っている。ゴーゴービークルの機能は以下の通りだ。
+ パラレルエンジンというエンジンを積んでいる
+ 冒険仕様になっている
+ 換装できるようになっている
今回の場合だと、「ダンプ」、「フォーミュラー」、「ジャイロ」、「ドーザー」、「マリン」が「ゴーゴービークル」の特徴を継承をしている。
そして、合体はこれらの「ゴーゴービークル」を組み合わせ行う。
オブジェクト指向もだいたいこんな感じで、springでウェブサービスを作るのであれば、springから提供されているオブジェクトを組み合わせて作る。つまり、オブジェクト指向とは使うであろう部品を個々で作っておいてあとで合体させるものだ。
#関数型について
一般的には「ラムダ計算を要したプログラミングスタイル。第一オブジェクトがオブジェクトではなく、関数である」という。これもよくわからない。僕の場合は最初に触った言語が関数型だったので、感覚としてわかるが正確に定義しないといけない場合は難しい。
今回もロボットで例えてみることにしよう。
さっきのロボットの説明を引き継いでみる。さっきは大まかな機能というオブジェクトを引き継いで作るのがオブジェクト指向だったのに対して、関数型は動きのみで作るという感じだ。
ゴーゴービークルを動かすのにも同じような動きがある。例えば、「車輪を回す」、「モーターを回す」、「プロペラを回す」といった具合に、「回す」という動きが共通している。この「回す」という動きを一つの関数として扱う。こうすれば「回す(車輪())」「回す(モーター())」「回す(プロペラ())」といったようになる。こうすることによって、いちいち「回す」というプログラムを書かずに済む。なおかつ、「回す」というプログラムは回転に関するプログラムを外部の変数に対して変えない決まりがある。これによって、どんな機械でも汎用的に機能する、ということができる。
#それでは、自分なりの考えを述べる。
慣れ親しんだのは関数型だが、どちらがやりやすいかは一概に言えない。というのも、オブジェクト指向自体に致命的な欠陥があるわけでもないし、関数型がオブジェクト指向よりも遥かに優れているともいえないからだ。
というのも、どちらとも記述の仕方の違いがある。一方は物事を部品ごとに管理し、もう一方は動きによって管理をするという手法を取っている。細かい部分でお互い一長一短があるのも事実だ。
オブジェクト指向の良いところは、プログラム同士をくっつけたり、受け継いだりすることによって一回オブジェクト指向をある程度理解できれば再利用が楽というところだろう。入り口に躓かなれければ、かなりプログラムが楽になるということだ。
関数型のよいところは、動きによって記述することによって予期せぬ代入に怯えなくて済む。副作用とは、グローバルな値に変化をつけてしまうこと。プログラムが一つならよいが、これがいくつもあったらどこかでバグが起こった時にデバッグが大変だ。関数型の欠点としては理解の難しさだろう。僕の場合はなぜか、関数型に合っていた。だが、調べれば調べるほど難しいということがわかった。Haskellのモナドなどが最たる例だろう。圏論を使ったり、厳密に定義をしている。この定義を読み解くのも難しく、それに加えて数学の知識をある程度持ち合わせてないといけない。
それなら、どちらが一番よいのか?という答えにたどり着かないではない。おそらく、僕の考えでは住み分けが大切だと思う。
オブジェクト指向は工学的な考えが強いと思う。結合や継承というを、数学的に定義するのは難しい。ならば、端から工学、つまり作ることに特化した考え方と定義すればいい。反対に、関数型は数学的で綿密に作りたい、数学的な考えでプログラムを作ってみるというふうに住み分けをする。
ここからが重要なのだが、お互いの世界を行き来できればいい。オブジェクト指向のプログラムでどうしても副作用を起こしたくない!という場合に関数型のプログラムを使えたり、反対に関数型でやっていたがデスクトップ周りのプログラムでどうしてもオブジェクト指向のプログラムが必要!となったら、オブジェクト指向が使えるようにすればいい。
これが現状できるのが、僕の考えだと「JavaScript」だろう。typescript,es6を使うことによって住み分けられる。他の言語でもできるであろうが、厳密に関数型を定義できていない言語もあるので、alt.jsで言語が作れるJavaScriptが一番良いと思う。
#まとめ
長々と語ったが、重要なことはどちらが劣っているとは測れないということだ。たしかに、関数型は「古くて新しい」。反対にオブジェクト指向は「新しくて古い」。だが、これらは単なる思い込みだろう。極論を言ってしまえば「どちらも正しく世界を記述することができる」。
これからもこの議論は続くであろうが、これを読んでちょっとでも関数型に興味を持った!オブジェクト指向に興味を持った!という人がこの議論を発展させてくれればいいなと思う