SlideShare a Scribd company logo
Writing your own DSL
Yes, it is that easy!
Who am I?
● Rob Kinyon
○ @rkinyon
○ rob.kinyon@gmail.com
● Devops lead for many years
● Developer in Ruby, Python, Perl, JS, and
others.
What is a DSL?
● Domain-Specific Language
What is a DSL?
● Domain-Specific Language
● Language - A vehicle for communication
What is a DSL?
● Domain-Specific Language
● Language - A vehicle for communication
● Domain - A restrained set of concepts
What is a DSL?
● Domain-Specific Language
● Language - A vehicle for communication
● Domain - A restrained set of concepts
● Specific - Limited to.
What is a DSL?
● Domain-Specific Language
● Language - A vehicle for communication
● Domain - A restrained set of concepts
● Specific - Limited to.
○ No, really. :)
Language and Communication
● Communicate in one direction
○ Author -> Executor
Language and Communication
● Communicate in two directions
○ Author -> Executor
○ Author -> Maintainer
Language and Communication
● Communicate in three directions
○ Author -> Executor
○ Author -> Maintainer
○ Specifier -> Author
Language and Communication
● Communicate in four directions
○ Author -> Executor
○ Author -> Maintainer
○ Specifier -> Author
○ Author -> Verifier
Language and Communication
● Communicate in MANY directions
○ Author -> Executor
○ Author -> Maintainer
○ Specifier -> Author
○ Author -> Verifier
○ Author -> Teammate(s)
○ Developer -> Sysadmin/Devops
○ … -> …
Language and Communication
● Communicate in MANY directions
○ Author -> Executor
○ Author -> Maintainer
○ Specifier -> Author
○ Author -> Verifier
○ Author -> Teammate(s)
○ Developer -> Sysadmin/Devops
○ … -> …
The ONLY
computer
Language and Communication
● Communicate in MANY directions
○ Author -> Executor
○ Author -> Maintainer
○ Specifier -> Author
○ Author -> Verifier
○ Author -> Teammate(s)
○ Developer -> Sysadmin/Devops
○ … -> …
All humans
Language and Communication
● Communicate in MANY directions
○ Author -> Executor
○ Author <-> Maintainer
○ Specifier <-> Author
○ Author <-> Verifier
○ Author <-> Teammate(s)
○ Developer <-> Sysadmin/Devops
○ … <-> …
All human
communication
is two-way
Domain-Specific
● Eskimos supposedly have 50+ words for
“snow”
○ Depends on how you count it
● Saami has 1000+ words dealing with
reindeer
○ snarri - a reindeer with short, branched horns
○ busat - a bull with a single, large testicle
Domain-specific : Busat
Busat - The quality of having
appropriately-specific expressiveness
for the domain.
DSLs you already use
● SQL
○ set manipulation DSL
● CSS
○ tree-visitor-defining DSL for setting metadata
● HAML
○ HTML-definition DSL
● Bash
○ A crappy way of issue shell commands with logic
Places for a DSL
● Packaging and orchestration
○ most devops/operations activities
● Configuration file generation
○ web servers
○ monitoring
○ datastores
● Configuration value management across environments
● Anything extremely complicated (such as SQL)
● Anything repetitive (such as CSS)
Reasons for a DSL
● Let the important things shine
● General-purpose is overly-verbose
● Bugs hide in boilerplate
● Non-developers can read and comprehend
○ And maybe even propose changes through PRs?
Reasons for a DSL
DSL is to Ruby
as
Ruby is to Java
Writing a DSL
● Three passes
○ Parsing
○ Validation
○ Production
Writing a DSL - Parsing
● DSL::Maker for parsing
Car = Struct.new(:make, :year, :engine)
Engine = Struct.new(:hemi)
class VehicleDSL < DSL::Maker
add_entrypoint(:car, {
:make => String,
:year => Integer,
:engine => generate_dsl({
:hemi => Boolean,
}) do
Engine.new(hemi)
end,
}) do |*args|
default(:make, args, 0)
Car.new(make, model, engine)
end
end
car {
make ‘Accord’
year 1990
engine {
hemi Yes
}
}
car ‘Civic’ {
year 2014
}
Car = Struct.new(:make, :year, :engine)
Engine = Struct.new(:hemi)
class VehicleDSL < DSL::Maker
add_entrypoint(:car, {
:make => String,
:year => Integer,
:engine => generate_dsl({
:hemi => Boolean,
}) do
Engine.new(hemi)
end,
}) do |*args|
default(:make, args, 0)
Car.new(make, model, engine)
end
end
car {
make ‘Accord’
year 1990
engine {
hemi Yes
}
}
car ‘Civic’ {
year 2014
}
Car = Struct.new(:make, :year, :engine)
Engine = Struct.new(:hemi)
class VehicleDSL < DSL::Maker
add_entrypoint(:car, {
:make => String,
:year => Integer,
:engine => generate_dsl({
:hemi => Boolean,
}) do
Engine.new(hemi)
end,
}) do |*args|
default(:make, args, 0)
Car.new(make, model, engine)
end
end
car {
make ‘Accord’
year 1990
engine {
hemi Yes
}
}
car ‘Civic’ {
year 2014
}
Car = Struct.new(:make, :year, :engine)
Engine = Struct.new(:hemi)
class VehicleDSL < DSL::Maker
add_entrypoint(:car, {
:make => String,
:year => Integer,
:engine => generate_dsl({
:hemi => Boolean,
}) do
Engine.new(hemi)
end,
}) do |*args|
default(:make, args, 0)
Car.new(make, model, engine)
end
end
car {
make ‘Accord’
year 1990
engine {
hemi Yes
}
}
car ‘Civic’ {
year 2014
}
Car = Struct.new(:make, :year, :engine)
Engine = Struct.new(:hemi)
class VehicleDSL < DSL::Maker
add_entrypoint(:car, {
:make => String,
:year => Integer,
:engine => generate_dsl({
:hemi => Boolean,
}) do
Engine.new(hemi)
end,
}) do |*args|
default(:make, args, 0)
Car.new(make, model, engine)
end
end
car {
make ‘Accord’
year 1990
engine {
hemi Yes
}
}
car ‘Civic’ {
year 2014
}
Car = Struct.new(:make, :year, :engine)
Engine = Struct.new(:hemi)
class VehicleDSL < DSL::Maker
add_entrypoint(:car, {
:make => String,
:year => Integer,
:engine => generate_dsl({
:hemi => Boolean,
}) do
Engine.new(hemi)
end,
}) do |*args|
default(:make, args, 0)
Car.new(make, model, engine)
end
end
car {
make ‘Accord’
year 1990
engine {
hemi Yes
}
}
car ‘Civic’ {
year 2014
}
#!/usr/bin/env ruby
require ‘vehicle/dsl’
filename = ARGV.shift ||
raise “No filename provided.”
vehicles = Vehicle::DSL.parse_dsl(
IO.read(filename),
)
# Do something here with vehicles
[
Car[
:make => ‘Accord’,
:year => 1990,
:engine => Engine[
:hemi => true,
],
],
Car[
:make => Civic,
:year => 2014,
:engine => nil,
],
]
. . .
truck ‘F-150’ {
year 1999
}
. . .
. . .
Truck = Struct.new(:make, :year, :engine)
. . .
class VehicleDSL < DSL::Maker
. . .
add_entrypoint(:truck, {
:make => String,
:year => Integer,
:engine => . . .,
}) do |*args|
default(:make, args, 0)
Truck.new(make, model, nil)
end
end
#!/usr/bin/env ruby
require ‘vehicle/dsl’
filename = ARGV.shift ||
raise “No filename provided.”
vehicles = Vehicle::DSL.parse_dsl(
IO.read(filename),
)
# Do something here with vehicles
[
. . .
Truck[
:make => ‘F-150’,
:year => 1999,
:engine => nil
],
. . .
]
Writing a DSL - Validation
● DSL::Maker for parsing
● DSL::Maker for validation
. . .
class VehicleDSL < DSL::Maker
. . .
add_validation(:car) do |car|
unless car.engine
return “Cars must have an engine”
end
end
end
car {
make ‘Accord’
year 1990
engine {
hemi Yes
}
}
car ‘Civic’ {
year 2014
}
. . .
class VehicleDSL < DSL::Maker
. . .
add_validation(:car) do |car|
unless car.engine
return “Cars must have an engine”
end
end
end
car {
make ‘Accord’
year 1990
engine {
hemi Yes
}
}
car ‘Civic’ {
year 2014
}
#!/usr/bin/env ruby
require ‘vehicle/dsl’
filename = ARGV.shift ||
raise “No filename provided.”
# This raises the error
vehicles = Vehicle::DSL.parse_dsl(
IO.read(filename),
)
# Do something here with vehicles
Error: Cars must have an engine
Writing a DSL - Production
● DSL::Maker for parsing
● DSL::Maker for validation
● You’re on your own for production
Writing a DSL - Production
● Work from outside in.
○ Parsing is done inside-out.
● Transform in a series of passes.
○ Expand everything (it’s just data)
● Don’t do anything irrevocable until the end
○ Work in temp directories, stage everything
Conclusion
● DSL::Maker 0.1.0 is available right now
● Patches welcome
○ 100% test coverage
● I’m blogging about this at http:
//streamlined-book.blogspot.com
○ First post on the topic
Questions?

