SlideShare a Scribd company logo
DSL&Builder Grails Code Reading  2008/05/23 上原潤二
DSL 対象領域特化型言語 楽譜♪ , MML, HTML, VHDL, *.ini, *.property, XAML, XUL, Windows のリソース定義言語 ,GIMP の Script-fu, elisp, AutoLISP, Postscript, アセンブラ ( 機械語記述専用言語 ),.. ⇔ 汎用言語
API と DSL               業務特化 構文  汎用言語  ->  DSL 語彙  標準API  ->  ドメインモデル
DSL の利点 文脈の限定 ( 前提の決め・制限 ), 詳細や不要機能の隠蔽による 簡潔性・簡易化 高密度 : 変更・レビューが容易 高抽象 : インピーダンスギャップ低減 Grails では .. Groovy 記述部分 (Domain, Contoller, ..) が DSL   ->  Grails の主たるアドバンテージの源泉の一つ
内部 DSL 言語自身の自己カスタマイズ機能など を駆使して言語上に作り上げるカスタム言語 ⇔外部DSL(パーサをちゃんと作る) 作るのが面倒 Groovyは内部DSLが得意
DSL の問題点 新しい言語を覚える必要がある 言語仕様のドキュメント化が必要 最終的にはソースを読む
DSL にべんりな Groovy オペレータオーバーロード ルーズステートメント AST 変換 クロージャ (+MOP) Builder  ← 今日のメインテーマ MOP ダイナミックファインダー 明示的なコンパイルが不要 fluent inteface 日本語メソッド名・クラス名
Builder とは何か AKA GroovyMarkup ツリー型データ構造をクロージャ ( と MOP) を駆使して簡潔に書き下す
例えばこんな感じ (1)
ビルダー記述の一般構造 < ビルダーオブジェクト>  = new  なんとかビルダー () < ビルダーオブジェクト >.< トップレベルメソッド > { メソッド名 ( 属性名 : 属性値 ,  属性名 : 属性値 ,...) { : } メソッド名 ( 属性名 : 属性値 ,  属性名 : 属性値 ,...) { : }.. }
ビルダー分類学 (1) ビルダー作成支援クラスから継承して作る groovy.util.BuilderSupport groovy.util.FactoryBuilderSupport 自前方式 ( 支援クラスを使用しない ) 自前方式のものを「ビルダー」と呼べるかはやや?だがここでは「広義のビルダー」としておく。
ビルダー分類学 (2) メソッド名を動的に作る MOPで実装 メソッド名は静的に定まっている 静的にメソッドを定義しておく  or MOPで実装
ビルダー実例 ConfigSlurper CliBuilder 自前方式 Grails のビルダーたち constraints, UrlMapping, BeanBuilder,WebBeanBuilder, FlowBuilder, HibernateMappingBuilder, HibernateCriteriaBuilder, JSonBuilder FactoryBuilderSupport を継承 ->  SwingBuilder, ObjectGraphBuilder, JmxBuilder BuilderSupport を継承 -> MarkupBuilder, DOMBuilder, AntBuilder, SAXBuilder, NodeBuilder 支援クラスを使用 メソッド名静的 メソッド名動的
ビルダーを作ろう! Let's Build a Builder!
ビルダー DSL の基本構造 パターン 1( ビルダーを明示使用 ) < ビルダーオブジェクト >.< トップレベルメソッド > { メソッド名 ( 属性名 : 属性値 ,  属性名 : 属性値 ,...) { }.. } パターン 2( ごくさりげない DSL) static hogehoge =  { メソッド名 ( 属性名 : 属性値 ,  属性名 : 属性値 ,...) { }.. } パターン 3( スクリプトファイルとして独立 ) < トップレベルメソッド > { メソッド名 ( 属性名 : 属性値 ,  属性名 : 属性値 ,...) { }.. }
実例紹介 MarkupBuilder(Groovy) UrlMapping Builder(Grails) ロボビルダー
MarkupBuilder 木は作らない ステートマシンで逐次出力 groovy-1.6-beta-1/src/main/groovy/xml/MarkupBuilder.java
BuilderSupport class BuilderSupport ... { : protected abstract void setParent(Object parent, Object child); protected abstract Object createNode(Object name); protected abstract Object createNode(Object name, Object value); protected abstract Object createNode(Object name, Map attributes); protected abstract Object createNode(Object name, Map attributes, Object value); } groovy-1.6-beta-1/src/main/groovy/util/BuilderSupport.java
UrlMappingBuilder(1) こういうやつ class UrlMappings { static mappings = { &quot;/$controller/$action?/$id?&quot;{ constraints { // apply constraints here } } &quot;500&quot;(view:'/error') } }   grails-1.0-RC1/src/grails/grails-app/conf/UrlMappings.groovy
UrlMappingBuilder(1) こういうやつ class UrlMappings { static mappings = { &quot;/ $ controller/ $ action?/$id?&quot;{ constraints { // apply constraints here } } &quot;500&quot; (view:'/error') } } なんだこれ?文字列? GString? grails-1.0-RC1/src/grails/grails-app/conf/UrlMappings.groovy
UrlMappingBuilder(2) public List evaluateMappings(Closure closure) { UrlMappingBuilder builder = new UrlMappingBuilder(); closure.setDelegate(builder);  //  デレゲートをセットしてクロージャを呼ぶ closure.call(); : public Object invokeMethod(String methodName, Object arg) { private Object _invoke(String methodName, Object arg, Object delegate) { if( methodName.startsWith(SLASH)  || isResponseCode) { // スラッシュで始まってる場合分岐 : public Object  getProperty(String name)  { if(urlDefiningMode) { previousConstraints.add(new ConstrainedProperty(UrlMapping.class, name, String.class)); return CAPTURING_WILD_CARD; // &quot;(*)&quot;  変数をワイルドカードに置き換え } else { return super.getProperty(name); } } grails-1.0-RC1/src/web/org/codehaus/groovy/grails/web/mapping/DefaultUrlMappingEvaluator.java
種明かし Groovy は文字列定数がメソッド名になる &quot;println&quot;(&quot;hello&quot;);  ←OK a=&quot;rintln&quot;; “p$a&quot;(&quot;hello&quot;);  ←OK invokeMethod でキャプチャ可能 GString 参照は getProperty でキャプチャ可能
ビルダーを作ってみよう ロボットを定義するDSL sample/ robot { body(texture:&quot;gcrlogo.png&quot;) { head(texture:&quot;earth.jpg&quot;) arm(x:-0.25){} leg(dummy:0) } } TransformGroup createArm(x, y, armLength, armWidth, dx=0, dy=0, dz=0, tx=null) { def trans = transformGroupBase() def shoulder = new Sphere(0.15f, Primitive.GENERATE_TEXTURE_COORDS | Primitive.GENERATE_NORMALS | Primitive.ENABLE_GEOMETRY_PICKING, createAppearance(tx)) def idou = new Transform3D();  idou.setTranslation(new Vector3d(x , y, 0)) def kaitenX = new Transform3D();  kaitenX.rotX(Math.PI*dx) def kaitenY = new Transform3D();  kaitenY.rotY(Math.PI*dy) def kaitenZ = new Transform3D();  kaitenZ.rotZ(Math.PI*dz) idou.mul(kaitenX);  idou.mul(kaitenY);  idou.mul(kaitenZ) trans.setTransform(idou);  trans.addChild(shoulder) def trans2 = transformGroupBase(false) def arm = new Cylinder(0.1f, armLength as float, Primitive.GENERATE_TEXTURE_COORDS |  Primitive.GENERATE_NORMALS | Primitive.ENABLE_GEOMETRY_PICKING, createAppearance(tx)) def idou2 = new Transform3D() idou2.setTranslation(new Vector3d(0, -armLength/2, 0)) trans2.setTransform(idou2) trans2.addChild(arm);  trans.addChild(trans2) ;  return trans } 以下のコードが1行に対応
TIPS メソッド xxx 呼び出しの括弧を省略したい getXxx() というメソッドを定義 ← 手軽 getProperty() でちゃんと定義
まとめ Groovyの簡潔記述能力 = Groovy言語機能 +  DSL による拡張能力 従って、 DSL を活用する -> Groovyの 真 のパワーを発揮 めんどうな3D処理を DSLでwrap (゚Д゚) ウマー Webアプリ3階層システムを Grailsが提供するDSLでwrap (゚Д゚) ウマー
参考リンク Groovy DSL roundup http://www.warneronstine.com/blog/articles/2008/04/24/groovy-dsl-roundup A Groovy DSL from scratch in 2 hours http://groovy.dzone.com/news/groovy-dsl-scratch-2-hours

More Related Content

KEY
Cocos2d Shaders
PDF
Hacking Ruby with Python
PDF
Boost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
PPTX
最新C++事情 C++14-C++20 (2018年10月)
PDF
並行プログラミングと継続モナド
PDF
競技プログラミングにおけるコードの書き方とその利便性
PPTX
エラーハンドリング
PPTX
C++0x総復習
Cocos2d Shaders
Hacking Ruby with Python
Boost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
最新C++事情 C++14-C++20 (2018年10月)
並行プログラミングと継続モナド
競技プログラミングにおけるコードの書き方とその利便性
エラーハンドリング
C++0x総復習

What's hot (19)

PDF
TypeScript & 関数型講座 第2回 TypeScript という言語
PDF
Haml 学習コース 初級編
PPTX
競技プログラミングのためのC++入門
PDF
オブジェクト指向できていますか?
PDF
C++入門?
PDF
C++でCプリプロセッサを作ったり速くしたりしたお話
PDF
Pfi Seminar 2010 1 7
PPT
次世代DaoフレームワークDoma
PDF
C++ Template Meta Programming の紹介@社内勉強会
PDF
闇魔術を触ってみた
PDF
Boost.Flyweight
PDF
組み込みでこそC++を使う10の理由
PDF
クロージャデザインパターン
PPTX
PDF
Emcpp item31
PDF
Hello Dark-Side C# (Part. 1)
PDF
はてなブックマークにおけるアクセス制御 - 半環構造に基づくモデル化
PDF
新しい並列for構文のご提案
TypeScript & 関数型講座 第2回 TypeScript という言語
Haml 学習コース 初級編
競技プログラミングのためのC++入門
オブジェクト指向できていますか?
C++入門?
C++でCプリプロセッサを作ったり速くしたりしたお話
Pfi Seminar 2010 1 7
次世代DaoフレームワークDoma
C++ Template Meta Programming の紹介@社内勉強会
闇魔術を触ってみた
Boost.Flyweight
組み込みでこそC++を使う10の理由
クロージャデザインパターン
Emcpp item31
Hello Dark-Side C# (Part. 1)
はてなブックマークにおけるアクセス制御 - 半環構造に基づくモデル化
新しい並列for構文のご提案
Ad

Viewers also liked (7)

PDF
Java x Groovy: improve your java development life
PDF
Seasar Conference2008 Grails(Final)
PDF
New features of Groovy 2.0 and 2.1
KEY
Java One 2012 Tokyo JVM Lang. BOF(Groovy)
PPT
Jo si se i tu també sessio torrent
PDF
Easy Going Groovy 2nd season on DevLOVE
PDF
Let's go Developer 2011 sendai Let's go Java Developer (Programming Language ...
Java x Groovy: improve your java development life
Seasar Conference2008 Grails(Final)
New features of Groovy 2.0 and 2.1
Java One 2012 Tokyo JVM Lang. BOF(Groovy)
Jo si se i tu també sessio torrent
Easy Going Groovy 2nd season on DevLOVE
Let's go Developer 2011 sendai Let's go Java Developer (Programming Language ...
Ad

Similar to Dsl&Builder (20)

PDF
G * magazine 0
PDF
Grailsのススメ(仮)
PDF
Groovy base gradle_20130309
PDF
「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」
PDF
Grails 2.0.0.M1の話
PDF
Grails-1.1を斬る!~Grails-1.1からのチーム開発~ in Tokyo
PDF
20110820 metaprogramming
PDF
groovy 2.1.0 20130118
PDF
明日から使えるgradle
PDF
Java開発の強力な相棒として今すぐ使えるGroovy
PDF
Gws 20130315 gradle_handson
PDF
Layout analyzerでのgroovyの利用について
PPTX
Letsgo sendai nobusue_20110528
PDF
G * magazine 1
KEY
Aizu lt tokyo_luxion
PDF
Gradleどうでしょう
ODP
こんにちはGroovy
PDF
現実世界のJRuby(ショートバージョン)
PDF
実践プログラミング DSL
PDF
Xtext And Grails20091218
G * magazine 0
Grailsのススメ(仮)
Groovy base gradle_20130309
「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」
Grails 2.0.0.M1の話
Grails-1.1を斬る!~Grails-1.1からのチーム開発~ in Tokyo
20110820 metaprogramming
groovy 2.1.0 20130118
明日から使えるgradle
Java開発の強力な相棒として今すぐ使えるGroovy
Gws 20130315 gradle_handson
Layout analyzerでのgroovyの利用について
Letsgo sendai nobusue_20110528
G * magazine 1
Aizu lt tokyo_luxion
Gradleどうでしょう
こんにちはGroovy
現実世界のJRuby(ショートバージョン)
実践プログラミング DSL
Xtext And Grails20091218

More from Uehara Junji (20)

PDF
Use JWT access-token on Grails REST API
PDF
Groovy Bootcamp 2015 by JGGUG
PDF
Groovy Shell Scripting 2015
PDF
Shibuya JVM Groovy 20150418
PDF
Markup Template Engine introduced Groovy 2.3
PDF
Introduce Groovy 2.3 trait
PDF
Indy(Invokedynamic) and Bytecode DSL and Brainf*ck
PDF
enterprise grails challenge, 2013 Summer
PDF
Groovy kisobenkyoukai20130309
PDF
Read Groovy Compile process(Groovy Benkyoukai 2013)
PDF
New feature of Groovy2.0 G*Workshop
KEY
G* Workshop in fukuoka 20120901
KEY
JJUG CCC 2012 Real World Groovy/Grails
KEY
Groovy 1.8の新機能について
KEY
Jggug ws 15th LT 20110224
PDF
Easy Going Groovy(Groovyを気軽に使いこなそう)
PDF
GroovyServ concept, how to use and outline.
PDF
Clojure
PDF
Groovy, Transforming Language
KEY
Jggug Nagoya 20090925 Groovy
Use JWT access-token on Grails REST API
Groovy Bootcamp 2015 by JGGUG
Groovy Shell Scripting 2015
Shibuya JVM Groovy 20150418
Markup Template Engine introduced Groovy 2.3
Introduce Groovy 2.3 trait
Indy(Invokedynamic) and Bytecode DSL and Brainf*ck
enterprise grails challenge, 2013 Summer
Groovy kisobenkyoukai20130309
Read Groovy Compile process(Groovy Benkyoukai 2013)
New feature of Groovy2.0 G*Workshop
G* Workshop in fukuoka 20120901
JJUG CCC 2012 Real World Groovy/Grails
Groovy 1.8の新機能について
Jggug ws 15th LT 20110224
Easy Going Groovy(Groovyを気軽に使いこなそう)
GroovyServ concept, how to use and outline.
Clojure
Groovy, Transforming Language
Jggug Nagoya 20090925 Groovy

Dsl&Builder

  • 1. DSL&Builder Grails Code Reading 2008/05/23 上原潤二
  • 2. DSL 対象領域特化型言語 楽譜♪ , MML, HTML, VHDL, *.ini, *.property, XAML, XUL, Windows のリソース定義言語 ,GIMP の Script-fu, elisp, AutoLISP, Postscript, アセンブラ ( 機械語記述専用言語 ),.. ⇔ 汎用言語
  • 3. API と DSL              業務特化 構文 汎用言語 -> DSL 語彙 標準API -> ドメインモデル
  • 4. DSL の利点 文脈の限定 ( 前提の決め・制限 ), 詳細や不要機能の隠蔽による 簡潔性・簡易化 高密度 : 変更・レビューが容易 高抽象 : インピーダンスギャップ低減 Grails では .. Groovy 記述部分 (Domain, Contoller, ..) が DSL   -> Grails の主たるアドバンテージの源泉の一つ
  • 5. 内部 DSL 言語自身の自己カスタマイズ機能など を駆使して言語上に作り上げるカスタム言語 ⇔外部DSL(パーサをちゃんと作る) 作るのが面倒 Groovyは内部DSLが得意
  • 6. DSL の問題点 新しい言語を覚える必要がある 言語仕様のドキュメント化が必要 最終的にはソースを読む
  • 7. DSL にべんりな Groovy オペレータオーバーロード ルーズステートメント AST 変換 クロージャ (+MOP) Builder ← 今日のメインテーマ MOP ダイナミックファインダー 明示的なコンパイルが不要 fluent inteface 日本語メソッド名・クラス名
  • 8. Builder とは何か AKA GroovyMarkup ツリー型データ構造をクロージャ ( と MOP) を駆使して簡潔に書き下す
  • 10. ビルダー記述の一般構造 < ビルダーオブジェクト> = new なんとかビルダー () < ビルダーオブジェクト >.< トップレベルメソッド > { メソッド名 ( 属性名 : 属性値 , 属性名 : 属性値 ,...) { : } メソッド名 ( 属性名 : 属性値 , 属性名 : 属性値 ,...) { : }.. }
  • 11. ビルダー分類学 (1) ビルダー作成支援クラスから継承して作る groovy.util.BuilderSupport groovy.util.FactoryBuilderSupport 自前方式 ( 支援クラスを使用しない ) 自前方式のものを「ビルダー」と呼べるかはやや?だがここでは「広義のビルダー」としておく。
  • 12. ビルダー分類学 (2) メソッド名を動的に作る MOPで実装 メソッド名は静的に定まっている 静的にメソッドを定義しておく  or MOPで実装
  • 13. ビルダー実例 ConfigSlurper CliBuilder 自前方式 Grails のビルダーたち constraints, UrlMapping, BeanBuilder,WebBeanBuilder, FlowBuilder, HibernateMappingBuilder, HibernateCriteriaBuilder, JSonBuilder FactoryBuilderSupport を継承 -> SwingBuilder, ObjectGraphBuilder, JmxBuilder BuilderSupport を継承 -> MarkupBuilder, DOMBuilder, AntBuilder, SAXBuilder, NodeBuilder 支援クラスを使用 メソッド名静的 メソッド名動的
  • 15. ビルダー DSL の基本構造 パターン 1( ビルダーを明示使用 ) < ビルダーオブジェクト >.< トップレベルメソッド > { メソッド名 ( 属性名 : 属性値 , 属性名 : 属性値 ,...) { }.. } パターン 2( ごくさりげない DSL) static hogehoge = { メソッド名 ( 属性名 : 属性値 , 属性名 : 属性値 ,...) { }.. } パターン 3( スクリプトファイルとして独立 ) < トップレベルメソッド > { メソッド名 ( 属性名 : 属性値 , 属性名 : 属性値 ,...) { }.. }
  • 16. 実例紹介 MarkupBuilder(Groovy) UrlMapping Builder(Grails) ロボビルダー
  • 17. MarkupBuilder 木は作らない ステートマシンで逐次出力 groovy-1.6-beta-1/src/main/groovy/xml/MarkupBuilder.java
  • 18. BuilderSupport class BuilderSupport ... { : protected abstract void setParent(Object parent, Object child); protected abstract Object createNode(Object name); protected abstract Object createNode(Object name, Object value); protected abstract Object createNode(Object name, Map attributes); protected abstract Object createNode(Object name, Map attributes, Object value); } groovy-1.6-beta-1/src/main/groovy/util/BuilderSupport.java
  • 19. UrlMappingBuilder(1) こういうやつ class UrlMappings { static mappings = { &quot;/$controller/$action?/$id?&quot;{ constraints { // apply constraints here } } &quot;500&quot;(view:'/error') } }   grails-1.0-RC1/src/grails/grails-app/conf/UrlMappings.groovy
  • 20. UrlMappingBuilder(1) こういうやつ class UrlMappings { static mappings = { &quot;/ $ controller/ $ action?/$id?&quot;{ constraints { // apply constraints here } } &quot;500&quot; (view:'/error') } } なんだこれ?文字列? GString? grails-1.0-RC1/src/grails/grails-app/conf/UrlMappings.groovy
  • 21. UrlMappingBuilder(2) public List evaluateMappings(Closure closure) { UrlMappingBuilder builder = new UrlMappingBuilder(); closure.setDelegate(builder); // デレゲートをセットしてクロージャを呼ぶ closure.call(); : public Object invokeMethod(String methodName, Object arg) { private Object _invoke(String methodName, Object arg, Object delegate) { if( methodName.startsWith(SLASH) || isResponseCode) { // スラッシュで始まってる場合分岐 : public Object getProperty(String name) { if(urlDefiningMode) { previousConstraints.add(new ConstrainedProperty(UrlMapping.class, name, String.class)); return CAPTURING_WILD_CARD; // &quot;(*)&quot; 変数をワイルドカードに置き換え } else { return super.getProperty(name); } } grails-1.0-RC1/src/web/org/codehaus/groovy/grails/web/mapping/DefaultUrlMappingEvaluator.java
  • 22. 種明かし Groovy は文字列定数がメソッド名になる &quot;println&quot;(&quot;hello&quot;); ←OK a=&quot;rintln&quot;; “p$a&quot;(&quot;hello&quot;); ←OK invokeMethod でキャプチャ可能 GString 参照は getProperty でキャプチャ可能
  • 23. ビルダーを作ってみよう ロボットを定義するDSL sample/ robot { body(texture:&quot;gcrlogo.png&quot;) { head(texture:&quot;earth.jpg&quot;) arm(x:-0.25){} leg(dummy:0) } } TransformGroup createArm(x, y, armLength, armWidth, dx=0, dy=0, dz=0, tx=null) { def trans = transformGroupBase() def shoulder = new Sphere(0.15f, Primitive.GENERATE_TEXTURE_COORDS | Primitive.GENERATE_NORMALS | Primitive.ENABLE_GEOMETRY_PICKING, createAppearance(tx)) def idou = new Transform3D(); idou.setTranslation(new Vector3d(x , y, 0)) def kaitenX = new Transform3D(); kaitenX.rotX(Math.PI*dx) def kaitenY = new Transform3D(); kaitenY.rotY(Math.PI*dy) def kaitenZ = new Transform3D(); kaitenZ.rotZ(Math.PI*dz) idou.mul(kaitenX); idou.mul(kaitenY); idou.mul(kaitenZ) trans.setTransform(idou); trans.addChild(shoulder) def trans2 = transformGroupBase(false) def arm = new Cylinder(0.1f, armLength as float, Primitive.GENERATE_TEXTURE_COORDS | Primitive.GENERATE_NORMALS | Primitive.ENABLE_GEOMETRY_PICKING, createAppearance(tx)) def idou2 = new Transform3D() idou2.setTranslation(new Vector3d(0, -armLength/2, 0)) trans2.setTransform(idou2) trans2.addChild(arm); trans.addChild(trans2) ; return trans } 以下のコードが1行に対応
  • 24. TIPS メソッド xxx 呼び出しの括弧を省略したい getXxx() というメソッドを定義 ← 手軽 getProperty() でちゃんと定義
  • 25. まとめ Groovyの簡潔記述能力 = Groovy言語機能 + DSL による拡張能力 従って、 DSL を活用する -> Groovyの 真 のパワーを発揮 めんどうな3D処理を DSLでwrap (゚Д゚) ウマー Webアプリ3階層システムを Grailsが提供するDSLでwrap (゚Д゚) ウマー
  • 26. 参考リンク Groovy DSL roundup http://www.warneronstine.com/blog/articles/2008/04/24/groovy-dsl-roundup A Groovy DSL from scratch in 2 hours http://groovy.dzone.com/news/groovy-dsl-scratch-2-hours