2010年5月4日火曜日

Scala DSL

クラウド時代に向けて:

  1. SimpleModel:オブジェクト・メタモデル。クラウド・アプリケーション向けの拡張中。
  2. SimpleModeler:SimpleModelのモデルコンパイラ。
  3. g3:メッセージフロー・フレームワーク。

の開発を行っているわけだけれど、これらの技術のキーテクノロジとなるのがDSL(Domain Specific Language)である。

SimpleModelはメタモデルだけれど、Scala DSLで簡潔に記述できることが要件の一つになっている。そして、SimpleModelのモデルコンパイラがSimpleModeler。SimpleModelerはSimpleModelを記述したScala DSLの集まりをソフトウェアリポジトリとして使用する。

またg3は、Scala DSLで記述したメッセージフロー・モデルに基づいて動作する。

このように、このところはScala DSLを中心に活動しているのだけれど、ここにいたるまで色々と紆余曲折があった。

1998年に登場したXMLがJavaと分散環境のミッシングリンクを埋めるキーテクノロジーであると感じ、Java&XMLを中心に活動していた時期がある。

分散環境では、分散ノード間でのオブジェクトの共有や移送は理論的には不可能ではないにしても相当ハードルが高く、当面は実運用的には不可能と考えてよい、というのが分散OSや分散オブジェクトの教訓。

このため、分散アプリケーションが取るべき現実解は、異機種間での疎結合のサービスを構造化された値の送受信で連携させるということになるのではないか。そしてこの「異機種間で送受信する構造化された値」を記述する技術が当時のJavaには欠けており、ここにXMLはすっぽりとはまるのではないか。

そういったブレークスルーの予感もあって、XMLアプリケーションであるSmartDoc(1998)とRelaxer(2000)を開発したのだけれど、これらのアプリケーションを通して、いわゆる「one source multi use」の有効性を体感することができた。

当時はまだ、DSL(Domain Specific Language)という用語はなかったか、あるいは一般的ではなかったのだけれど、用途ごとの専用言語をXML上に構築して「one source multi use」の運用を行うこと、つまり今の言い方ではDSLが今後の技術の主流になると思えた。

ただ、XMLをDSLのホスト言語として使用することを試行錯誤する中で、XMLは文書をマークアップするにはとても良いのだけれど、定義ファイルやプログラムといった用途に使用するのには向いていないことが分かってきた。

そこで、プログラミング言語をホスト言語にすることを考えたのが次の段階。最初に候補となったのはGroovy。これは2004年頃。Javaベースであり、メタな操作も可能なのでDSLのホスト言語としてうってつけであると思ったわけである。

しかし、いくつか問題があってGroovyを採用するのは断念した。

当時のGroovyは、非常に遅かったのが一点。ただ、こういった問題は時間が解決するので、DSLの用途ではそれほど大きな問題ではない。

木構造を扱う抽象構文的な拡張の柔軟性が低い、という問題もあった。これは、他に良いところがあれば我慢できる範囲。(なにぶん古い話なので今は違った状況になっていると思う。)

しかし、これは大きな問題だと思ったのは、動的言語であるためにDSLの構文にコンパイラ相当のエラーチェックをかけることができない、ということ。これはDSLを使ってモデルを作成していく際の効率を著しく低下させる。

たとえば、フレームワークの設定ファイルに識別子のミススペルがあることが原因で、フレームワークが意味不明のエラーで落ちる、というような事が起きる。

DSL処理系の開発も難しくなる。DSL処理系をクイックハックで作る分には楽でよいのだけれど、本格的なものにしようとするとコンパイラ相当のエラーチェックを自分で実装しなければならなくなる。

そんな中で、アノテーション技術が登場したこともあり、JavaをDSLのホスト言語とすることに決めて開発を進めていた。

しかし、JavaをDSLのホスト言語として使用した場合、メタな情報はjava.lang.reflectionとアノテーションで部分的に取り出すことができるだけなので用途が限られるという問題がある。Javaの文法を構文木として取得するのが非常に難しい。EclipseのASTを使うという案もあったのだけれど、Eclipseに依存してしまうので断念した。

以上のようなこともあり、Javaでは木構造のデータ構造を簡潔に記述するための文法を定義するのが難しい。Javaで書いたロジックをそのまま取り出すことも難しい。

もちろん、GWTのような荒業もあるけれど、これはハードルが高すぎて一般的な技術には成り得ない。

また、Javaではテキスト情報をDSLの一部として記述するのが一苦労。コメントに記述したものを、自作パーサで読み込むといったようなことをやったりしていた。

そして最後に行きついたのがScalaということになる。これが、2008年の7月。

Scalaは、高階関数と字句上の様々なトリックを併用することで、簡潔で強力なDSLを簡単に構築することができる。また、生文字リテラルやXMLリテラルがあるのでテキスト情報の記述も簡単。ケースクラスや抽出子によるリテラル追加機能もよい。しかも、型推論のついた静的型付け言語。

まさに、DSLのために生まれてきた言語である。

たとえば、以前にご紹介したg3フレームワークが使用する以下のScala DSL。Enterprise Integration PatternsのSplitパターンとAggregateパターンを使用したメッセージフローを記述している。これをXMLやJavaで記述しようとすると、大変な事になりそうだ。実装もややこしくなる。

Split.scala
class Split extends G3Application {
  start(List(1, 2, 3, 4, 5)) split() agent {
    case x: Int => x + 100
  } aggregate()
}

しかし、Scalaだととてもすんなりいくのである。実装も、簡単というわけではないけれど、XMLやJavaをDSLにした時のことを考えるとはるかに容易になる。