More Related Content

Similar to Writing your own DSL

HTML 5 and CSS 3
HTML 5 and CSS 3HTML 5 and CSS 3
HTML 5 and CSS 3
Kannika Kong
 
OpenSCAD Tutorial
OpenSCAD TutorialOpenSCAD Tutorial
OpenSCAD Tutorial
John Oliva
 
You Can Work on the Web Patform! (GOSIM 2023)
You Can Work on the Web Patform! (GOSIM 2023)You Can Work on the Web Patform! (GOSIM 2023)
You Can Work on the Web Patform! (GOSIM 2023)
Igalia
 
MongoDB and DigitalOcean Automation with Cloud Manager
MongoDB and DigitalOcean Automation with Cloud ManagerMongoDB and DigitalOcean Automation with Cloud Manager
MongoDB and DigitalOcean Automation with Cloud Manager
Jay Gordon
 
Forge - DevCon 2017, Darmstadt Germany: HFDM - What, why & how?
Forge - DevCon 2017, Darmstadt Germany: HFDM - What, why & how?Forge - DevCon 2017, Darmstadt Germany: HFDM - What, why & how?
Forge - DevCon 2017, Darmstadt Germany: HFDM - What, why & how?
Autodesk
 
Dart the better Javascript 2015
Dart the better Javascript 2015Dart the better Javascript 2015
Dart the better Javascript 2015
Jorg Janke
 
