« Redmine .Net APIであるredmine-net-api | トップページ | RedmineにおけるEVMの考え方 »

2012/12/22

ドメイン特化言語の感想~ドメイン専門家とプログラマが会話するための環境作り

ファウラー著「ドメイン特化言語」を読んだ。
やはり、ファウラーはIT業界の未来について、いつも一歩先のことをよく考えている。
自分が理解できたこと、感想をラフなメモ書き。


【参考】
ごあいさつ - DSL翻訳者の悩み

48章(DecisionTable)のクラス図 - DSL翻訳者の悩み

41章(Dynamic Reception)のクラス図 - DSL翻訳者の悩み

【1】ステートマシンの例からDSLの意義を考える

第1章で、ステートマシンの例を持ちだして、DSLが何故必要なのかを説明してくれている。
自分が本を出版してみて分かったことは、本の最初で、この本で言いたいことは何なのか、を明示することが重要。
普通は最初に、具体例や問題を提示して、本で言いたい主張を概略的に述べると、読者を引き込みやすい。

ステートマシンの例では、Javaで実装したステートマシンを各インスタンスごとに振る舞いを変えるために、XMLやRake構文を使う方法が示されている。

XMLを使う場合は、設定ファイルみたいなもので、その利点は、実行時に動的に振る舞いを変えることができるのでコンパイル不要になること。
この場合、XMLは外部DSLになる。

XMLは基本は外部DSLと見なして良い。
外部DSLで最も成功した例はAnt。
外部DSLでは、DSLスクリプト、パーサー、セマンティックモデルの3つに分けて実装される。

Rakeを使う場合は、設定ファイルのように見えるが、Rubyで書かれているので実行可能なスクリプトでもある。
この場合、Rakeは内部DSLになる。

内部DSLはAPIとは違う。「流れるようなインターフェイス」と呼ばれるらしいが、具体的な構文はメソッドチェインと同じ。
内部DSLが脚光を浴びたのは、Railsの出現であり、Webフレームワークを内部DSLで一種のモデルとして表現したことにあると思う。
内部DSLではセマンティックモデルとパーサーが混じっているので、セマンティックモデルと式ビルダーという形式で分けて表現すると良いらしい。

内部DSLの例は、GroovyやJRuby、Lispなど。
Lispは昔からマクロという形式で表現していた。
内部DSLはLispの先祖返りとも言えるかもしれない。

この例で重要な点は、DSLがステートマシンのモデルを表現する事に使われていること。
ここから、DSLとモデルの密接な関係が出てくる。

【2】DSLの特徴

DSLの一番の特徴はチューリング完全でないこと。
チューリング完全でないという意味は、命令形の制御構文を持たないことを意味しているらしい。
実際、本来のAntはタスク志向なので、If文やFor文は使えない。
とはいえ、AntはIf文やFor文もライブラリを拡張することで使えるようになってしまった。
その点はファウラーは批判的で、DSLは汎用言語化すべきでなく、問題領域の表現に注力すべきと言っている。

ファウラーはモデルをドメインモデルとセマンティックモデルで区別している。
ドメインモデルは振る舞いを持つ動的モデル。
ドメイン駆動開発(DDD)では、ドメインモデルの構築が基本方針になっている。

セマンティックモデルは基本はデータしか持たない静的なモデル。
外部DSLならXMLの設定ファイルがセマンティックモデルになる。
内部DSLでは、セマンティックモデルに実行可能な振る舞いも混じっている。

セマンティックモデルが重要な理由は、プログラマがDSLで表現できることと、そのDSLがユビキタス言語へ進化する可能性があるkと。
つまり、ドメイン専門家の言葉でセマンティックモデルを表現することで、ドメイン専門家とプログラマが有意義な会話ができる。
すると、プログラムの実装方法を表現する事よりも、プログラムの意図を表現することへ注力できるようになる。

セマンティックモデルの使い道の一つは、ドメイン専門家によるモデルの理解だけでなく、そのモデルからコード生成できる点もある。
Lispは昔からマクロでやっていたし、RailsはActiveRecordという概念でORマッピングしている。
ドメイン特化言語」では、Cobolのコピー句からJavaソースを生成するDSLを作ったという例が記載されていた。
この例の意味は、Cobolのコピー句はストアドプロシージャのカーソルのようにレコードを定義しているので、そこからそのレコードに操作するJavaライブラリを作ったのではないか、と想像する。

