Objective Cat & Functional Cat

オブジェクト指向の猫と関数型の猫の違いについて考えている。猫が鳴くこと、人間が猫の鳴き声を聞くことについて。その設計について。

念のため注釈しておく。本エントリは、特定のプログラミング言語の特徴について論じるものではない。言うまでもなく、某宗教戦争とも無関係である。ただ私が、使用する言語の特徴によるプログラマの思考工程の差異を確かめたくなって書いている。有用であるか否かは、人によるとしか言えない。いつもどおりの悲しい話である。

オブジェクト指向パラダイムの猫

オブジェクト指向の猫は言うまでもなくオブジェクトである。いくつかのパターンを考えてみよう。書き手の技能の都合上、Javaのように見えなくもない架空の言語を使うことにする。

public class 猫 {
    public void 鳴く() {
    }
}

この時点で、私なら一旦手が止まる。鳴くのは猫の機能なのだろうか、鳴くのは猫だけか? 犬も鳴くしツクツクボウシも鳴くだろう。鳴かない猫だっているかもしれないし、toString() したくない Object だってあるはずだ。ニャーという鳴き声を文字列かなにかで定義したほうがいいかもしれない。あるいは、動物というインタフェースに対して猫という抽象度の高いクラスを実装し、さらに猫の種類によってサブクラスを作ったほうがいいのではないだろうか。

まずいことに、この鳴き声を知覚するためには、「聞く」機能を持つ「人間」というオブジェクトも存在しなければならない。猫を認知するクラスが必要なのだ。「人間」は耳というパーツに加え、聴力というパラメータを付加しなければならない。

事態をさらに複雑化するとすれば、猫の鳴き声を聞くのは人間だが、しかしながら、猫にも耳はある。

おそらく多くのプログラマが、自分の使っている言語を利用して一度は「人間」をはじめとする有機物を表現することを試みるだろうと思う。ことに私はそういったお遊びを好むため、これまでにも何度となくやってみた。しかし何度考えても、どこか不自然な気がしていた。今もまた、プログラミングするかのごとく「猫と人間」を自然に表現することは不可能ではないかという気分になっている。

関数型パラダイムの猫

某おじさんの提唱する static を使えば、ある種の問題は解決できるかもしれない。要はこのように書く。

public class 猫{
    private String 鳴き声 = "ニャー";
    世界に一般的に存在する動詞.鳴く(鳴き声);
}
public class 人間{
    private int 聴力 = 100;
    世界に一般的に存在する動詞.聞く(聴力);
}

public class 世界に一般的に存在する動詞{
    public static void 鳴く(String 鳴き声){
    }
    public static void 聞く(int 聴力){
      if (聴力 < 基準値) {
         throw new Exception("聞こえない");
      }
    }
}

なんとも複雑であるが、オブジェクト指向的な記述を用いるとしても、ここまでくると、もはや関数型のパラダイムに近づいているとも言える。関数がオブジェクトとは独立して存在しているからだ。というより、このような設計こそオブジェクト指向パラダイムの本領であるとも言えるかもしれない。

猫は猫である。関数型の手法でも、猫は猫というデータで表現することができる。そして、鳴くという関数があり、聞くという関数が、ただただ定義されている。人間と猫の関係が発生した際にのみ、鳴くと聞くを合成する。

いや、ちょっと待ってほしい。
猫はいつ鳴く? 尻尾を踏まれたとき? もしそうならば、「尻尾を踏む」というイベントをオブジェクトとして定義しなければならない。そのイベントを受け取るオブジェクトもまた必要だろう。

ここまで複雑になるならば、世の中には既にパターンの一つや二つあるのではないか。そう、デザパタだ。天地創造するためには世界は new できないといけないし、世界が複数あると混乱するから世界は Singleton で実装したほうがいいかもしれない。世界のコンストラクタは private であって、世界はインスタンス化された世界自身そのもの以外にありえない。

\(^o^)/

ふたつの世界の猫

どちらも猫であるし、どちらもより具体的に実装することが可能だろう。どちらが優れているか劣っているか、そういうことではないし、それはどうでもいい。自分にとってどちらの武器が扱いやすいのか、それを把握した上で、プログラミングという作業を実施したいと思っている。

「猫が鳴く」というただそれだけの現象を表現しようとすると、人間という知覚者が必要であり、猫が持つべき機能が猫ではないところに付加されたり、犬になったりする。オブジェクト指向の猫は千切れる猫だ。オブジェクト指向の問題点は、工夫しようとすればするほど、あるいは、拡張性を持たせるとか、安全性を高めたいといった場合に、すべてがより複雑になり、頭脳明晰に生まれついた人間でない限りは容易に間違える、そういう手法なのではないか。少なくとも、私はそう考え始めている。

誰もが、自然言語の延長のように使えるプログラミング言語がほしい、と思ったとき、オブジェクト指向的なパラダイムしか選択肢がなかったとしたら。子どもたちが遊びの延長として手を伸ばしやすいパラダイムはどれだろう。操作性に優れた統合開発環境だけが答えなのだろうか。オブジェクトとメソッド、データと関数。ふたつの世界を行き来した果てに、なにか別の解が用意されている可能性はないだろうか。

それにしても、「猫が鳴く」という単純な行為を表現したいときでさえ、プログラマが持ちうる武器は、まだこんなにも複雑で、不器用だ。「猫」を「業務」に置き換えたとしても、同じではないかと思う。メールを書く、チームメンバーのタスクを管理する、給与・賞与を決定する、在庫や販売数を管理する、外貨を管理する、日々の、あらゆる、雑多な業務。それらをさらに複雑化する、なんらかのソフトウェア群。

自分が知覚しようとする、簡単で、つまり誤解の少ない現実の事象を、知覚そのままに、醤油差しから小皿に醤油を注ぐがごとく、誤解なく、行うためのプログラミング言語は、いったいどのような顔つきなのだろうかと、結論の出ないまま、ふたつの世界の猫を愛でる。

という、悲しい話。