MongoDB Schema Design
MongoDB Schema DesignMongoDB Schema Design
MongoDB Schema Design
Joe Drumgoole
 
DSLs for fun and profit by Jukka Välimaa
DSLs for fun and profit by Jukka VälimaaDSLs for fun and profit by Jukka Välimaa
DSLs for fun and profit by Jukka Välimaa
Montel Intergalactic
 
Dart the Better JavaScript
Dart the Better JavaScriptDart the Better JavaScript
Dart the Better JavaScript
Jorg Janke
 
TDC 2020 - Implementing a Mini-Language
TDC 2020 - Implementing a Mini-LanguageTDC 2020 - Implementing a Mini-Language
TDC 2020 - Implementing a Mini-Language
Luciano Sabença
 
Fuzzing softwares for bugs - OWASP Seasides
Fuzzing softwares for bugs - OWASP SeasidesFuzzing softwares for bugs - OWASP Seasides
Fuzzing softwares for bugs - OWASP Seasides
OWASPSeasides
 
Creating Domain Specific Languages in F#
Creating Domain Specific Languages in F#Creating Domain Specific Languages in F#
Creating Domain Specific Languages in F#
Tomas Petricek
 
REST services and IBM Domino/XWork - DanNotes 19-20. november 2014
REST services and IBM Domino/XWork - DanNotes 19-20. november 2014REST services and IBM Domino/XWork - DanNotes 19-20. november 2014
REST services and IBM Domino/XWork - DanNotes 19-20. november 2014
John Dalsgaard
 
