09.epigenetic

変幻する実行可能知識 09

「まねるといふこと」

人は真似ることによって成長する. オブジェクトも同じだ. オブジェクトにはクラスだとか, 継承だとか, 多相性だとかいろいろな側面があるけれど, 実はそんなのはどうでもよくて, 本質は何かを「真似る」ことにある. 一つ一つのオブジェクトは何かを真似る, シミュレートする存在だ.

まず何よりもオブジェクトそのものがコンピュータ (あるいは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点. 一つは具体的な最小限のことから始めて面倒くさいことはできるだけさぼりながら, 必要になったときにだけ付け足していく. 例えば最初はフロント係は斉藤さんだけとして, 後で複数のフロント係がいる場合のことを考えるのである. もう一つはできるだけ本質だけを捕まえて変な方向に逸れないようにする, 逸れてしまったなと思ったらすぐに戻ってくる. もちろん何が本質かはマニュアルには書いていない. あなたの全人生がかかっている.

この例ではプログラミング言語風に書いたけれど, もちろんJavaではこうはいかない. いろいろな決まり事をたくさん書く必要があって, 書いているうちに本質を忘れてしまう. でも例えばSmalltalkとか (ちょっと譲って) GroovyやRubyのような言語ならばこれに近いことが書ける. もちろん (たいていは動かすことはできないけど) UMLだって大丈夫. つまりこの真似っこゲームとはモデリング = プログラミングの過程そのものなのである. ただし普通のモデリングの教科書には載っていない, きわめてボトムアップでコンクリートなモデリングだけど, モデリング = 真似ることの本質を衝いているのではないだろうか.

僕はこれを勝手にエピジェネティック・プログラミング (epigenetic programming) と呼んでいる. エピジェネティック (後成的) とは, イギリスの生物学者C.H. ウォディントンが提唱した発生学上の概念で, 砂場の山に水をかけているうちにだんだんと川になっていくように, 発生の過程はランダムだけれど最終的にはバランスの取れた落ち着くべきところに落ち着く過程だというのである (「発生と分化の原理」C.H.ウォディントン, 1968, 共立出版, 絶版).

エピジェネティック・プログラミングはKent Beckのテスト駆動開発にもとても似ているでしょう? エピジェネティック・プログラミングではテストのことは具体的に考えていないけれど, モデル駆動開発と契約による設計の手法を利用している. そしてこのようなプログラミングをサポートするためのOpenMDAというツール開発に参加していたのだけれど, 本当の実現にはまだ時間がかかりそうだ...

2004.12.19
山田正樹 (メタボリックス)

Comments