プログラマが知るべき97のこと/ドメイン特化言語
チェスプレイヤー、幼稚園の先生、保険の外交員など、どの分野にも言えることですが、専門家というのは、日常生活で使われる言葉とは全く違った言葉を使うものです。いわゆる「ドメイン特化言語(DSL: Domain Specific Language)」が存在するのはそのためです。分野(ドメイン)には、それぞれ固有の事象があり、固有の事象を表す特殊な語彙があるので、DSLによってその語彙に対応するというわけです。
DSLは、ある分野に固有の語彙や語法を使用して事象を表現できるよう作られたプログラミング言語です。この言語を使えば、コードは当該分野の専門家にとって読みやすく理解しやすくなります。その言語を使うことで、専門家自身が自らコードを書くこともできれば理想でしょう。DSLの中でも特に古くから存在するのは、ソフトウェア開発者や科学者をターゲットとしたDSLです。UNIXの環境設定ファイルなどで使われる「ミニ言語」や、LISPのマクロの力を利用して作成された言語などは、その中でも古い例と言えるでしょう。
DSLは、大きく内部DSLと外部DSLに分類することができます。
内部DSL: 内部DSLは、汎用のプログラミング言語の書き方を工夫して、見かけ上の構文を自然言語に近づけた言語です。内部DSLの作成には、糖衣構文(syntactic sugar)を豊富に持ち、フォーマットの自由度の高い言語(Ruby、Scalaなど)の方が、そうでない言語(Javaなど)よりも向いていると言えます。内部DSLでは、ホスト言語(基になった言語)のAPI、ライブラリ、ビジネスコードなどはラッピングされるのが普通です。ラッパが提供され、技術的知識がなくてもその機能を容易に利用できるようにしてあるのです。また、コードをファイルに書けば、そのファイルを使って即、実行できるのが普通です。実装の仕方や分野によって言語の用途は様々に異なってきます。用途の例としては、データ構造の構築、依存関係の定義、プロセスやタスクの実行、他のシステムとの通信、ユーザ入力のバリデーションなどが挙げられます。内部DSLの構文はホスト言語の構文の制約を受けます。ホスト言語での書き方を工夫してDSLを作るのに役立つパターンは多数存在します。例えばエクスプレッションビルダ、メソッドチェーン、アノテーションなどです。ホスト言語が再コンパイルを必要としない言語であれば、内部DSLは非常に簡単に作成でき、対象ビジネス分野の専門家にとって使いやすいものになるでしょう。
外部DSL: 外部DSLは、汎用のプログラミング言語とはまったく別の構文を持ったDSLです。グラフイカルな外部DSL もありますが、テキストベースの外部DSLの方が一般的です。テキストベースの外部DSLのコードは、レキサ一、パーサ、モデルトランスフォーマ、ジェネレータといったポストプロセッシングのためのツール群を組み合わせることによって処理されます。通常の場合外部DSLは読み込み時に内部モデルに変換され、後続処理に使われます。EBNFなどの文法(grammar)を定義するのが有効でしょう。文法は、エディ夕、ピジュアライザ、パーサジェネレータ等のツール群が扱うパーツを生成するための起点となります。シンプルなDSLならば、たとえば正規表現を利用した「手作りの」パーサなどでも十分に対応ができます。ただし、手作りのパーサは、あれこれ欲張ると非常にわかりにくく、使いにくくなってしまうので、openArchitectureWare、ANTLR、SableCC、AndroMDAなど、元々文法定義またはDSLのために作られた既存のツールを探す方が合理的でしょう。XMLの「方言」を作り、それを外部DSLとする方法もよく使われますが、特に技術知識のない人にとってコードが読みにくくなりやすいのが難点です。
DSLを作るときは、使う人が誰かということを常に考慮にいれておく必要があります。DSLの利用者は、開発者でしょうか、管理者でしょうか、どこかの企業の顧客でしょうか、それともエンドユーザでしょうか。言語の技術レベルや利用可能なツール、例えばシンタックスヘルプ(例: IntelliSense)、リアルタイムバリデーション、可視化ツールなどへの対応や、コード表現を利用者に応じて変えることになります。DSLが技術的な詳細を隠蔽すれば、技術者の助けを借りることなく、ユーザが自分の手でシステムを自らのニーズに合わせることができます。最初にDSLの枠組みさえ提供されれば、あとは各自が自力で作業を進められるため、それが開発作業のスピードアップにつながります。言語は使用されるうちに、徐々に進化することになるでしょう。既存の表現や文法からの移行のために使える手立ても増えます。