Talend connect BE Vincent Harcq - Talend ESB - DI
Talend connect BE Vincent Harcq - Talend  ESB - DITalend connect BE Vincent Harcq - Talend  ESB - DI
Talend connect BE Vincent Harcq - Talend ESB - DI
Vincent Harcq
 
Building an E-commerce website in MEAN stack
Building an E-commerce website in MEAN stackBuilding an E-commerce website in MEAN stack
Building an E-commerce website in MEAN stack
divyapisces
 
Scala services in action
Scala services in actionScala services in action
Scala services in action
Underscore
 
Embedded C
Embedded CEmbedded C
AD109 Navigating the Jungle of Modern Web Development
AD109 Navigating the Jungle of Modern Web DevelopmentAD109 Navigating the Jungle of Modern Web Development
AD109 Navigating the Jungle of Modern Web Development
Shean McManus
 
Rubyconf Bangladesh 2017 - Lets start coding in Ruby
Rubyconf Bangladesh 2017 - Lets start coding in RubyRubyconf Bangladesh 2017 - Lets start coding in Ruby
Rubyconf Bangladesh 2017 - Lets start coding in Ruby
Ruby Bangladesh
 
Montreal.rb 2022-10-05 - Glimmer DSL for SWT - Ruby Desktop Development GUI ...
 Montreal.rb 2022-10-05 - Glimmer DSL for SWT - Ruby Desktop Development GUI ... Montreal.rb 2022-10-05 - Glimmer DSL for SWT - Ruby Desktop Development GUI ...
Montreal.rb 2022-10-05 - Glimmer DSL for SWT - Ruby Desktop Development GUI ...
Andy Maleh
 

Similar to Writing your own DSL (20)

HTML 5 and CSS 3
HTML 5 and CSS 3HTML 5 and CSS 3
HTML 5 and CSS 3
 
OpenSCAD Tutorial
OpenSCAD TutorialOpenSCAD Tutorial
OpenSCAD Tutorial
 
You Can Work on the Web Patform! (GOSIM 2023)
You Can Work on the Web Patform! (GOSIM 2023)You Can Work on the Web Patform! (GOSIM 2023)
You Can Work on the Web Patform! (GOSIM 2023)
 
MongoDB and DigitalOcean Automation with Cloud Manager
MongoDB and DigitalOcean Automation with Cloud ManagerMongoDB and DigitalOcean Automation with Cloud Manager
MongoDB and DigitalOcean Automation with Cloud Manager
 
Forge - DevCon 2017, Darmstadt Germany: HFDM - What, why & how?
Forge - DevCon 2017, Darmstadt Germany: HFDM - What, why & how?Forge - DevCon 2017, Darmstadt Germany: HFDM - What, why & how?
Forge - DevCon 2017, Darmstadt Germany: HFDM - What, why & how?
 
Dart the better Javascript 2015
Dart the better Javascript 2015Dart the better Javascript 2015
Dart the better Javascript 2015
 
MongoDB Schema Design
MongoDB Schema DesignMongoDB Schema Design
MongoDB Schema Design
 
DSLs for fun and profit by Jukka Välimaa
DSLs for fun and profit by Jukka VälimaaDSLs for fun and profit by Jukka Välimaa
DSLs for fun and profit by Jukka Välimaa
 
Dart the Better JavaScript
Dart the Better JavaScriptDart the Better JavaScript
Dart the Better JavaScript
 
TDC 2020 - Implementing a Mini-Language
TDC 2020 - Implementing a Mini-LanguageTDC 2020 - Implementing a Mini-Language
TDC 2020 - Implementing a Mini-Language
 
Fuzzing softwares for bugs - OWASP Seasides
Fuzzing softwares for bugs - OWASP SeasidesFuzzing softwares for bugs - OWASP Seasides
Fuzzing softwares for bugs - OWASP Seasides
 
Creating Domain Specific Languages in F#
Creating Domain Specific Languages in F#Creating Domain Specific Languages in F#
Creating Domain Specific Languages in F#
 
