残念ながら、第8回「建築家の視点、アーキテクトとしての共通認識」の最後でお約束した第2シーズンには、もろもろの事情があって今回はまだ突入できなかった。それまでのつなぎとして第1シーズンの番外編をお届けしようと思う。
人はまねることによって成長する。オブジェクトも同じだ。オブジェクトにはクラスだとか、継承だとか、多相性だとかいろいろな側面があるけれど、実はそんなのはどうでもよくて、本質は何かを「まねる」ことにある。1つ1つのオブジェクトは何かをまねる、シミュレートする存在だ。
まず何よりもオブジェクトそのものがコンピュータ(あるいはCPU)をまねしている。それぞれのオブジェクトはレジスタあるいはメモリ(=インスタンス変数)とプログラム(=メソッド)とプログラム・カウンタ(=継続)を持っているのである。そう考えればメッセージ交換(=メソッド呼び出し)はネットワークで結合されたコンピュータ間でやり取りされるパケットに相当する。メッセージ交換の考えを発展させていくと、オブジェクトを組み立てる、目に見えない接着剤としてのパターンという概念にたどり着くのだが、その話はまた別の機会としよう。
継続(continuation)とはスタック・フレームとプログラム・カウンタを抽象化した概念である。継続はどんなプログラミング言語にも存在するはずだが、継続を明示的に扱えるようにしたプログラミング言語はそう多くない(Scheme、Continuation based Cなど)。継続を利用すると計算の順序(例外とか大域脱出とか)をきれいに記述することができるし、応用範囲も広い。興味のある人は例えば琉球大学の河野真治さんの論文を見るといい。
もちろんオブジェクトはCPUだけをまねしているわけではない。そのうえで別の何物かをまねすることによってソフトウェアが作られる。では何をまねすればいいのだろうか? オブジェクトの本来の考え方はこうだ。「あるがままをまねなさい」、つまり対象となる問題領域に存在するモノをオブジェクトとしなさい。そのときにデータベースだの、入力画面だの、サブシステムだのに惑わされてはなりません、と。
例えばホテルの顧客管理システムを作ろうとしたとする。結跏趺坐(けっかふざ)して目を半眼とし、頭と心を空っぽにして、おへその上辺りにホテルのフロントをイメージしよう(まぁそれは冗談で、実際にはビジネス・モデリングだの、ユースケース・モデリングだのをするわけだが:-))。ここで「人」のイメージが浮かんだ。じゃあ、あるオブジェクトに「人」をまねしてもらおう、ということになる。本当はいきなりクラスではなく、まずオブジェクトとして作りたいんだけど、たいていのオブジェクト指向プログラミング言語では無理だからこんなふうにしておこう。
class 人 { }
オブジェクト指向の教科書を見ると「現実世界に存在するからといって人なんてモノをオブジェクトにしてはいけません」とか書いてあることもあるが、気にすることはない。もちろんここから骨格とか筋肉とか人体モデリングを始めてしまったら「おいおい、それはちゃうやろ」とツッコミが入ることは必至だが、そんなやつはいない。単に「人」というだけではオブジェクトは人の何をまねしていいか、よく分からないというだけの問題だ。この「人」が実際に何をするのか、オブジェクトがうまくまねできるようにシナリオを書いてあげればいいのである。
例えばフロントにはフロント係の人がいる。そこに電話がかかってくる。「X月X日予約したいんですが……」「はい、お客さまのお名前とお電話番号をお伺いいたします……」。ほらそうすると、ここにはフロント係という人と、電話をかけてきた人がいることが分かるでしょ。そうしたらそれをそれぞれ別のオブジェクトにまねしてもらえばいい。ここで継承とかいい出すと分かりにくいから、それも放っておく。
class フロント係 { } 斉藤さん = new フロント係(); class 電話をかけてきた人 { } お客さまA = new 電話をかけてきた人();
じゃあ「フロント」とか「電話」はどうしようか? 気になるのなら適当なオブジェクトにまねしてもらえばいい。フロントは当分出番がないと思うけど、後々ホテルと顧客のインターフェイスの窓口(ファサード・パターンだ)として使い物になるかもしれない。電話も機器としての電話機を考える必要はない。ここで電話の本質はそれがお客さまとホテルをつなぐチャネルということだ(と、このシナリオを書いている脚本家である私は考える)。
class フロント { } class 電話 { }
シナリオによれば、お客さまが電話をかけてきて、フロント係がそれを取るわけだから、このオブジェクトたちにはこういうまねをしてほしい。
class 電話をかけてきた人 { 電話をかける(); } class フロント係 { 電話を受ける(); }
電話をかけるとはフロントの誰かに電話を受けてもらうことだけど、いまはフロントには斉藤さんしかいないから直接斉藤さんを呼び出すことにしよう。面倒くさいところはみんな文字列だ。
電話をかける(){ 斉藤さん.電話を受ける("X月X日予約したい"); } 電話を受けた斉藤さんは、 電話を受ける(内容){ お客さんの名前 = お客さんA.名前は何?(); お客さんの電話番号 = お客さんA.電話番号は何?(); ... }
ということは、電話をかける人は自分の名前や電話番号も答えられなくちゃいけない。
class 電話をかけてきた人 { ... 名前は何?(); 電話番号は何?(); }
という具合に、まねっこゲームは進んでいくのである。注意してほしいのは次の2点。1つは具体的な最小限のことから始めて面倒くさいことはできるだけさぼりながら、必要になったときにだけ付け足していく。例えば最初はフロント係は斉藤さんだけとして、後で複数のフロント係がいる場合のことを考えるのである。もう1つはできるだけ本質だけをつかまえて変な方向にそれないようにする、それてしまったなと思ったらすぐに戻ってくる。もちろん何が本質かはマニュアルには書いていない。あなたの全人生が懸かっている。
この例ではプログラミング言語風に書いたけれど、もちろんJavaではこうはいかない。いろいろな決まり事をたくさん書く必要があって、書いているうちに本質を忘れてしまう。でも例えばSmalltalkとか(ちょっと譲って)GroovyやRubyのような言語ならばこれに近いことが書ける。もちろん(たいていは動かすことはできないけど)UMLだって大丈夫。つまりこのまねっこゲームとはモデリング=プログラミングの過程そのものなのである。ただし普通のモデリングの教科書には載っていない、極めてボトムアップでコンクリートなモデリングだけど、モデリング=まねることの本質を突いているのではないだろうか。
僕はこれを勝手にエピジェネティック・プログラミング(epigenetic programming)と呼んでいる。エピジェネティック(後成的)とは、イギリスの生物学者C. H. ウォディントンが提唱した発生学上の概念で、砂場の山に水をかけているうちにだんだんと川になっていくように、発生の過程はランダムだけれど最終的にはバランスの取れた落ち着くべきところに落ち着く過程だというのである(『発生と分化の原理』、C. H. ウォディントン、共立出、1968、絶版)。
エピジェネティック・プログラミングはKent Beckのテスト駆動開発にもとても似ているでしょう? エピジェネティック・プログラミングではテストのことは具体的に考えていないけれど、モデル駆動開発と契約による設計の手法を利用している。そしてこのようなプログラミングをサポートするためのOpenMDAというツール開発に参加していたのだけれど、本当の実現にはまだ時間がかかりそうだ……。
山田正樹
(株)ソフトウェア・リサーチ・アソシエイツ 、(株)ソニーコンピュータサイエンス研究所を経て、1995年(有)メタボリックス設立。代表取締役。アーキテクチャ、モデリング、マネージメント、コラボレーションなどを含む広い意味でのソフトウェア・プロセス・エンジニアリングが専門。ソフトウェア・ツール開発、メンタリング、コンサルティングなどを行っている。
Copyright © ITmedia, Inc. All Rights Reserved.