変幻する実行可能知識 07「うごくといふこと」ソフトウェアという「知識 (表現) 」が他の種類の知識と大きく変わっているところは, 「柔らかい」「移ろいやすい」ということ, 「動く」ということ, この二つの点だ. 他の典型的な知識 (表現) である書物はいったん印刷されたらほとんど変わることはないし, 「実行」されることもない. もっとビジュアルな知識 (表現), 例えば普通のCGアニメーションは確かに「動く」けれど, もちろんここでいう「動く」とは意味が違う. 外界の何かに反応してあるいは自律的に内容が変化して, それがそれ自身の表現や外界に反映される, のがここでいう「動く」ということだ. それにもかかわらず, 多くの人はソフトウェアを作る過程であまり「動く」ということに注意を払わない. 確かに最近UMLのようなものを使ったモデリングをする機会が多くなったはずだが, ユースケース図やクラス図しか描かないという人も多いのではないだろうか? いやいや, クラス図には属性だけじゃなくて, ちゃんと操作も書くよ, と言うかも知れないけれど, あれは実は単に「属性名」「操作名」でしかない. 属性は名前があればまぁよい, どうせ値を入れる単なる「場所」なんだからまっとうな名前さえ付いていれば許そう. でも操作名は「私が理解できる言葉はこれこれです」と宣言している辞書に過ぎない. 何の動きも表していないのである. 動きの入っていないモデルはいくら精密に美しく書かれていても, 「実行可能知識」であるソフトウェアとしては, 仏作って魂入れず, なのである. 特にビジネス・アプリケーションを開発している現場ではいくらオブジェクトという言葉がはやっていたとしても, 実際にはデータ中心であることが多い. まずデータをきっちり定義して, 次にそれがどう動くか考えよう, というわけだ. だから動き, 振る舞いを実際に考えるのは最後の最後, 実際のプログラミング言語を使ったコーディングの時になってしまう(注). そうすると動きを変えようとしたときに思ったようにいかない (保守) とか, そもそも思ったように動くとはどういうことかよく分からない (テスト) とかという事態に陥るのも当然の話でしょ?
じゃあ, そうじゃないやり方なんてあるんですか? 車だってまず車を作ってから動かすでしょ? 動かしながら車を作るなんてあり得ない! (注) いえいえ, それがあるんですよ. それがソフトウェアというもんなんですから. ソフトウェアの場合には, ソフトウェアを作るのも (人間以外は) すべてソフトウェアなわけですから.
構造を考えるのと同時に動かしたい. それが開発の「生産性」をもっとも高める手段の一つだし, ソフトウェアにはそれができるはずだ. その方法はいくつかある. 一つは要求から直接実装コードを生みだし, 構造を書くと同時に動きも書き, 同時にテストの形で実際に動かす, XP的な方法だ. この場合は構造を書くのと動きを書くのと動かすのが同時というよりは, むしろまず動かして, それにドライブされて動きを書き, それにドライブされて構造が決まるといった方がいい. 徹底したボトムアップの方法であるが, 動きの記述は通常の手続き型プログラミング言語程度の抽象度しかないので, とにかくしょっちゅうリファクタリングしていないと動きの本質が見えなくなってしまうのが難点だ. もっと動きの本質を表すことはできないか? これにもいくつかの方法がある. 一つは動きをある特定の入力 (あるいは環境の変化) があったときにある特定の出力をするもの, と決めることだ. 代数的仕様記述とか, 論理プログラミングとか, ルール・ベースとか, 制約指向とかはこのグループに入る. ある意味で動きを静的なものとして捉えることによって抽象化している. で, 動きそのものの動的な部分はどこに行ったかというと, そのインタプリタに押し込められている. これは特別に研究的な話というわけではなく, 実際のプロジェクトでもよく使われる方法だ. ある特定の領域の背後に共通する動きがあるんだとしたら, その動きそのものは (小さな) インタプリタとして作り, ルールをデータとして入力する. 最初に作るのは少し大変だけど, いったん作ってしまえばバリエーションや拡張をすべてルールとして静的に記述して実行時に食わせることができるので柔軟性や生産性, 保守性が非常に高くなる. 例えばUnixの開発ツールであるmakeってそういうものでしょ. ビジネス・ルールをいちいちコードとして記述するのではなく, ルールとそのインタプリタとして書くやり方もよく行われる. もう一つは動きをオートマトンとして考えるやり方だ. オートマトンとは「自分で動くもの」だからまさに動きそのものを抽象化したモデルで, 「ある事象が起きたらあることをする」ものを組み合わせた機械だ. 馴染みの深いものとしては例えばUMLの状態図を考えればよい. 前の例に較べるとこっちはインタプリタ (動き) そのものを抽象的に考えようという方向だ. 普通のプログラミングだけでもひーひー言っているのに, さらにこんなものを考えるなんて, 何が嬉しいんだろう? 状態図は直接動かせる. しかも通常のプログラミング言語で動きを記述するのに較べて, 動きの本質以外のことに気を遣う必要がない. つまり, 生産性がきわめて高い. しかも本質だけが書いてあるから変更が容易だ. つまり, 拡張性や保守性も高い. そしてあらゆることを考えた後にようやく動かせるようになるのではなく, 考え始めたその時点から, つまり分析や基本設計の段階から実際に動かせる. まだもう一つの方法がある. それはこういう高尚で小難しい (!?) ことは考えたくない人向きかも知れない. どうせ (手続き型) プログラミング言語を使うならば, もっとまともなプログラミング言語を使うことだ. 実際, プログラミング言語の背後にあるモデルもある種のオートマトンだし, プログラミング言語もある種のインタプリタで実行されているはずだ. にもかかわらず, (大方の) プログラミング言語がこんなにややこしく, 間違いやすく, 本質が見えにくいのはなぜだろうか. GroovyやRuby, Pythonなどいわゆる「スクリプト」系の言語, あるいはSchemeやSmalltalk, ML系統の「なつかしの」言語が少しずつではあってもなし崩し的に使われるようになってきているのには, 多分それなりの理由があるはずだ. 商用ソフトウェア開発に当たって慎重になるあまり, 「動き」をどう表現するか, どう実現するかについてあまりに保守的な姿勢がまかり取ってきたように思えるけれど, ソフトウェアは「動いてなんぼ」なんだから, アーキテクトはもう少し頑張ってもいいかも知れない. さて, この連載ではこれまで, ソフトウェア開発を実行可能な知識の変換過程と見る立場から, 「知っていることを (第1回) 正しく (第2回) 分ける (第3回) ことによって分かり (第4回), 分けたものを変換して (第6回) つなぐ (第5回) ことによって動かす (今回)」というアーキテクトの仕事を追いかけてきた. 次回は中入りとして, その後後半戦に入ろうと考えている. |