PHPにおける
DSL
PHPカンファレンス関西 2017
松藤 秀治 (2017-7-15)
じこしょうかい
● 松藤 秀治(まつふじ ひではる)
● matsu_hide
● フリーエンジニア/ND&I
はじめに
● 「PHPでDSLを使ってみるための一例」です。
● 「他にもこんな実装があるよー」という方はぜひ教えてく
ださい!
● いろいろ抜けているトピックが多々多々多々あると思いま
すが、生暖かい目で見ていただけると助かります(_ _)
DSLの例
SQL → RDBへの問い合わせ言語
シェルスクリプト → Unixなどで利用
CSS → HTMLの体裁を表現する
PHPはDSL?
「PHPは、最初の時点ではWebページ作成に使うツールを集
めたフレームワークであり、作者としても「スクリプト言語を作
るなどといった考えはまったくなかった」のであるが・・・」
(Wikipedia)
DSLから汎用のプログラミング言語に発展
DSLってなに?
Domain Specific Language (ドメイン特化(固有)言語)
「DSLとは、小さな問題領域に的を絞ったカスタム言語であ
る。DSLは、その領域に固有の表現で記述し、検証する。」
(ドメイン特化型開発 p.12)
それがない世界
RDBへの問い合わせをSQLを使わずに書く?
WebページをHTMLだけでデザインする?
問題領域に適した表現で記述することで理解しやすくなり、
生産性が上がる。⇒変化に強くなる
今回の問題領域(サンプル)
ECサイトである条件を満たすとき割引する。
「キャンペーン商品を含んでいる場合は合計金額から10%値
下げしたい。」
「合計金額が1000円を超えたら、送料無料にしたい。」
実践!DSL
パーサー(構文解析)
エンジン
エディター
実践!DSL
orz
実践!DSL
パーサー ⇒ YAML
エンジン ⇒ ExpressionLanguage (Symfony)
エディター ⇒ あきらめる (or Xtext)
ExpressionLanguage Component
式をコンパイルして、評価するエンジン。
ワンライナー(戻り値はbooleanでなくても可)
Symfonyが提供しているコンポーネント。
今回のDSL
キャンペーン商品の割引:
条件: カート.キャンペーン商品を含む()
割引: カート.商品合計() * 0.1
全体はYAMLで記述
「条件」と「割引」に
ExpressionLanguageを
使う
Cartクラス
...
public function 送料()
{
return $this->getShippingCost();
}
public function キャンペーン商品を含む ()
{
return $this->existsCampaignProduct();
}
public function 商品合計()
{
return $this->getProductTotalPrice();
}
...
ExpressionLanguageを使う部分(抜粋)
$el = new ExpressionLanguage();
foreach ($config as $name => $values) {
$isSatisfied = $el->evaluate($values['条件'], ['カート' => $cart]);
if (! $isSatisfied) continue;
$price = $el->evaluate($values['割引'], ['カート' => $cart]);
$cart->addDiscount(new Discount($name, $price));
}
デモ
オブジェクト指向で実装すると・・・
条件・割引をインターフェイスで抽象化したり。
DIコンテナで注入できるようにしたり。
などなど。
いずれにしても条件・割引のルールが変更されるたびに実
装が必要になる。
DSLのデメリット
設計が難しい。
 ・問題領域の特定
 ・想定外の要求に対してどう対応するか
DSLを使うかどうかに関わらず、難しい問題なので、設計力
が重要になってくる。
まとめ
● DSLは小さな問題領域にフォーカスしたものである。
● PHPでもライブラリなどを利用することによってDSLを定義
できる。
● DSLの設計は難しいがメリットも大きい。
● コードで実装することだけが解決策ではない。
参考
サンプル:
https://github.com/matsufuji/phpck2017-dsl
ExpressionLanguage:
http://symfony.com/doc/current/components/expression_
language.html

PHPカンファレンス関西2017 PHPにおけるDSL