REST services and IBM Domino/XWork - DanNotes 19-20. november 2014
REST services and IBM Domino/XWork - DanNotes 19-20. november 2014REST services and IBM Domino/XWork - DanNotes 19-20. november 2014
REST services and IBM Domino/XWork - DanNotes 19-20. november 2014
 
Talend connect BE Vincent Harcq - Talend ESB - DI
Talend connect BE Vincent Harcq - Talend  ESB - DITalend connect BE Vincent Harcq - Talend  ESB - DI
Talend connect BE Vincent Harcq - Talend ESB - DI
 
Building an E-commerce website in MEAN stack
Building an E-commerce website in MEAN stackBuilding an E-commerce website in MEAN stack
Building an E-commerce website in MEAN stack
 
Scala services in action
Scala services in actionScala services in action
Scala services in action
 
Embedded C
Embedded CEmbedded C
Embedded C
 
AD109 Navigating the Jungle of Modern Web Development
AD109 Navigating the Jungle of Modern Web DevelopmentAD109 Navigating the Jungle of Modern Web Development
AD109 Navigating the Jungle of Modern Web Development
 
Rubyconf Bangladesh 2017 - Lets start coding in Ruby
Rubyconf Bangladesh 2017 - Lets start coding in RubyRubyconf Bangladesh 2017 - Lets start coding in Ruby
Rubyconf Bangladesh 2017 - Lets start coding in Ruby
 
Montreal.rb 2022-10-05 - Glimmer DSL for SWT - Ruby Desktop Development GUI ...
 Montreal.rb 2022-10-05 - Glimmer DSL for SWT - Ruby Desktop Development GUI ... Montreal.rb 2022-10-05 - Glimmer DSL for SWT - Ruby Desktop Development GUI ...
Montreal.rb 2022-10-05 - Glimmer DSL for SWT - Ruby Desktop Development GUI ...
 

Recently uploaded

Discover the benefits of outsourcing SEO to India
Discover the benefits of outsourcing SEO to IndiaDiscover the benefits of outsourcing SEO to India
Discover the benefits of outsourcing SEO to India
davidjhones387
 
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
3a0sd7z3
 
Bengaluru Dreamin' 24 - Personal Branding
Bengaluru Dreamin' 24 - Personal BrandingBengaluru Dreamin' 24 - Personal Branding
Bengaluru Dreamin' 24 - Personal Branding
Tarandeep Singh
 
Should Repositories Participate in the Fediverse?
Should Repositories Participate in the Fediverse?Should Repositories Participate in the Fediverse?
Should Repositories Participate in the Fediverse?
Paul Walk
 
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
3a0sd7z3
 
一比一原版(USYD毕业证)悉尼大学毕业证如何办理
一比一原版(USYD毕业证)悉尼大学毕业证如何办理一比一原版(USYD毕业证)悉尼大学毕业证如何办理
一比一原版(USYD毕业证)悉尼大学毕业证如何办理
k4ncd0z
 
怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
rtunex8r
 
Honeypots Unveiled: Proactive Defense Tactics for Cyber Security, Phoenix Sum...
Honeypots Unveiled: Proactive Defense Tactics for Cyber Security, Phoenix Sum...Honeypots Unveiled: Proactive Defense Tactics for Cyber Security, Phoenix Sum...
Honeypots Unveiled: Proactive Defense Tactics for Cyber Security, Phoenix Sum...
APNIC
 
Securing BGP: Operational Strategies and Best Practices for Network Defenders...
Securing BGP: Operational Strategies and Best Practices for Network Defenders...Securing BGP: Operational Strategies and Best Practices for Network Defenders...
Securing BGP: Operational Strategies and Best Practices for Network Defenders...
APNIC
 
一比一原版新西兰林肯大学毕业证(Lincoln毕业证书)学历如何办理
一比一原版新西兰林肯大学毕业证(Lincoln毕业证书)学历如何办理一比一原版新西兰林肯大学毕业证(Lincoln毕业证书)学历如何办理
一比一原版新西兰林肯大学毕业证(Lincoln毕业证书)学历如何办理
thezot
 
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
xjq03c34
 
