アーキテクチャを支える言語

FowlerDSL本のAlternative Computational Modelを足がかりとして、ソフトウェアアーキテクチャにおけるDSLの役割について考察する。

導入

Martin Fowler氏はWeb版DSL本の中で、「DSLにおいて重要なのは、言語それ自体ではなく、DSLによって構築される意味モデル("Semantic Model")である」ということを繰り返し述べています(意味モデルについては、以前こちらのエントリで紹介しました)。その上で、この意味モデルが持ちうる、ある性質について「もう一つの処理モデル("Alternative Computational Models")」と題された章で説明されています。


ここで「もう一つの」("alternative")とされているのは、命令的な("imperative")処理に対する宣言的な("declarative")処理です。こうした宣言的な処理を支える意味モデルとして、適応型モデル("Adaptive Model";場所によってアクティブモデルとも呼ばれています)が想定されています。この適応型モデルとは、デシジョンテーブルやステートマシンのように、要素間の関係によってふるまいを規定するような抽象モデルのことです。Fowlerにとっては、こうした適応型モデルこそがDSLを使う意義の一つとなります。

Alternative computational models are also one of the compelling reasons for using a DSL, which is why I've spent a big chunk of time on them in this book. If your problem can be easily expressed using imperative code, then a regular programming language works just fine. The key benefits of a DSL, greater productivity and communication with domain experts, really kick in when you are using an alternative compuational model. Domain experts often think about their problems in a non-imperative way, such as a decision table. An active model allows you to capture their way of thinking more directly in a program and the DSL allows you to communicate that representation more clearly to them (and yourself).


もう一つの処理モデルもDSLを使用する上で説得力のある理由になります。これこそ私がこの本の中で多くの紙面を割いてきた理由でもあります。もし、命令型のコードを用いて容易に表現できる問題であれば、通常のプログラミング言語でうまく行くでしょう。DSLの主要なメリット、すなわち生産性を向上させ、ドメインエキスパートとのコミュニケーションをより良いものにするというメリットは、このもう一つの処理モデルを使った場合に効いてくるものなのです。ドメインエキスパートは、彼らが持つ問題について、デシジョンテーブルのように命令的ではないやり方で考えています。アクティブモデルを使えば、彼らの考え方をプログラムにおいて直接的にとらえることができますし、DSLを使えばこうした表象について、ドメインエキスパートと(そしてあなた自身と)より明確にコミュニケーションすることができるようになります。
http://martinfowler.com/dslwip/AlternativeComputationalModels.html

Fowlerのこの説明がこのエントリの出発点になります。FowlerのDSL本は適応型モデルについて、具体例としてデシジョンテーブル依存関係のネットワークルールシステムステートマシンといったものが例として挙げられるのみで、ソフトウェアを作成する上でどう考えるべきかについては言及されません。しかし、この点についての理解をもう少し深める(広げる)ことは、DSL全体についての理解を深める上でも重要なのではないかと思うのです。

EvansのDSL

まずは、DDDで有名なEric Evans氏のDSLに関する議論を、InfoQで紹介されているJAOOでのプレゼンテーションから見てみましょう。DDDにおけるEric Evansの考え方は「ユビキタス言語」という概念に集約されています。これは、モデルへと流れ込む情報に含まれる「言葉」に注目し、その言葉を用いてドメインモデルを構成することはもちろん、その言葉をプロジェクト内でのコミュニケーションから実装まで一貫して使用するというものです。


モデル自体よりは「モデルを構成する概念」を軸に考えているEvansが提示しているのが「細かいDSLを積み重ねることでソフトウェアを構成する」という発想です。具体例としては、「時間」という低次の概念をDSLを用いて表現できるようにするライブラリが示されます。

CalendarDate workDate = CalendarDate.of(2006,9,20)
CalendarDate dueDate = workDate.month().end().plus(Duration.days(30));

概念をレイヤに分解し、それぞれについて宣言的にプログラミングするためのライブラリを作るというやり方は、時間はかかるかもしれませんが、一度形になってしまえば可読性においても、生産性においても有効なものと考えられます。また、低次の概念ほど汎用性が高くなるため、全く別のプロジェクトにおいても再利用できるというメリットもあるでしょう。