いずれにしても、こういったDSLの構築技術が、クラウドに限らずこれからのソフトウェア開発のキーテクノロジーになると思っている。よほどの本格的な用途でない限り、ホスト言語の上に構築する内部DSLを使うことになるので、内部DSLが最重要技術ということである。

内部DSLのホスト言語としては、現在のところRuby、Groovy、Scalaが有力だと思われるけれど、やっぱりDSLは静的型付けがよいかな、ということでボクの選択はScalaということになる。もちろん、これは各自の好みで決めてよいところ。DSL処理系の開発効率も重要なので、プログラミングに慣れている言語を選択するのがよいでしょう。

Scala DSLアプリケーションであるSimpleModelerやg3の開発を通して、二年近くScala DSLプログラミングしてきて、多少ノウハウも蓄積されてきた。そのようなこともあり、Scala DSLに関するノウハウを5月18日に行われるJJUG CCCで『Scala DSLの作り方』というセッションで発表させていただけることになった。

興味のある方はぜひどうぞ。

2010年5月3日月曜日

クラウド・モデリング

5月14日に行われる『Hadoopを中心とした分散環境での開発方法論・モデリング・設計手法等についての座談会』という座談会に参加させていただくことになった。

よい機会なので、クラウドをターゲットにして取り組んできたモデリング手法、ツール、フレームワークなどをつらつらと整理しているところ。

オブジェクト指向モデリングは、本来、振舞いモデルを記述する能力が高い所が特徴であり強みでもあるはずだけれど、今のところ有効活用されているとは言い難い。

伝統的な基幹システムも、新興のWebシステムも基本的には画面とデータベース間の転記が基本アプリケーション・アーキテクチャとなっていることが多く、この場合には従来型のデータモデリングで十分だったということかもしれない。

三段(3 tier)構成のシステムアーキテクチャといった設計レベルでのモデリングもあるけれど、アーキテクチャレベルの鳥瞰図があれば、あとは直接プログラミングした方が話が早い。

しかし、クラウドでは故障、遅延、規模といった問題が従前より重要な課題となって浮上するため、今までのようにはいかなくなるだろう。

故障、遅延、規模の問題をデータベースシステムを中心としたミドルウェア層で吸収することはもはやできなくなるわけで、性能と一貫性のバランスを取るために、アプリケーションの用途に応じて、アプリケーション側で調整を行う必要が出てくる。いずれこういった問題を吸収するクラウド・ミドルウェアが出てくることになるとは思うけど、これは10年スパンで考えていくことである。

利用者側への見せ方、エクスペリエンスにも影響が出てくる。たとえば、今までだったらフォームの完了ボタンが完了したらデータベースには確実に書かれているはずだったけど、クラウドでは後で書いときます、という約束が行われるだけとなることが多くなる。そうなると、利用者側のアクションとして、書かれたことの確認や、実は書き損なっていたのでリカバリを利用者自身にお願いするというようなユースケースが普通に出てくる。

こういった問題を取り扱うには並列、分散、非同期といった要因を上位のモデリング段階で扱わなくてはならなくなるはず。そのモデリングのためのメカニズムとしてオブジェクト指向が再評価されることになるだろう、というのが最初のアイデア。そして、システム構築という観点から見るとMQ的なキューを中心としたシステムアーキテクチャ、アプリケーションアーキテクチャになるだろう、というのが二つ目のアイデア。

当時考えていたこれらのアイデアを昨年の1月にクラウド研究会でお話をさせていただいた流れから、UNIXマガジン誌に寄稿した記事を『クラウドの技術』の一編として再録していただいた。

この2つのアイデアを、従来から考えているモデリング手法に取り込む方針で作業を進めている。

従来システムに対するオブジェクト指向のモデリング手法はSimpleModeling、MindmapModelingという形でまとめ、一昨年の夏に出版させていただいた。

SimpleModelingとMindmapModelingは、内部的には共通のメタモデルSimpleModelを使用しており、相互運用可能である。MindmapModelingでラフなドメインモデルやユースケースモデルを抽出し、SimpleModelingで本格的なモデリングに入っていくという流れを想定している。

SimpleModelでは、イベントを軸に静的モデルと動的モデルを相互連携させる点がポイントとなっている。SVOがモデリングの基本になる。Vがイベント。イベントがアクター(S)とResource(O)の状態遷移を束ねる。ユースケースも物語をイベントの列として記述することで、静的モデルと動的モデルの両方にシームレスに連結できる。

クラウド・アプリケーションの場合でも、この枠組は引き続き有効ではないか、というのが今のところの考え。とはいえ、静的モデル、動的モデルの双方に相応の拡張が必要になる。

静的モデルでは、いわゆるBASEトランザクションに対応したデータモデリングが必要になってくる。ここでSVOの枠組みを自然に拡張していくことで対応できるのではないか、と考えている。具体的には、関連の各種プロパティの解釈の精度を上げることと、イベント・エンティティにBASE向けの属性を取り入れるといったことである。

動的モデルでは、新しくメッセージ・フローという概念の導入がミッシングリンクを埋める鍵になるのではないかと考えている。オブジェクト指向に限らず、コントロール・フローやデーター・フローをモデル化する図は色々と用意されているのだけれど、コントロール・フローとデータ・フローを包含して記述するための図というのが案外ない。しかし、クラウド・アプリケーションのモデリングでは、コントロール・フローとデータ・フローを同じ文脈上で記述することが、有効なのではないか仮説を立てているところである。

この仮説に基づいて、メッセージフロー図の文法、メッセージフローのDSL、そしてメッセージフローの実行系としてのフレームワークを開発しているのが現在のステータス。メッセージフローのDSLとフレームワークが一段落したら、一昨年から昨年にかけて開発したScala DSLコンパイラSimpleModelerを、メッセージフロー対応する構想となっている。

先は長そうだけど、ぼちぼちやっていくつもり。