HijackLoader Evolution: Interactive Process Hollowing
HijackLoader Evolution: Interactive Process HollowingHijackLoader Evolution: Interactive Process Hollowing
HijackLoader Evolution: Interactive Process Hollowing
Donato Onofri
 

Recently uploaded (12)

Discover the benefits of outsourcing SEO to India
Discover the benefits of outsourcing SEO to IndiaDiscover the benefits of outsourcing SEO to India
Discover the benefits of outsourcing SEO to India
 
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
快速办理(新加坡SMU毕业证书)新加坡管理大学毕业证文凭证书一模一样
 
Bengaluru Dreamin' 24 - Personal Branding
Bengaluru Dreamin' 24 - Personal BrandingBengaluru Dreamin' 24 - Personal Branding
Bengaluru Dreamin' 24 - Personal Branding
 
Should Repositories Participate in the Fediverse?
Should Repositories Participate in the Fediverse?Should Repositories Participate in the Fediverse?
Should Repositories Participate in the Fediverse?
 
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
快速办理(Vic毕业证书)惠灵顿维多利亚大学毕业证完成信一模一样
 
一比一原版(USYD毕业证)悉尼大学毕业证如何办理
一比一原版(USYD毕业证)悉尼大学毕业证如何办理一比一原版(USYD毕业证)悉尼大学毕业证如何办理
一比一原版(USYD毕业证)悉尼大学毕业证如何办理
 
怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
怎么办理(umiami毕业证书)美国迈阿密大学毕业证文凭证书实拍图原版一模一样
 
Honeypots Unveiled: Proactive Defense Tactics for Cyber Security, Phoenix Sum...
Honeypots Unveiled: Proactive Defense Tactics for Cyber Security, Phoenix Sum...Honeypots Unveiled: Proactive Defense Tactics for Cyber Security, Phoenix Sum...
Honeypots Unveiled: Proactive Defense Tactics for Cyber Security, Phoenix Sum...
 
Securing BGP: Operational Strategies and Best Practices for Network Defenders...
Securing BGP: Operational Strategies and Best Practices for Network Defenders...Securing BGP: Operational Strategies and Best Practices for Network Defenders...
Securing BGP: Operational Strategies and Best Practices for Network Defenders...
 
一比一原版新西兰林肯大学毕业证(Lincoln毕业证书)学历如何办理
一比一原版新西兰林肯大学毕业证(Lincoln毕业证书)学历如何办理一比一原版新西兰林肯大学毕业证(Lincoln毕业证书)学历如何办理
一比一原版新西兰林肯大学毕业证(Lincoln毕业证书)学历如何办理
 
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
办理新西兰奥克兰大学毕业证学位证书范本原版一模一样
 
HijackLoader Evolution: Interactive Process Hollowing
HijackLoader Evolution: Interactive Process HollowingHijackLoader Evolution: Interactive Process Hollowing
HijackLoader Evolution: Interactive Process Hollowing
 

