Upload
seeyoung-chang
View
1.286
Download
3
Embed Size (px)
DESCRIPTION
DSL로 만나는 Groovy - Spring Camp 2013 발표자료 관련 소스: https://github.com/seeyoung/GroovyDSL 발표 동영상: http://www.youtube.com/watch?v=VQSJ2harjoI
Citation preview
DSL로 만나는 Groovy
장 시 영
KGGUG
DSL
•DSLR? DSL? A domain-specific language (DSL) is a computer language specialized to a particular application domain.
http://en.wikipedia.org/wiki/Domain-specific_language
http://www.aladin.co.kr/shop/wproduct.aspx?ISBN=8991268994
•DSL <-> GPL(General Purpose Language)
•DSL = Mini Languages
•DSL Example => XML, HTML, CSS, SQL
•Groovy로 해석되는 DSL – 각종 Builder, GORM, gradle, Grails
Groovy?
• Ruby?
• Dynamic Language?
• 다양한 빌더
• Grails, gradle, GORM 등
Groovy Builder DSL – XML writer = new StringWriter() builder = new groovy.xml.MarkupBuilder(writer) builder.numbers { description 'Squares and factors of 10..15' for (i in 10..15) { number (value: i, square: i*i) { //#1 for ( j in 2..<i) { if (i % j == 0) { factor (value: j) //#2 } } } } } println writer http://groovyconsole.appspot.com/
Groovy Builder DSL - HTML def writer = new StringWriter() def html = new groovy.xml.MarkupBuilder(writer) html.html { head { title 'Constructed by MarkupBuilder' } body { h1 'What can I do with MarkupBuilder?' form (action:'whatever') { for (line in [ 'Produce HTML', 'Produce XML', 'Have some fun' ]){ input(type:'checkbox',checked:'checked', id:line, '') label(for:line, line) br('') } } } } println writer
GORM – DSL • ORM DSL
– Mapping • Table, Column mapping • Relational mapping
– ORM관련 설정 • Cache 전략 • Custom ID 전략 • Composite Primary Keys • Index 설정
– http://grails.org/doc/latest/guide/single.html#ormdsl
• Query DSL – Basic Query
• list, get, getAll
– Dynamic Finders • findByXXX
– Book.findByTitle(„정글만리‟), findByTitleLike(„%정글‟) – http://grails.org/doc/latest/ref/Domain%20Classes/findBy.html
Groovy로 만든 한글 DSL
Object.metaClass.을 =
Object.metaClass.를 =
Object.metaClass.의 =
{ clos -> clos(delegate) }
먼저 = { it }
표시하라 = { println it }
제곱근 = { Math.sqrt(it) }
먼저 100 의 제곱근 을 표시하라
먼저(100).의(제곱근).을(표시하라)
출처: http://it.gilbird.com/textyle/8318
Groovy는 왜 DSL에 강한가?
• Dynamic Language – Dynamic Type
num = 10; str = “20” assert num instanceof Integer assert str instanceof String
– Closure • Caller에게 양보하기
– MOP(Meta Class, Expando Class) • 요술상자, 아메바
– Groovy‟s chain method calls (GEP 3) • 괄호 빼기
먼저 100 의 제곱근 을 표시하라 먼저(100).의(제곱근).을(표시하라)
• JVM 기반
– Groovy는 결국 Java Class로 컴파일 – 거의 95%이상 Java와 동일하게 코딩 가능 – Java와 Groovy의 혼용
Groovy MOP
• MOP(Meta Object Protocol)
– MetaObjectProtocol
• http://en.wikipedia.org/wiki/Metaobject
• MetaClass, ExpandoMetaClass http://mrhaki.blogspot.kr/2009/10/groovy-goodness-expando-as-dynamic-bean.html
– 요술을 부리는 MOP Hooks
• invokeMethod, methodMissing, get/setProperty, propertyMissing
Groovy MetaClass
MOP Hooks - invokeMethod
import org.codehaus.groovy.runtime.StringBufferWriter import org.codehaus.groovy.runtime.InvokerHelper class Traceable implements GroovyInterceptable { Writer writer = new PrintWriter(System.out) private int indent = 0 Object invokeMethod(String name, Object args){ writer.write("\n" + ' '*indent + "before method '$name'") writer.flush() indent++ def metaClass = InvokerHelper.getMetaClass(this) def result = metaClass.invokeMethod(this, name, args) indent-- writer.write("\n" + ' '*indent + "after method '$name'") writer.flush() return result } } class Whatever extends Traceable { int outer(){ return inner() } int inner(){ return 1 } } def log = new StringBuffer() def traceMe = new Whatever(writer: new StringBufferWriter(log)) assert 1 == traceMe.outer() println log
Method 실행 순서
MOP Hooks – methodMissing class GORM { def dynamicMethods = [...] // an array of dynamic methods that use regex def methodMissing(String name, args) { def method = dynamicMethods.find { it.match(name) } if(method) { GORM.metaClass."$name" = { Object[] varArgs -> method.invoke(delegate, name, varArgs) } return method.invoke(delegate,name, args) } else throw new MissingMethodException(name, delegate, args) } } http://groovy.codehaus.org/Using+methodMissing+and+propertyMissing
Groovy Closure
def lineFile = new File(getClass().getResource("numbers.txt").getPath()) def sumValue = 0, multiflyValue = 1, concateValue = '' lineFile.eachLine { sumValue += Integer.parseInt(it) multiflyValue *= Integer.parseInt(it) concateValue += it } assert sumValue == 10 assert multiflyValue == 24 assert concateValue == '1234'
한국어 DSL로 돌아와서
Object.metaClass.을 =
Object.metaClass.를 =
Object.metaClass.의 =
{ clos -> clos(delegate) }
먼저 = { it }
표시하라 = { println it }
제곱근 = { Math.sqrt(it) }
먼저 100 의 제곱근 을 표시하라
먼저(100).의(제곱근).을(표시하라)
100.제곱근 을 표시하라
출처: http://it.gilbird.com/textyle/8318
관련 자료
• http://notes.3kbo.com/groovy-dsls • http://en.wikipedia.org/wiki/Domain-
specific_language • DSL 번역본 • 프로그래밍 그루비 • 한국어 DSL • Groovy for Domain-Specific Languages • http://en.wikipedia.org/wiki/Metaobject • http://groovy.codehaus.org/api/overview-
summary.html • Groovy Grails 의 좋은 점 • ★ Groovy