Domain Specific Languages With Groovy

2,402 views
2,283 views

Published on

Domain Specific Language를 그루비로 만드는 법

Published in: Technology
2 Comments
6 Likes
Statistics
Notes
No Downloads
Views
Total views
2,402
On SlideShare
0
From Embeds
0
Number of Embeds
480
Actions
Shares
0
Downloads
33
Comments
2
Likes
6
Embeds 0
No embeds

No notes for slide

Domain Specific Languages With Groovy

  1. 1. Domain-Specific Languages With Groovy<br />Chun-Kil Kang<br />gilbird@naver.com, Twitter: @gilbirdk<br />
  2. 2.
  3. 3.
  4. 4. Expressing Requirements...<br />
  5. 5. 해결책은? DSL !<br />표현력이 월등more expressive<br />공통의 관심사common metaphore<br />전문가domain expert의 도움<br />비즈니스 로직과 애플리케이션 코드 분리<br />순환적 라이프사이클<br />
  6. 6. DSL 이란?<br />DSL: Domain-Specific Language<br />“Little Language”<br />Wikipedia<br />DSL은 특정 작업의 사용 목적으로 설계한 프로그램 언어.<br />DSL은 개념을 언어 구문으로 만들 수 있는 특정 범주의 지식에 한정된 언어이다.<br />
  7. 7. DSL ...<br />온 세상이 DSL<br />기술어Technical Dialects<br />표기법 Notations<br />비즈니스 용어 Business Languages<br />
  8. 8.
  9. 9. ^[w-.]+@([w-]){2,4}$<br />
  10. 10.
  11. 11.
  12. 12.
  13. 13. DSL의 특징<br />DSL은 언어이다.<br />특정 지식의 범주를 다룬다.<br />형식을가지고 있다. (문자 or 그림)<br />결과를 산출한다.<br />객체 설정, 데이터 구조 표현<br />내부 혹은 외부에 존재<br />호스트 언어에 임베드(E-DSL)<br />Standalone (custom parser)<br />어떤 질적 속성을 가짐<br />가독성 readability<br />가속성writability<br />유용성 usability<br />검증성 testability<br />확장성 extensibility <br />
  14. 14. Why Groovy?!<br />
  15. 15. HelloWorld.java<br />importjava.util.*;<br />publicclassHelloWorld{  publicstaticvoidmain( String[] args ) {     List langs = newArrayList();<br />     langs.add( "Groovy" );     langs.add( "Grails" );     langs.add( "Griffon" );<br />     Collections.sort(langs);<br />     for( Iterator it = langs.iterator(); it.hasNext(); )        System.out.println( "Hello " + it.next() );  }}<br />
  16. 16. HelloWorld.groovy<br />['Groovy', 'Grails', 'Griffon'].sort().each {    println"Hello $it"}<br />
  17. 17. 읽기 쉬운 코드? (Java)<br />
  18. 18. 읽기 쉬운 코드? (Groovy)<br />
  19. 19. 왜 Groovy인가?<br />왜 Groovy인가?<br />내부/임베드DSL 생성 가능<br />임베드DSL은 Java애플리케이션에 손쉽게 내장가능<br />DSL로 커버 못하는 영역은 Groovy사용<br />Custom parser는?<br />lexer/parser는 구현, 유지보수및 사용이 복잡<br />추가 구현 힘듬<br />복잡한 구문 구현 어려움<br />
  20. 20. 실세계Groovy 적용 예<br />보험 정책 위험도 계산 엔진<br />은행 계좌 규칙<br />대출 승인 규칙<br />인력 자원 : 직원 스킬 표현<br />바이러스 백신 시뮬레이션<br />시나리오에 따른 마켓 데이터 생성<br />...<br />
  21. 21. GroovyDSLs<br />
  22. 22. MarkupBuilder<br /><invoices><br /> <invoice><br /> <line>product 1</line><br /> <line>product 2</line><br /> </invoice><br /></invoices><br />newgroovy.xml.MarkupBuilder().invoices {<br /> invoice(id: "4") {<br />line("product 1")<br />line("product 2")<br /> }<br />}<br />
  23. 23. Groovy DSLs<br />XMLBuilder<br />HTMLBuilder<br />AntBuilder<br />SwingBuilder<br />Grails<br />Griffon<br />Gradle<br />Grape<br />
  24. 24. Groovy가 제공하는 것들<br />
  25. 25. Java vs. Groovy<br />Java<br />Class  행동<br />컴파일러가 모든 규칙 인지<br />행동은 바이트코드로 고정<br />Groovy<br />Class와 MetaClass 행동<br />동적 언어<br />컴파일러는 행동에 대하여 모름<br />행동은 완전히 실행시간에 동적임<br />
  26. 26. Groovy MOP<br />Meta Object Protocol<br />모든 것은 MOP을 통함<br />메소드호출, 속성 액세스, 연산자...<br />그래서 Groovy는 “동적언어”<br />완전하게 실행시간에Groovy 코드를 커스터마이즈가능함<br />1+1=1 ? 가능함! 어떻게?<br />
  27. 27. 런타임 시스템 후킹<br />GroovyObject<br />invokeMethod()<br />get/setProperty()<br />Categories<br />MetaClass<br />invokeConstructor() / method() / staticMethod()<br />invokeMissingMethod() / invokeMissingProperty()<br />get/setProperty()<br />ExpandoMetaClass<br />Integer.metaClass.plus = { Integeri -> 1 }<br />
  28. 28. 연산자 오버로딩<br /><ul><li>환율 연산
  29. 29. 30.won + 15.euro
  30. 30. 거리
  31. 31. 12.kilo.meters + 3.meters
  32. 32. 병렬, 작업 흐름
  33. 33. taskA & taskB | taskC
  34. 34. 계좌 기입
  35. 35. account << 10.won
  36. 36. account += 10.dollar</li></ul>+ a.plus(b)<br />- a.minus(b)<br />* a.multiply(b)<br />/ a.divide(b)<br />% a.modulo(b)<br />| a.or(b)<br />& a.and(b)<br />a[b] a.getAt(b)<br />a<<b a.leftShift(b)<br />
  37. 37. 속성에 숫자 추가<br />category로 숫자에 메소드와 속성 추가 가능<br />classMyCategory {static Distance getMeters(Integer n) {new Distance(n, Distance.METER) }}<br />use (MyCategory) {println3.meters}<br />
  38. 38. ExpandoMetaClass<br />Grails에서 ExpandoMetaClass공헌<br />Integer.metaClass.getMeters = { ->new Distance(delegate, Distance.METER)}<br />println3.meters<br />
  39. 39. 융통성 있는 문법<br />괄호 생략<br />move left<br />monstor.move x: 3.meters, y: 4.meters<br />compare indicator: ’NIKEI’, withFund: ’XYZ’<br />account.debit amount: 30.won, in: 3.days<br />리스트와 맵 문법 내장<br />List<br />[1, 2, 3, 4]<br />Map<br />[a:1, b:2, c:3]<br />Range<br />Monday..Friday<br />
  40. 40. 트리 구조 빌더<br />트리 구조 데이터 생성 가능<br />클로저를 마지막 인자로 받는 메서드 체인 호출 구조<br />newMarkupBuilder().invoices {invoice( id: “4”) {line“product 1”line“product 2” }}<br />손쉽게 자신만의 빌더 생성 가능!<br />
  41. 41. BuilderSupport<br />Implement BuilderSupport<br />구현 해야 하는 메서드<br />createNode(name)<br />createNode(name, map)<br />createNode(name, value)<br />createNode(name, map, value)<br />nodeCompleted(parent, node)<br />postNodeCompletion(parent, node)<br />
  42. 42. 커스텀 제어 구조<br />클로저closure를 메서드파라메터로 전달<br />unless( account.balance<0, {account.debit10.dollars})<br />단축 표기법<br />unless (account.balance < 0) {account.debit10.dollars}<br />무엇이든 만들어 보세요!<br />withLock(aLock) { ... }<br />transactional { ... }<br />async { ... }<br />execute(within: 50.seconds) { ... }<br />
  43. 43. RobotBuilder<br />defwallE = newRobotBuilder().robot('Wall E') {<br />forward( dist: 20)<br />left( rotation: 90)<br />forward( speed: 10, duration: 5)<br />}<br />wallE.go()<br />
  44. 44. Builder 최종 인스턴스 구조<br />
  45. 45. FactoryBuilderSupport<br />classRobotBuilderextendsFactoryBuilderSupport {<br /> {<br />registerFactory( 'robot', newRobotFactory())<br />registerFactory( 'forward', newForwardMoveFactory())<br />registerFactory( 'left', newLeftTurnFactory())<br /> };<br />}<br />
  46. 46. Robot<br />class Robot {<br /> String name<br />def movements = []<br />void go() {<br />println"$name 로봇 동작합니다..."<br />movements.each { movement -><br />println movement<br /> }<br /> }<br />}<br />
  47. 47. ForwardMove, LeftTurn<br />classForwardMove {<br />def dist<br /> String toString() { "이동! 거리... $dist" }<br />}<br />classLeftTurn {<br />def rotation<br /> String toString() { "좌회전! 이동각... $rotation 도" }<br />}<br />
  48. 48. AbstractFactory<br />publicabstractclassAbstractFactoryimplementsFactory {<br />publicbooleanisLeaf() { return false; }<br />publicbooleanonHandleNodeAttributes( FactoryBuilderSupport builder,<br /> Object node, Map attributes) { return true; }<br />public void onNodeCompleted( FactoryBuilderSupport builder,<br /> Object parent, Object node) { }<br />public void setParent( FactoryBuilderSupport builder,<br /> Object parent, Object child) { }<br />public void setChild( FactoryBuilderSupport builder, <br /> Object parent, Object child) { }<br />}<br />
  49. 49. RootFactory<br />classRobotFactoryextendsAbstractFactory {<br />defnewInstance( FactoryBuilderSupport builder, name, value,<br /> Map attrs) {<br />new Robot(name: value)<br /> }<br />voidsetChild( FactoryBuilderSupport builder, Object parent,<br /> Object child) {<br />parent.movements << child<br /> }<br />}<br />
  50. 50. LeftTurnFactory<br />classLeftTurnFactoryextendsAbstractFactory {<br />booleanisLeaf() { true }<br />defnewInstance( FactoryBuilderSupport builder, name, <br /> value, Map attrs) {<br />newLeftTurn()<br /> }<br />}<br />
  51. 51. ForwardMoveFactory<br />classForwardMoveFactoryextendsAbstractFactory {<br />booleanisLeaf() { true }<br />defnewInstance( FactoryBuilderSupport builder, name, value, <br /> Map attrs) {<br />newForwardMove()<br /> }<br />...<br />
  52. 52. ForwardMoveFactory<br /> ...<br />booleanonHandleNodeAttributes( FactoryBuilderSupport builder, <br /> Object node, Map attrs) <br /> {<br />if( attrs.speed && attrs.duration) {<br />node.dist = attrs.speed + attrs.duration<br />attrs.remove( 'speed')<br />attrs.remove('duration')<br /> }<br /> true<br /> }<br />}<br />
  53. 53. RobotBuilder<br />Wall E 로봇 동작합니다...<br />이동! 거리 ... 20<br />좌회전! 거리 ... 90도<br />이동! 거리 ... 15<br />
  54. 54. DSL 애플리케이션 통합<br />
  55. 55. 통합 매커니즘<br />Java 6 : JSR-223 / javax.script.*<br />Groovy 자체 메커니즘<br />GroovyShell<br />GroovyClassLoader<br />Spring 2.0 dynamic language beans<br />Lang namespace<br />POGO customizer<br />
  56. 56. Java 6 스크립팅API<br />scripting.dev.java.net에서 Groovy 엔진 JAR 제공<br />CLASSPATH에 포함시킬 것!<br />ScriptEngineManager manager = newScriptEngineManager();ScriptEnginegEngine = manager.getEngineByName(“groovy”);String result = (String)gEngine.eval(“’Foo’*2”);<br />
  57. 57. GroovyShell<br />expression과 스크립트를 evaluate<br />바인딩을 통하여 값 입/출력<br />evaluate한 스크립트는 global 함수나 변수를 포함한 베이스 클래스를 가짐<br />
  58. 58. GroovyShell예<br />def binding = new Binding()binding.mass = 22.3binding.velocity = 10.6def shell = newGroovyShell(binding)defexpr = “mass * velocity ** 2 / 2”assertshell.evaluate(expr) == 1252.814<br />
  59. 59. GroovyClassLoader예<br />GroovyClassLoadergcl = newGroovyClassLoader();Class greetingClass = gcl.parseClass( new File( “DSL.groovy”));GroovyObjectdsl = (GroovyObject)greetingClass.newInstance();dsl.setMetaClass(myCustomDSLMetaClass);<br />
  60. 60. DSL 설계시고려사항<br />
  61. 61. DSL 적용<br />강제로 적용하지 말 것!<br />대신...<br />사용자들이 자신들만의 DSL을 만들도록 할 것<br />정기적으로 최종 사용자를 포함시킬 것<br />어떻게 DSL을 사용하고 있는지 검토할 것<br />사용자들에게 어떤 것이 되고 안 되는지 알려줄 것<br />
  62. 62. 씻고, 닦고, 반복<br />반복 프로세스<br />간단하게 시작<br />처음에 원하는 것을 얻을 수 없음을 상기<br />관련 전문가와 브레인스토밍하며 지속적으로 개선 시켜야 함!<br />
  63. 63. 방어 프로그래밍<br />DSL은 샌드박스에서 실행해야 한다.<br />사용자들이 애플리케이션을 다운시켜서는 안됨<br />테스트, 테스트, 테스트!<br />우아하게 실패할 것<br />유효하지 않은 경우 : 에러 테스트!<br />의미 있는 에러 메시지를 출력할 것<br />
  64. 64. 요약<br />DLS은 해당 분야 전문가domain xpert와 개발자 사이에 공통의 상징metaphor으로서 공유할 수 있는 훌륭한 툴<br />DSL은 기존의 틀에 박힌 코드 없이 범주domain 개념을 표현<br />Groovy 문법과 동적 특성으로 DSL를 쉽게 만들고 Java 애플리케이션 통합<br />고품질 적용을 고려하여 반복적iterative이고 방어적인 프로그래밍.<br />
  65. 65. 참고자료<br />JavaZone 2008 Groovy DSL<br />GuillaumLaforge, G2One<br /><ul><li>Design you own Domain-Specific Language</li></ul>GuillaumLaforge, SpringSource, SpringOne2GX<br />Groovy in Action<br />DierkKönig, GuillaumLaforge, Manning Publications<br />Programming Groovy<br />VankatSubramaniam, PragramaticBookshelf<br />Groovy 오픈캐스트<br />http://opencast.naver.com/gr386<br />

×