Writing your own DSL

  • 1. Writing your own DSL Yes, it is that easy!
  • 2.
  • 3. Who am I? ● Rob Kinyon ○ @rkinyon ○ rob.kinyon@gmail.com ● Devops lead for many years ● Developer in Ruby, Python, Perl, JS, and others.
  • 4. What is a DSL? ● Domain-Specific Language
  • 5. What is a DSL? ● Domain-Specific Language ● Language - A vehicle for communication
  • 6. What is a DSL? ● Domain-Specific Language ● Language - A vehicle for communication ● Domain - A restrained set of concepts
  • 7. What is a DSL? ● Domain-Specific Language ● Language - A vehicle for communication ● Domain - A restrained set of concepts ● Specific - Limited to.
  • 8. What is a DSL? ● Domain-Specific Language ● Language - A vehicle for communication ● Domain - A restrained set of concepts ● Specific - Limited to. ○ No, really. :)
  • 9. Language and Communication ● Communicate in one direction ○ Author -> Executor
  • 10. Language and Communication ● Communicate in two directions ○ Author -> Executor ○ Author -> Maintainer
  • 11. Language and Communication ● Communicate in three directions ○ Author -> Executor ○ Author -> Maintainer ○ Specifier -> Author
  • 12. Language and Communication ● Communicate in four directions ○ Author -> Executor ○ Author -> Maintainer ○ Specifier -> Author ○ Author -> Verifier
  • 13. Language and Communication ● Communicate in MANY directions ○ Author -> Executor ○ Author -> Maintainer ○ Specifier -> Author ○ Author -> Verifier ○ Author -> Teammate(s) ○ Developer -> Sysadmin/Devops ○ … -> …
  • 14. Language and Communication ● Communicate in MANY directions ○ Author -> Executor ○ Author -> Maintainer ○ Specifier -> Author ○ Author -> Verifier ○ Author -> Teammate(s) ○ Developer -> Sysadmin/Devops ○ … -> … The ONLY computer
  • 15. Language and Communication ● Communicate in MANY directions ○ Author -> Executor ○ Author -> Maintainer ○ Specifier -> Author ○ Author -> Verifier ○ Author -> Teammate(s) ○ Developer -> Sysadmin/Devops ○ … -> … All humans
  • 16. Language and Communication ● Communicate in MANY directions ○ Author -> Executor ○ Author <-> Maintainer ○ Specifier <-> Author ○ Author <-> Verifier ○ Author <-> Teammate(s) ○ Developer <-> Sysadmin/Devops ○ … <-> … All human communication is two-way
  • 17. Domain-Specific ● Eskimos supposedly have 50+ words for “snow” ○ Depends on how you count it ● Saami has 1000+ words dealing with reindeer ○ snarri - a reindeer with short, branched horns ○ busat - a bull with a single, large testicle
  • 18. Domain-specific : Busat Busat - The quality of having appropriately-specific expressiveness for the domain.
  • 19. DSLs you already use ● SQL ○ set manipulation DSL ● CSS ○ tree-visitor-defining DSL for setting metadata ● HAML ○ HTML-definition DSL ● Bash ○ A crappy way of issue shell commands with logic
  • 20. Places for a DSL ● Packaging and orchestration ○ most devops/operations activities ● Configuration file generation ○ web servers ○ monitoring ○ datastores ● Configuration value management across environments ● Anything extremely complicated (such as SQL) ● Anything repetitive (such as CSS)
  • 21. Reasons for a DSL ● Let the important things shine ● General-purpose is overly-verbose ● Bugs hide in boilerplate ● Non-developers can read and comprehend ○ And maybe even propose changes through PRs?
  • 22. Reasons for a DSL DSL is to Ruby as Ruby is to Java
  • 23. Writing a DSL ● Three passes ○ Parsing ○ Validation ○ Production
  • 24. Writing a DSL - Parsing ● DSL::Maker for parsing
  • 25. Car = Struct.new(:make, :year, :engine) Engine = Struct.new(:hemi) class VehicleDSL < DSL::Maker add_entrypoint(:car, { :make => String, :year => Integer, :engine => generate_dsl({ :hemi => Boolean, }) do Engine.new(hemi) end, }) do |*args| default(:make, args, 0) Car.new(make, model, engine) end end car { make ‘Accord’ year 1990 engine { hemi Yes } } car ‘Civic’ { year 2014 }
  • 26. Car = Struct.new(:make, :year, :engine) Engine = Struct.new(:hemi) class VehicleDSL < DSL::Maker add_entrypoint(:car, { :make => String, :year => Integer, :engine => generate_dsl({ :hemi => Boolean, }) do Engine.new(hemi) end, }) do |*args| default(:make, args, 0) Car.new(make, model, engine) end end car { make ‘Accord’ year 1990 engine { hemi Yes } } car ‘Civic’ { year 2014 }
  • 27. Car = Struct.new(:make, :year, :engine) Engine = Struct.new(:hemi) class VehicleDSL < DSL::Maker add_entrypoint(:car, { :make => String, :year => Integer, :engine => generate_dsl({ :hemi => Boolean, }) do Engine.new(hemi) end, }) do |*args| default(:make, args, 0) Car.new(make, model, engine) end end car { make ‘Accord’ year 1990 engine { hemi Yes } } car ‘Civic’ { year 2014 }
  • 28. Car = Struct.new(:make, :year, :engine) Engine = Struct.new(:hemi) class VehicleDSL < DSL::Maker add_entrypoint(:car, { :make => String, :year => Integer, :engine => generate_dsl({ :hemi => Boolean, }) do Engine.new(hemi) end, }) do |*args| default(:make, args, 0) Car.new(make, model, engine) end end car { make ‘Accord’ year 1990 engine { hemi Yes } } car ‘Civic’ { year 2014 }
  • 29. Car = Struct.new(:make, :year, :engine) Engine = Struct.new(:hemi) class VehicleDSL < DSL::Maker add_entrypoint(:car, { :make => String, :year => Integer, :engine => generate_dsl({ :hemi => Boolean, }) do Engine.new(hemi) end, }) do |*args| default(:make, args, 0) Car.new(make, model, engine) end end car { make ‘Accord’ year 1990 engine { hemi Yes } } car ‘Civic’ { year 2014 }
  • 30. Car = Struct.new(:make, :year, :engine) Engine = Struct.new(:hemi) class VehicleDSL < DSL::Maker add_entrypoint(:car, { :make => String, :year => Integer, :engine => generate_dsl({ :hemi => Boolean, }) do Engine.new(hemi) end, }) do |*args| default(:make, args, 0) Car.new(make, model, engine) end end car { make ‘Accord’ year 1990 engine { hemi Yes } } car ‘Civic’ { year 2014 }
  • 31. #!/usr/bin/env ruby require ‘vehicle/dsl’ filename = ARGV.shift || raise “No filename provided.” vehicles = Vehicle::DSL.parse_dsl( IO.read(filename), ) # Do something here with vehicles [ Car[ :make => ‘Accord’, :year => 1990, :engine => Engine[ :hemi => true, ], ], Car[ :make => Civic, :year => 2014, :engine => nil, ], ]
  • 32. . . . truck ‘F-150’ { year 1999 } . . . . . . Truck = Struct.new(:make, :year, :engine) . . . class VehicleDSL < DSL::Maker . . . add_entrypoint(:truck, { :make => String, :year => Integer, :engine => . . ., }) do |*args| default(:make, args, 0) Truck.new(make, model, nil) end end
  • 33. #!/usr/bin/env ruby require ‘vehicle/dsl’ filename = ARGV.shift || raise “No filename provided.” vehicles = Vehicle::DSL.parse_dsl( IO.read(filename), ) # Do something here with vehicles [ . . . Truck[ :make => ‘F-150’, :year => 1999, :engine => nil ], . . . ]
  • 34. Writing a DSL - Validation ● DSL::Maker for parsing ● DSL::Maker for validation
  • 35. . . . class VehicleDSL < DSL::Maker . . . add_validation(:car) do |car| unless car.engine return “Cars must have an engine” end end end car { make ‘Accord’ year 1990 engine { hemi Yes } } car ‘Civic’ { year 2014 }
  • 36. . . . class VehicleDSL < DSL::Maker . . . add_validation(:car) do |car| unless car.engine return “Cars must have an engine” end end end car { make ‘Accord’ year 1990 engine { hemi Yes } } car ‘Civic’ { year 2014 }
  • 37. #!/usr/bin/env ruby require ‘vehicle/dsl’ filename = ARGV.shift || raise “No filename provided.” # This raises the error vehicles = Vehicle::DSL.parse_dsl( IO.read(filename), ) # Do something here with vehicles Error: Cars must have an engine
  • 38. Writing a DSL - Production ● DSL::Maker for parsing ● DSL::Maker for validation ● You’re on your own for production
  • 39. Writing a DSL - Production ● Work from outside in. ○ Parsing is done inside-out. ● Transform in a series of passes. ○ Expand everything (it’s just data) ● Don’t do anything irrevocable until the end ○ Work in temp directories, stage everything
  • 40. Conclusion ● DSL::Maker 0.1.0 is available right now ● Patches welcome ○ 100% test coverage ● I’m blogging about this at http: //streamlined-book.blogspot.com ○ First post on the topic