佐藤 竜一 監修
佐藤 竜一 翻訳
佐藤 竜一 原著
デバシィシュ・ゴーシュ 著
DSL(Domain-Specific Language:ドメイン特化言語)とは、特定の領域の問題に特化したコンピュータ言語です。ビジネス上の概念を表現するにせよ、コンピュータ内部の処理を表現するにせよ、汎用のプログラミング言語では表現力に限界があり、その表現はたちまち煩雑なものとなりがちです。しかし、その問題に特化した言語、すなわちDSL を利用すれば、その問題を明確に表現、あるいはエレガントに解決することができます。DSLを使って高度なレベルで問題を表現することで、その問題に関わる専門家とのコミュニケーションを円滑にすることも可能です。
本書は、読者が自分自身でDSLを設計/実装し、それを効果的に利用するために必要となるすべての知識を提供します。そのようなDSLは独立した処理系として利用することも、既存のプログラミング言語に組み込んで利用することもできます。また本書を読むことで、Ruby、Scala、Groovy、Clojureといったモダンな言語を使ったメタプログラミングの技法を習得し、プログラマとしてさらなる高みに立つことができるでしょう。
第1部 DSL入門
第1章 ドメインの言葉を話す方法を学ぶ1.1 問題ドメインと解決ドメイン
1.1.1 問題ドメイン
1.1.2 解決ドメイン
1.2 ドメインモデリング:共通語彙の準備
1.2.1 共通語彙の利点
グルー(接着剤)としての共通語彙
テストケースにおける共通のテクノロジー
開発期間中の共通語彙
1.3 DSL入門
1.3.1 DSLとは何か?
一般的に使われる言語とDSLはどう違うのか?
ビジネスユーザーにとってのDSLとは?
1.3.2 一般的なDSL
1.3.3 DSLの構造
1.4 DSLの実行モデル
1.5 DSLの分類
1.5.1 内部DSL
1.5.2 外部DSL
1.5.3 テキストベース以外のDSL
1.6 いつDSLを利用するか
1.6.1 DSLの長所
DSLは表現力豊かである
DSLは簡潔である
DSLは高い抽象化レベルで設計されている
DSLはより高いリターンをもたらす
DSLベースの開発はスケーラブルである
1.6.1 DSLの短所
言語の設計は難しい
DSLは上流工程でのコストとなる
DSLの利用はパフォーマンスに影響を与える
DSLではツールによるサポートが期待できない場合がある
「また新しい言語を覚えなくちゃ」症候群
DSLによって言語間の不協和音が発生しうる
1.7 DSLと抽象の設計
1.8 まとめ
1.9 参考文献
2.1 Javaで最初のDSLを実装する
2.1.1 共通語彙の準備
2.1.2 Javaによる最初の実装
Orderクラスを実装する
Orderビルダーの利用
JavaによるDSLの分析
2.2 DSLをよりわかりやすくする
2.2.1 XMLを使ってドメインを外部化する
2.2.2 Groovy:より表現力豊かな実装言語
Groovyによるソリューション
methodMissingを使ったメソッドの組み込み
動的メソッド注入におけるGroovyのメタプログラミング技法
高階関数とクロージャに対する正規のサポート
2.2.3 Groovy DSLの実行
2.3 DSLの実装パターン
2.3.1 内部DSLパターン:共通特性と多様性
スマートAPI
構文木操作
型埋め込み
リフレクティブメタプログラミング
実行時メタプログラミング
コンパイル時メタプログラミング
2.3.2 外部DSLパターン:共通特性と多様性
コンテキスト駆動の文字列操作
XMLから利用可能なリソースへの変換
DSLワークベンチ
外部の埋め込みコードとDSLの混合
パーサーコンビネータベースのDSL設計
2.4 DSLの実装方法を選択する
既存のインフラストラクチャの再利用
既存の知識の活用
外部DSLの学習曲線
必要十分な表現力
合成可能性
2.5 まとめ
2.6 参考文献
3.1 DSLの組み込み方法
3.1.1 DSLの統合に注意すべき理由
3.2 内部DSLを組み込むためのパターン
3.2.1 Java 6のスクリプトエンジンの利用
Groovy DSLの準備
DSL実装とスクリプトの統合
Java 6のスクリプティングに関する問題
3.2.2 DSLラッパーの利用
準備作業
DSLの構築
Scalaの暗黙の型変換を使う
ユーザーが得るメリット
3.2.3 言語特有の統合機能
JavaコードとGroovy DSLの間のやり取り
Groovyクラスローダーを使ったより優れた統合方法
最終結果
3.2.4 Springベースの統合
Springの動的言語サポート
実装の構成
3.3 外部DSL向けの統合パターン
3.4 エラーと例外のハンドリング
3.4.1 例外の命名
3.4.2 入力エラーのハンドリング
型システムが使えない場合
パーサーの役割
3.4.3 例外的なビジネス状況の処理
3.5 パフォーマンスの管理
3.6 まとめ
3.7 参考文献
第2部 DSLの実装
第4章 内部DSLの実装パターン4.1 DSLの道具箱を準備する
4.2 埋め込みDSL:メタプログラミングのパターン
4.2.1 暗黙的コンテキストとスマートAPI
DSLの表現力を判定する
暗黙的コンテキストの定義
スマートAPIを使って表現力を向上させる
4.2.2 動的なデコレーターによるリフレクティブメタプログラミング
Javaによるデコレーター
Javaでの実装を改善する
Rubyによる動的なデコレーター
4.2.3 ビルダーを使ったリフレクティブメタプログラミング
Groovyビルダーの魔法
Groovyビルダーの内部
4.2.4 教訓:メタプログラミングのパターン
4.3 埋め込みDSL:型付けされた抽象を使うパターン
4.3.1 汎用的な抽象としての高階関数
グループ化された報告書の生成
基礎となる抽象の準備
最初の試行:特化した実装
汎用的な実装
4.3.2 明示的に型付けした制約によるドメインロジックのモデル化
Rubyにおける実行時検証
Scalaにおける明示的に型付けされた制約
4.3.3 教訓:型を使って考える
4.4 生成型DSL:実行時に定型コードを生成する
4.4.1 生成型DSLの動作原理
4.4.2 簡潔なDSLの設計に使えるRubyのメタプログラミング
クラスメソッドを使って妥当性検査を抽象化する
動的なメソッド生成を行うミクシン
最後のグルー(接着剤)
4.5 生成型DSL:マクロによるコンパイル時のコード生成
4.5.1 Clojureによるメタプログラミング
4.5.2 ドメインモデルの実装
4.5.3 Clojureマクロの美しさ
4.6 まとめ
4.7 参考文献
5.1 動的な型付けによってDSLを簡潔にする
5.1.1 読みやすさ
5.1.2 ダックタイピング
ダックタイピングによるポリモーフィズムの実現
取引ドメインの例
5.1.3 メタプログラミングについてもう一度
5.1.4 なぜRuby、Groovy、Clojureなのか
5.2 Rubyによる取引処理DSL
5.2.1 APIから始める
基礎となる抽象
DSLファサード
5.2.2 ちょっとしたモンキーパッチ
5.2.3 DSLインタプリタの実装
インタプリタの追加
ボブの言語を話すということ
5.2.4 デコレーターとしてドメインルールを追加する
取引DSL:今いる場所
ドメインルールの実装
デコレーターを使ったRuby DSL
5.3 注文処理DSL:Groovyの最後のフロンティア
5.3.1 これまでの注文処理DSL
5.3.2 メタプログラミングのスコープの制御
GroovyのMOPとカテゴリー
基本的なDSL
5.3.3 仕上げ
5.4 Clojureを使って考え方を変える
5.4.1 ドメインオブジェクトの構築
5.4.2 デコレーターを使ってドメインオブジェクトをエンリッチする
Clojureのコンビネータの使い方
高階関数を使ったデコレーター
Clojureのマクロを使ってまとめ上げる
これまでにやったこと
5.4.3 REPLによるDSLセッション
5.5 従うべき指針
5.5.1 複雑さ最小の原則の遵守
5.5.2 最適な表現力の尊重
5.5.3 入念に設計された抽象の原則を弱めない
5.5.4 言語間の不協和音を避ける
5.6 まとめ
5.7 参考文献
6.1 なぜScalaか?
6.2 Scala DSLに向けた最初の一歩
6.2.1 Scala DSLを使ったJavaオブジェクトのテスト
6.2.2 JavaオブジェクトのラッパーとしてのScala DSL
6.2.3 さほど重要ではない機能をScala DSLでモデル化
6.3 ScalaでDSLを使ってみよう
6.3.1 表現力豊かな構文
6.3.2 ドメイン抽象の生成
証券
口座と取引
6.4 取引生成DSLの構築
6.4.1 実装の詳細
暗黙の型変換
暗黙の型変換の詰め合わせ
implicitとレキシカルスコープ
6.4.2 DSL実装パターンのバリエーション
6.5 DSLでビジネスルールをモデル化する
6.5.1 拡張可能なVisitorとしてのパターンマッチング
6.5.2 ドメインモデルの強化
6.5.3 DSLによる税および手数料計算のビジネスルール
適用可能な税および手数料のリストを取得する
税および手数料の算出
DSLとAPI:何が違うのか?
6.6 すべてをつなぎ合わせる
6.6.1 トレイトと型を使ったさらなる抽象
6.6.2 具象ドメインコンポーネントの作成
6.7 DSLの合成
6.7.1 拡張を使った合成
DSLを成長させる
プラグイン可能なセマンティクスを持った合成DSL
関数コンビネータを使った合成
完全に合成されたDSLを使う
6.7.2 階層的な組み合わせを使って異なるDSLを合成する
実装の結合を避ける
残高をどのようにモデル化するか
残高DSLをポートフォリオDSLに合成する
6.8 DSLのモナド構造
モナドとは何か
モナドによる「偶有的な複雑性」の削減
モナドを使った取引DSLの設計
6.9 まとめ
6.10 参考文献
7.1 外部DSLの解剖学
7.1.1 単純さが最優先
7.1.2 ドメインモデルの抽象化
大きなボックスをモジュラー化する
セマンティックモデル
セマンティックモデルの生成
7.2 外部DSL設計におけるパーサーの役割
7.2.1 パーサーとパーサージェネレータ
7.2.2 構文主導型変換
ANTLRを使った例をセットアップする
レクサーの設計
文法規則の設計
独自のアクションとして外部コードを埋め込む
パーサーモジュールの構築
ここまでの道のり
7.3 パーサーの分類
7.3.1 単純なトップダウンパーサー
LL(1)再帰下降パーサー
LL(k)再帰下降パーサー
7.3.2 より高度なトップダウンパーサー
再帰下降バックトラックパーサー
メモ化パーサー
述語制御パーサー
7.3.3 ボトムアップパーサー
演算子順位パーサー
LR(k)パーサー
LRパーサーのバリエーション
実際には何を使えばいいのか
7.4 Xtextを使ったツールベースのDSL開発
7.4.1 文法規則とアウトラインビュー
7.4.2 文法に対するメタモデル
7.4.3 セマンティックモデルに対するコード生成
Xpandテンプレートを使ったコード生成
DSLスクリプトの処理
長所と短所(ただし、長所が大部分)
7.5 まとめ
7.6 参考文献
8.1 パーサーコンビネータ
8.1.1 パーサーコンビネータとは何か
8.1.2 パーサーコンビネータによるDSLの設計
8.2 Scalaのパーサーコンビネータライブラリ
8.2.1 パーサーコンビネータライブラリ中の基本的な抽象
8.2.2 コンビネータによってパーサーをつなぎ合わせる
すべての文法規則は関数
逐次合成コンビネータ
選択コンビネータ
逐次合成(選択保持)コンビネータ
繰り返しコンビネータ
すべてをまとめる
8.2.3 DSLパーサーコンビネータ用のモナド
逐次合成コンビネータの実装:大変な方法
モナドの利用:ママ見て、余計なコードがなくなったよ!
8.2.4 Packratパーサーで左再帰のDSL構文をパースする
Packratパーサーはメモ化によって効率を上げている
Packratパーサーは左再帰をサポートする
Packratパーサーはスキャナなしでパースできる
意味述語のサポート
順序選択
8.3 パーサーコンビネータを使ったDSLの設計
8.3.1 ステップ1:文法の実行
8.3.2 ステップ2:DSLのセマンティックモデルの構築
関数適用に対するコンビネータ
部分関数の適用に対するコンビネータ
8.3.3 ステップ3:注文を表現する抽象の設計
8.3.4 ステップ4:関数適用コンビネータを使ってASTを生成する
8.4 Packratパーサーを使ったDSL
8.4.1 ドメインの問題の紹介
ビジネス処理の理解
実装するSSIルールのサンプル
8.4.2 文法の構築
8.4.3 セマンティックモデルの設計
8.4.4 パーサー合成によるDSLセマンティクスの拡張
独自の拡張に対するモナド
デコレーターとして独自のパーサーを設計する
デコレーターを追加する
8.5 まとめ
8.6 参考文献
第3部 DSL開発の将来
第9章 DSL設計:未来の展望9.1 DSLの設計に対する言語サポートの拡充
9.1.1 表現力を向上させる努力
9.1.2 メタプログラミングの強力さ
9.1.3 XMLの代わりにS式を使う
9.1.4 パーサーコンビネータの普及
9.2 DSLワークベンチ
9.2.1 DSLワークベンチとは何か
9.2.2 DSLワークベンチを利用することによるメリット
9.3 IDEツールによるサポート
9.4 DSLの進化
9.4.1 DSLのバージョニング
9.4.2 DSLのスムーズな進化に関するベストプラクティス
暗黙的コンテキストを使ってバージョンの進化を容易にする
自動変形による後方互換性の維持
DSLファサードで多数のバージョン管理問題に対処する
入念に設計された抽象の原則に従う
9.5 まとめ
9.6 参考文献
A.1 入念に設計された抽象の特性
A.1.1 最小化
A.1.2 蒸留
A.1.3 拡張性と合成可能性
A.2 最小化:約束したものだけを公開する
A.2.1 汎用的な型を使った進化
A.2.2 実装の露出を防ぐためのサブタイプ化
A.2.3 実装継承を正しく使う
A.3 蒸留:必要なもののみを残す
A.3.1 何が“余計な”ものなのか
A.3.2 偶有的な複雑性
A.3.3 汚染の除去
A.3.4 DIによって実装の詳細を追い出す
A.4 拡張性による段階的な成長の実現
A.4.1 拡張性とは何か
A.4.2 ミクシン:拡張性のためのデザインパターン
A.4.3 Mapの拡張にミクシンを使う
A.4.4 関数拡張性
A.4.5 拡張性も「猿真似」になり得る
A.5 合成可能性は純粋性から生まれる
A.5.1 合成可能性に対するデザインパターン
A.5.2 言語に戻って
プロトタイプベースのオブジェクト指向
どこにでもあるメタプログラミング
A.5.3 副作用と合成可能性
コマンドとクエリーの分離
Haskellでの例
A.5.4 合成可能性と並行性
A.6 参考文献
B.1 DSLにおけるメタプログラミング
B.1.1 DSL実装における実行時メタプログラミング
B.1.2 DSL実装におけるコンパイル時メタプログラミング
C++:テンプレート
LispとClojure:マクロ
Java:アノテーション処理とAOPのサポート
B.2 DSLとしてのLisp
B.2.1 Lispの何が特別なのか
B.2.2 データとしてのプログラムコード
B.2.3 プログラムコードとしてのデータ
B.2.4 リスト構造だけをパースする単純なパーサー
B.3 参考文献
C.1 Rubyが持つDSL向けの機能
C.2 参考文献
D.1 Scalaが持つDSL向けの機能
D.2 参考文献
E.1 Groovyが持つDSL向けの機能
E.2 参考文献
F.1 Clojureが持つDSL向けの機能
F.2 参考文献
G.1 IDEにどんな機能を求めるか
G.2 Java/Groovy開発環境の構築
G.3 Java/Scala開発環境の構築
G.4 多言語開発向けの人気の高いIDE
監訳を終えて — 佐藤 竜一
索引
金融取引システムの基礎知識
金融取引システム:取引と決済
金融取引システム:顧客注文の処理
金融取引システム:顧客の口座
金融取引システム:取引の現金価格
金融取引システム:証券の種類
金融取引システム:標準決済指図(SSI)
付属データはこちら
内容についてのお問い合わせは、正誤表、追加情報をご確認後に、お送りいただくようお願いいたします。
正誤表、追加情報に掲載されていない書籍内容へのお問い合わせや
その他書籍に関するお問い合わせは、書籍のお問い合わせフォームからお送りください。
本書の書影(表紙画像)をご利用になりたい場合は書影許諾申請フォームから申請をお願いいたします。
書影(表紙画像)以外のご利用については、こちらからお問い合わせください。
刷数は奥付(書籍の最終ページ)に記載されています。
書籍の種類:
書籍の刷数:
本書に誤りまたは不十分な記述がありました。下記のとおり訂正し、お詫び申し上げます。
対象の書籍は正誤表がありません。
発生刷 | ページ数 | 書籍改訂刷 | 電子書籍訂正 | 内容 | 登録日 | ||||||
---|---|---|---|---|---|---|---|---|---|---|---|
1刷 | 116 図4.8 |
未 | 未 |
|
2013.09.12 | ||||||
1刷 | 116 図4.9 |
未 | 未 |
|
2013.09.12 |
kannkyo さん
2018-12-08
比較的実践的なドメイン固有言語(DSL)の入門書。 Java、Scala、Ruby及びGroovy等の複数言語のDSLの実装方法を幅広く紹介する。DSL云々以前の基本的な文法の説明はしてくれないので、読者に要求される技術レベルは高い。 が、日本であまり普及していないDSLを幅広く知るには、最善の一冊。
river125 さん
2015-01-01
DSLについて勉強。巨匠マーチン・ファウラーの本は読み疲れしそうだったので、こっちを読んでみたが、こっちも疲れた。DSLを学問的研究対象と見てるのかな。もう少しコード例を増やして実践的な側面を重視して欲しかった。掲載コードも、あんまりDSLの利点を実感できない印象。読み終えて、さぁClojureで(あるいはRubyで)DSLを実装しよう、という気にはならなかった。
Tadatoshi Sekiguchi さん
2013-01-05
DSLの概要からデザインパターン、内部DSLの実装、外部DSLの実装まで一通り解説している本。DSL in Actionの邦訳。DSL本としては圧倒的なボリュームで、xTextといったDSL専用プラットフォームにも言及している。内部DSL, 外部DSLの解説がScala押しで、Scala DSLを始めるにあたり読んでおきたい。またDSLを考える上で、抽象型をどのように考えるかといった考え方が付録についており参考になる。実例は金融(証券)を題材としていて、金融ドメインの知識があるとすんなり入ってくる。