23-ドメイン特化言語

プログラマが知るべき97のこと」の23個目のエピソードは、ドメイン特化言語DSL:Domain Specific Language)に関する話題です。「ドメイン」という用語は、DSLだけでなく、クラス設計としてのドメイン、上流工程におけるドメインなど様々な場面で登場します。ドメイン特化言語DSL)もその1つで、特定の分野(ドメイン)に対して、特化した語彙や語法を使用して表現を行う為に使用されます。DSLは、汎用的ではない反面、特定の分野については書きやすく読みやすいのが特徴です。ちなみに、ドメイン特化言語に対し、JavaやCなどの言語は汎用言語と呼ばれる事もあるようです。このエピソードでは、DSLの種類として内部DSLと外部DSLを解説し、プログラマDSLを設計する場合のヒントが書かれています。
内部DSLRubyScalaなどの柔軟な記法を許す言語が得意とする、プログラミング言語の記述パターンです。ScalaではRubyの影響を受け、DSLを作りやすい言語設計が意識されています。Rubyでは記述の自由度が高いため、様々な内部DSLが発明されています。代表的なのはRSpecではないでしょうか?

# bowling_spec.rb
require 'bowling'

describe Bowling, "#score" do
  it "returns 0 for all gutter game" do
    bowling = Bowling.new
    20.times { bowling.hit(0) }
    bowling.score.should == 0
  end
end

公式サイトのサンプルを引用しました。RSpecでは、英語でそのまま仕様(Spec)をほぼ記述でき、それをテストとして実行できます。頭の中で考えていることがそのままプログラムのコードとして記述できるのはDSLのメリットでしょう。
一方、Javaなどの言語では文法上の制約が多く、内部DSLを作る事が難しくなっています。しかし、少し工夫をしてみれば、RubyScalaほどは洗練された形にはならなくとも、書きやすく可読性が高いコードを書くことは可能です。アノテーション、static インポート、可変長引数などを駆使すると可能性は広がります。例えば次のようなコードでロジックを書く事ができます。

// 2つのタスクを並列に処理し、終わるまで待つ
new ParallelRunner() {
  @Override
  public void run() {
  }
  @Override
  public void runOther() {
  }   
}.invokeAndWait();

Javaっぽい部分は残ってしまうのは残念ですが、DSLっぽい記述はJavaでも可能です*1
2つ目は外部DSLで、特定の分野に特化したテキストなどを独自の文法で記述します。プログラムではその構文をパースし、実行コードに変換します。構文解析をサポートするライブラリも存在するため、必要に応じて簡単に作れるというのも魅力でしょう。設定ファイルを外部DSLとして記述しておけば設定ファイルが読みやすくなりますし、プログラムの仕様を外部ファイル(テキストやExcel)に定義しておく事もできるでしょう。単純なプロパティファイルやXMLファイルよりも簡単に記述でき、可読性が高くなります。

DSLを作る事で、ある分野に特化した上で作業や定義などを効率良く行う事ができます。つまり、汎用的にするよりも特化する事でシンプルになるということです。そのようなDSLを作る時に最も重要なのは使う側の立場で考えるということです。勿論、自分が最初のユーザになるのですから、少なくとも自分は使いやすいDSLを作る必要があるでしょう。
また、DSLを使い設計していくことで、コードを書くときの意識が変わってきます。コードを「どう書くか?」ではなく「どう使われるか?」を強く意識するようになってきます。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

*1:DSLというと怒られてしまうかもしれませんが、書きやすく読みやすければいいのです