ただし、ここではCalendarDateが宣言的に構築できるようになっているのみで、モデル自体は適応型ではない、単なるデータ構造にすぎません。DSLの意義がソースコードの可読性を向上させる点にも見出すことができることの一例ではないでしょうか。

適応型モデリング

「適応型」と訳語を当てていますが、この"adaptive"は「状況に合わせて変化することができる」といった意味ととらえるべきです。たとえば、「デシジョンテーブル」を表現したモデルはそれ自体ではふるまいを持たず、特定のルールを与えられて初めてルールに応じたふるまいができるようになります。ここからも分かる通り、適応型モデルの最大の意義はオブジェクトを組み替えることでふるまいを変えることができる点にあります。さらに言えば、この「ふるまいの定義」を実行時に行える点が大きなメリットであると言えるでしょう。アプリケーションの設計において、こうした可変性を整理しておくことは重要です。


Johan Den Haan氏は、モデル駆動ソフトウェア開発(MDSD)について説明しているエントリにおいて、可変性を次の3つのレベルで考えています。

  • レベル0: 特定のドメインにおける、アプリケーションの静的な部分
  • レベル1: DSLを用いてアプリケーションの開発もしくは設計時に定義される可変な部分
  • レベル2: 実行時に設定される、あるいは変化するアプリケーションの場所

その上で、レベル2の可変性を実現する方法として、何らかのエンジンを使う方法と適応型モデリングを使う方法が提示されます。エントリのテーマであるMDSDのスピードアップという観点から、適応型モデリングの長所と課題についてそれぞれ次のように説明されています。

長所:

  • 変化に適応するのが早く、容易である。
  • 保守期間を必要とせず、実行時に変更できる。
  • 変更が制御されたものだけである、つまり、レベル2の変更だけが実行時に可能である。
  • 変更が抑制され制御されていれば、テストの手間は少なくなる。


課題:

  • MDDのメリットはできる限り特化した言語を使うことにある。適応型モデリングが意味するのは、モデルとツールによるサポートがより抽象的で特殊性が低いということだ。
  • どこまでやるのか?つまり、何をレベル1とし、何をレベル2とするべきなのか?
  • 適応型モデリングにおいて、編集は難しくない。一方で、テストやデバッグツールをどう使うのか?どう品質を保証するのか?この点に関する課題はエンジンを使った場合の方が強い。

つまり、適応型モデルは、こうした課題を考慮し、またエンジンの使用も検討した上でメリットが出る場合に採用するべきだと考えるべきでしょう。

まとめ

DSLを考える上でまず重要なのが、モデルと言語を区別することだということには変わりありません。その上でモデルの設計をする際に、どういうレイヤを積み重ねるのか、各パートの可変性をどのレベルで考えるべきなのかということについて、アップフロントに考えておく必要があるということになりそうです。開発/設計のレベルで可変性(というより柔軟性)を保持するのであれば、通常のドメインモデルを構築し、それを操作するためのFluentなAPIを準備するという流れが基本になるでしょうし、ランタイムの可変性が求められるのであれば、適応型モデルが必要になるでしょうし、DSLのタイプも必然的に外部DSLにならざるを得ないでしょう。


また、今回は可読性可変性という観点から、DSLについて考えてきましたが、それとは逆の方向で言語が持つ規定性についても、意識しておく必要があるでしょう。コンパイル言語である限りランタイムの可変性→外部DSLが必須ですが、逆に外部DSL→ランタイムという訳ではありません。例えば、Webフレームワークの画面遷移などは定義ファイルに書かれることが多いですが、実際に変更してしまえば正常に動作はしません。そういう意味では、ホスト言語を超えた表現力を獲得するために外部DSLが選択されているとも言えますが、一方でクライアントコードから直接オブジェクトを操作することができないため、予め想定されていない操作をされてしまう可能性を抑えることもできるようになります。こうした規定性はアーキテクチャを安定させる上で大いに役に立ちます。


つまり、ドメイン=ビジネスドメインと考える必要はなく、適切なレイヤリングを行うことでレイヤごとにそれぞれのドメインが定められることになります。その上で、ソフトウェア全体として「固定する所はがっちりと規定し、可変にするべき所はその性質に応じてどこまでも柔軟にする」という、アーキテクチャ策定上の基本戦略を支えてくれるのがDSLだということになるのではないでしょうか。