Os Secoske

704 views

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
704
On SlideShare
0
From Embeds
0
Number of Embeds
31
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Os Secoske

  1. 1. Implementing DSLs in Groovy Matt Secoske http://blog.secosoft.net http://objectpartners.com
  2. 2. DSL? Groovy?
  3. 3. D omain S pecific L anguage: A language that clearly expresses the ideas of a particular domain
  4. 4. aka: fluent / humane interfaces problem oriented languages little / mini languages macros (as in Excel)
  5. 5. Domain Specific Language
  6. 6. this:
  7. 7. not this:
  8. 8. this:
  9. 9. not this:
  10. 10. A DSL is just another tool in our toolbox. It’s a jig to help us build our applications. picture copyrighted @2007 Pat Warner, http://www.patwarner.com
  11. 11. why?
  12. 12. bring the syntax closer to the domain (the experts language)
  13. 13. mrMustard .didIt( Murder .of( mrGreen )) .in( theKitchen ) .with( theCandleStick )
  14. 14. /^([a-zA-Z0-9_.-])+@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+$/
  15. 15. class CreateQuizComments < ActiveRecord::Migration def self.up create_table :quiz_comments do |t| t.column :name, :string t.column :email, :string t.column :url, :string t.column :comment, :text end end def self.down drop_table :quiz_comments end end
  16. 16. Goal: make the problem easier to understand
  17. 17. (My) Ultimate Goal: Be able to give the code to the experts, and have them use it
  18. 18. Types of DSLs: - Internal - External - Functional - Object Oriented
  19. 19. Internal DSLs - extending a language - can be whatever you want - within the laws of the base language
  20. 20. Groovy?
  21. 21. A Compelling Story: - Much of the flexibility of Ruby - Familiar Java idioms and syntax - Is focused on the JVM - and Java “pain points”
  22. 22. Groovy has good DSL support: - introspection / reflection (ability to parse(itself)) Meta-Object Protocol - syntactic sugar Builders Duck Typing Categories ExpandoMetaClass Named Parameters Operator Overloading
  23. 23. Introspection / Reflection - Access to the AST at Class loading time - Can run/load code at any time
  24. 24. class MyGroovy extends GroovyClassLoader { protected CompilationUnit createCompilationUnit(CompilerConfiguration config, CodeSource source) { CompilationUnit cu = super .createCompilationUnit(config, source); cu.addPhaseOperation( new PrimaryClassNodeOperation() { public void call (SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { String name = classNode.getName(); if (name.endsWith( &quot;Foo&quot; )) { BlockStatement code = new BlockStatement(); classNode.addMethod( ”bar&quot; ,Opcodes.ACC_PUBLIC, null , null , null ,code); } } },Phases.CONVERSION); return cu; } } Adapted from blackdrag’s blog: http://blackdragsview.blogspot.com/2006/11/chitchat-with-groovy-compiler.html
  25. 25. Meta Object Protocol - Determines what’s running at Runtime - add/modify/intercept methods, properties MetaClass Class getFoo() doesntExistOnClass() Other Code
  26. 26. more Groovy syntactic sugar
  27. 27. Duck typing : flexible code if it walks like a duck… and it quacks like a duck… its probably a …. a = ”a string&quot; println a. class // => class java.lang.String a = 1 println a. class // => class java.lang.Integer
  28. 28. builders : structured data swing = new SwingBuilder() frame = swing.frame( title: 'Life' ) { vbox { panel( id: 'canvas' ) { vstrut(height: 300 ) hstrut(width: 300 ) } hbox { glue() button( text: 'Next' , actionPerformed:{evolve()}) } }} frame.pack() frame.show()
  29. 29. Using “ use ” (Groovy Categories) class MeasureCategory { static Measurement getLbs( final Integer self) { new Measurement(self, Measurement.Pounds) } } aClosure = {-> println 4 .lbs.of( &quot;Sugar&quot; ) } use (MeasureCategory. class ) { println 1 .lbs.of( &quot;Carrots&quot; ) // -> 1 Pounds of Carrots aClosure. call () // -> 4 Pounds of Sugar }
  30. 30. Using ExpandoMetaClass: metaClass = new ExpandoMetaClass(Integer. class , true ) metaClass.getLbs << {-> &quot;${delegate} pounds&quot; } metaClass.initialize() i = 1 ; println i // => 1 println i. class // => java.lang.Integer println i.lbs // => 1 pounds
  31. 31. Using ExpandoMetaClass: metaClass = new ExpandoMetaClass(Integer. class , true ) metaClass.getLbs << {-> &quot;${delegate} pounds&quot; } metaClass.initialize() i = 1 ; println i // => 1 println i. class // => java.lang.Integer println i.lbs // => 1 pounds
  32. 32. To Expando or not to Expando … - global usage (good and bad) - must be aware of context - naming collisions use + aspects/annotations = somewhat finer grained control
  33. 33. Operator Overloading: class Foo { String meh; public Foo(String meh) { this .meh = meh} public String toString() { meh } public Foo plus (other) { new Foo( this .meh + other.toString()) } } a = new Foo( &quot;Hello &quot; ) b = new Foo( &quot;World&quot; ) c = &quot;New World&quot; println a + b // -> “Hello World” println a + c // -> “Hello New World”
  34. 34. Grails/Hibernate Criteria Builder: def c = Account.createCriteria() def results = c { like( &quot;holderFirstName&quot; , &quot;Fred%&quot; ) and { between( &quot;balance&quot; , 500 , 1000 ) eq( &quot;branch&quot; , &quot;London&quot; ) } maxResults( 10 ) order( &quot;holderLastName&quot; , &quot;desc&quot; ) }
  35. 35. A Recipe DSL: use(MeasurementCategory) { recipe = new Recipe() recipe.ingredients = [ 2 .cups.of( &quot;Milk&quot; ), 2 .tsps.of( &quot;Chocolate Milk Mix&quot; ) ] recipe.steps { with( &quot;drinking glass&quot; ) { add( &quot;Chocolate Milk Mix&quot; ) stirIn( &quot;Milk&quot; ) } } }
  36. 36. Domain Specific Language syntax approaches the problem understanding++
  37. 37. Three things that always matter: Naming Structure Context } Meaning
  38. 38. Thank You! slides at: http://blog.secosoft.net

×