少し前になりますが、DSL読書会@JavaEE勉強会でCode GenerationとLanguage Workbenchesのまとめを発表したので、ここにも載せておきます。
Google Docsで作ってみたのですが、Slide Shareと勝手が違っていて、埋め込んだ状態でうまく閲覧できそうにないです。まともに見たい人は、最大化ボタンをクリックするのが良いかと思います。
僕の担当分はDSL本の最後の部分で、この資料はそれまでの部分のまとめが他の人から発表されている前提で作っています。これだけ見てもあまりわからないかもしれませんので、字だけになりますが少しだけ補足しておきます(Fowler DSLのエッセンスにさらっと目を通しておかれると、少しは分かり良いかもしれません)。
DSL Overview
DSL概念全体の中でCode Generationがどのような位置づけにあるかを俯瞰するために、Fowler DSLの全体像を示しています。
DSLスクリプトを言語処理層(Language Processing Layer、パーサー/ビルダーなど)が処理することでセマンティックモデルが構築され、セマンティックモデルをアプリケーションから直接実行したり、他の環境向けにコードを生成してから実行することで望みの計算を行います。セマンティックモデルはFowler DSLのキーとなるもので、Fowler DSLを他のDSLアプローチと隔てている最も大きな要因の一つです。
DSLは、DSLスクリプトと言語処理層の形態によって内部DSLと外部DSLに分類されます。内部DSLはDSLスクリプト、言語処理層、セマンティックモデルを同じプログラミング言語上に構築するもので、外部DSLはDSLスクリプトを独立した言語で記述するものです。
セマンティックモデルから望みの結果を得るためのパターン群を総称して、出力生成戦略(Output Production Strategy)と呼びます。Code Generationはこのうちの1部分という位置づけです。
ちなみに、ハートマークはFowler自身がセマンティックモデルを直接実行するスタイルを好んでいる印としてつけています。本命はセマンティックモデルの直接実行であり、コードジェネレーションは仕方なくやっている、という匂いが文章の端々から感じられるためです。
Code Generation Patterns (What to produce)
コード生成のためのパターンのうち、「何を(どのようなスタイルのコードを)生成するか」についてのパターンを示したスライドです。
Model Ignorant Generationは、その名の通りモデルらしきものがまったく存在しないコードを生成するパターンです。モデルが持つ振る舞いはすべて、コードの中に手続きの形で平坦化されて埋めこまれます。これは、ターゲット環境がサポートする言語に抽象化能力が乏しく、モデルが構成できない場合や、モデルを実体化できるほどメモリリソースに余裕がない場合にある意味仕方なく取られるパターンです。もちろんFowlerはあまり好んではいません。
Model Aware Generationは、ターゲット環境上にも(限られた形態かもしれないものの)モデルを構築し、モデルを操作する形のコードを生成するパターンです。Fowlerお気にです。
Code Generation Patterns (How to produce)
続いて、「どうコードを生成するか」についてのパターンを示したスライドです。「どう作るか」は「何を作るか」に強く依存することに注意が必要です。
Templated Generationは、テンプレートエンジンを使ってコード出力するパターンです。生成対象となるコードで静的に決定される部分が多い場合に有効です。Model Ignorant Generationを使う場合、平坦化されたコードが一定のパターンで繰り返されることが多いため、このパターンが向いています。通常テンプレートエンジンは複雑な制御機構を持っていないため、分岐や選択が入り組んだ複雑な生成には向きません。
Transformer Generationは、モデルを変換するコードをカスタムで作るパターンであり、要はTemplated Generation以外の場合を指しています。複雑な制御が必要であったり、コードに動的に決定される部分が多い場合に向いています。Model Aware Generationを使う場合、コードの記述は最小限となり、繰り返しも少なく静的に決定される部分も小さいため、このアプローチが向いています。
Language Workbenches
言語ワークベンチは、「独自のカスタムDSLを容易に構築できるようにしてくれる環境」です。さらに次のスライドで、言語ワークベンチに共通する要素を紹介しています。FowlerのDSL概念と似た形はとっていますが、異なる部分もいくつかあります。
最も大きな違いは、セマンティックモデルが振る舞いを持つことはほとんどなく、必要な振る舞いはコードジェネレーションのプロセスでテンプレートエンジンによって埋め込まれる点です。
セマンティックモデルが振る舞いを持たないのは、言語ワークベンチが汎用的・統一的に個々のセマンティックモデルを扱えるようにするために「メタモデル」を用意した(せざるを得なかった)のが主な原因のようです。あまり詳しくはないのですが、メタモデルに汎用的な振る舞いの表現を埋め込むのは確かに難しそうです。
もう一つは、セマンティックモデルを様々な方法で視覚化したり、編集したりできる編集環境が用意されている点です。自分が見たツールでは、メタモデルと関連づけながら独自エディタを生成するための開発環境が用意されていました。
MOFとの関係
最後のMOFとの関連はおまけみたいなもんです。とりあえずMOFは忘れてよし!
手抜きで字だらけなのであまり分かりやすくはないと思いますが…
Google Docsで作ってみたのですが、Slide Shareと勝手が違っていて、埋め込んだ状態でうまく閲覧できそうにないです。まともに見たい人は、最大化ボタンをクリックするのが良いかと思います。
僕の担当分はDSL本の最後の部分で、この資料はそれまでの部分のまとめが他の人から発表されている前提で作っています。これだけ見てもあまりわからないかもしれませんので、字だけになりますが少しだけ補足しておきます(Fowler DSLのエッセンスにさらっと目を通しておかれると、少しは分かり良いかもしれません)。
DSL Overview
DSL概念全体の中でCode Generationがどのような位置づけにあるかを俯瞰するために、Fowler DSLの全体像を示しています。
DSLスクリプトを言語処理層(Language Processing Layer、パーサー/ビルダーなど)が処理することでセマンティックモデルが構築され、セマンティックモデルをアプリケーションから直接実行したり、他の環境向けにコードを生成してから実行することで望みの計算を行います。セマンティックモデルはFowler DSLのキーとなるもので、Fowler DSLを他のDSLアプローチと隔てている最も大きな要因の一つです。
DSLは、DSLスクリプトと言語処理層の形態によって内部DSLと外部DSLに分類されます。内部DSLはDSLスクリプト、言語処理層、セマンティックモデルを同じプログラミング言語上に構築するもので、外部DSLはDSLスクリプトを独立した言語で記述するものです。
言語処理層を構成するパターン群を総称して、構文解析戦略(Syntactic Analysis Strategy)と呼び、特に内部DSLを構築するテクニックが豊富に語られています。
セマンティックモデルから望みの結果を得るためのパターン群を総称して、出力生成戦略(Output Production Strategy)と呼びます。Code Generationはこのうちの1部分という位置づけです。
ちなみに、ハートマークはFowler自身がセマンティックモデルを直接実行するスタイルを好んでいる印としてつけています。本命はセマンティックモデルの直接実行であり、コードジェネレーションは仕方なくやっている、という匂いが文章の端々から感じられるためです。
Code Generation Patterns (What to produce)
コード生成のためのパターンのうち、「何を(どのようなスタイルのコードを)生成するか」についてのパターンを示したスライドです。
Model Ignorant Generationは、その名の通りモデルらしきものがまったく存在しないコードを生成するパターンです。モデルが持つ振る舞いはすべて、コードの中に手続きの形で平坦化されて埋めこまれます。これは、ターゲット環境がサポートする言語に抽象化能力が乏しく、モデルが構成できない場合や、モデルを実体化できるほどメモリリソースに余裕がない場合にある意味仕方なく取られるパターンです。もちろんFowlerはあまり好んではいません。
Model Aware Generationは、ターゲット環境上にも(限られた形態かもしれないものの)モデルを構築し、モデルを操作する形のコードを生成するパターンです。Fowlerお気にです。
Code Generation Patterns (How to produce)
続いて、「どうコードを生成するか」についてのパターンを示したスライドです。「どう作るか」は「何を作るか」に強く依存することに注意が必要です。
Templated Generationは、テンプレートエンジンを使ってコード出力するパターンです。生成対象となるコードで静的に決定される部分が多い場合に有効です。Model Ignorant Generationを使う場合、平坦化されたコードが一定のパターンで繰り返されることが多いため、このパターンが向いています。通常テンプレートエンジンは複雑な制御機構を持っていないため、分岐や選択が入り組んだ複雑な生成には向きません。
Transformer Generationは、モデルを変換するコードをカスタムで作るパターンであり、要はTemplated Generation以外の場合を指しています。複雑な制御が必要であったり、コードに動的に決定される部分が多い場合に向いています。Model Aware Generationを使う場合、コードの記述は最小限となり、繰り返しも少なく静的に決定される部分も小さいため、このアプローチが向いています。
Language Workbenches
言語ワークベンチは、「独自のカスタムDSLを容易に構築できるようにしてくれる環境」です。さらに次のスライドで、言語ワークベンチに共通する要素を紹介しています。FowlerのDSL概念と似た形はとっていますが、異なる部分もいくつかあります。
最も大きな違いは、セマンティックモデルが振る舞いを持つことはほとんどなく、必要な振る舞いはコードジェネレーションのプロセスでテンプレートエンジンによって埋め込まれる点です。
セマンティックモデルが振る舞いを持たないのは、言語ワークベンチが汎用的・統一的に個々のセマンティックモデルを扱えるようにするために「メタモデル」を用意した(せざるを得なかった)のが主な原因のようです。あまり詳しくはないのですが、メタモデルに汎用的な振る舞いの表現を埋め込むのは確かに難しそうです。
もう一つは、セマンティックモデルを様々な方法で視覚化したり、編集したりできる編集環境が用意されている点です。自分が見たツールでは、メタモデルと関連づけながら独自エディタを生成するための開発環境が用意されていました。
MOFとの関係
最後のMOFとの関連はおまけみたいなもんです。とりあえずMOFは忘れてよし!
手抜きで字だらけなのであまり分かりやすくはないと思いますが…
コメント