セマンティックモデルが普通はXMLのような静的モデルで表現される場合、XMLというテキストをパースしてモデルへ変換する仕組みが必要になる。
つまり、パースして抽象構文木を作る仕組みが必要なため、チョムスキー階層とか、レキサーとか、コンパイルに関する知識が必要になる。
ドメイン特化言語」のあとがきでは、この本を翻訳するために、コンパイルを勉強するなら誰もが知っているドラゴンブックを読み直したという文章があり、すごいなと思う。

DSLは奥が深い。

【3】DSLの動物園

DSLの抽象的な話を読むよりも、やはり具体例を見る方が分かりやすい。
ドメイン特化言語」では、幾つかのDSLが紹介されている。

Graphizは、DOT言語で書かれる外部DSL。
ネットワーク図のような絵を出力してくれる。
モデルの可視化に役立つ。

CSSもDSLと見なすのは驚いた。
実際、WebのUIの構造を表現している。
重要な点は、CSSを扱う人は自分をプログラマーではなくWebデザイナーと呼んでいること。
つまり、DSLを扱えるのにプログラマーではないWebの専門家であると自称しているわけだ。

HQLはHibernateで使われているSQLライクな内部DSL。
普通のSQLとは違う。
ORマッピングの一つ。

FITは表形式のテストフレームワークをサポートする内部DSL。
ユーザが、テストの条件をデシジョンテーブルで表現したりすることで、受入テストが理解しやすくなる。

もう一つ重要な点は、FITがテスト志向なDSLであること。
DSLの使い道は、モデルの表現やコード生成だけでなく、テストをサポートするライブラリとして使う方法もある。
ユーザというドメイン専門家がテストを理解できる点が重要。
Cucumberのような最近流行している振る舞い駆動開発(BDD)も、内部DSLを使った一つの例とみなせるだろう。

makeやAntなどのビルドスクリプトもDSL。
Antは外部DSLだし、Rakeは内部DSL。
これらは、タスク指向、成果物指向とも言われる。
タスク指向の意味は、処理をタスクと見なして、タスクの流れと見なすこと。
例えば、ソースのチェックアウト→コンパイル→パッケージング→デプロイという流れでタスクを分割し、タスクの順序を定める。
これは、バッチ設計のジョブネット図、ジョブフロー図の考え方に近い。
つまり、一連のタスクが条件分岐したり、合流したり、あるタイミングで起動するなどの制御を入れるなどの手法が必要なことを示唆している。
今なら、Antなどのビルドスクリプトで複雑なビルド処理や自動テストを分割しておき、Jenkinsでタイミングを制御したり、処理の流れを定めるなどのやり方になるだろう。

【5】全体を通しての感想

DSLの使い道は、モデルの表現、受入テスト、ビルド処理があげられる。
モデラーはDLSでモデルを表現して、コードを自動生成することで、モデル駆動開発を目指す人が多いが、そのやり方は既に失敗していると思う。
むしろ、DSLを通じて、ユーザとプログラマが会話できる環境を作る方へ注力した方が有意義なのだろう。

ドメイン特化言語」で面白いのは、ExcelやAccessがDSLに似た例としてあげられていること。
Excelは、表形式でデータを扱い、VBAのようなマクロがあり、一つの汎用言語である。
Excelを使っている人は、自分はプログラマではないと思っているけれど、実際は、彼らが欲している用途に応じてモデルを作り、Excel内で計算している。
でも、Excelは表というデータが目立ちすぎて、計算方法をプログラムという構造まで抽象化できない弱点がある。
Accessも同様だ。

このようなツールは昔のCaseツールを連想させる。
Caseツールはモデルを作るためのツールとして販売されていたが、結局廃れてしまった。
現在の流れを見れば、DSLをプログラムの一部として書いて、モデルをどんどん改良していくスタイルの方がいいだろうと思う。

僕は「ドメイン特化言語」の前半しか読んでなくて、後半のパターン集はさほど読んでいない。
厚さが600ページもあるので盛り沢山。
概略だけ読んでも面白いと思う。

|

« Redmine .Net APIであるredmine-net-api | トップページ | RedmineにおけるEVMの考え方 »

Agile」カテゴリの記事

Ruby」カテゴリの記事

ソフトウェア工学」カテゴリの記事

パターン言語」カテゴリの記事

モデリング」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



« Redmine .Net APIであるredmine-net-api | トップページ | RedmineにおけるEVMの考え方 »