A Polyglot worldon DSLs
Who Am I‣ koen.handekyn@up-nxt.com  CEO UP-nxt, R&D division of the UnifiedPost Group.  Electronic Document Handling (Archi...
Why Ruby?PRODUCTIVITY
Why Ruby? FUN
Why Ruby?
Why is Ruby productive‣ Simplicity - next time :) ?‣ Functional Programming - next time :) ?‣ DSL’s and Meta-Programming
Simplicity‣   DRY‣   KISS‣   YAGNI‣   Least Surprise‣   Convention over Configuration (meaningful defaults)
DSL (domain specific languages)‣ The DSL does not solve every problem in the  universe but rather focuses on one little  do...
Internal vs External‣   An external DSL has it’s own custom scanner and    parser or uses a standard one, like XML. exampl...
ActiveAdmin
ActiveAdmin.register Product do  # Create sections on the index screen  scope :all, :default => true  scope :available  sc...
ActiveRecord‣ Properties are dynamically   defined. For every column   found in the database, a     class Client < ActiveRe...
Example DSL: rake                                                   namespace :morning do                                 ...
Example DSL: rails routes‣ The Rails router              match "/patients/:id" => "patients#show"  recognizes URLs and    ...
Capistrino‣ Capistrano is a utility and framework for executing  commands in parallel on multiple remote machines, via SSH...
Slop‣ Slop is a simple option parser with an easy to remember  syntax and friendly API.‣ https://github.com/injekt/slop   ...
Workflow                                     class Article‣ Workflow is a finite-state-            include Workflow          ...
Sinatra: A DSL for REST apps
CanCan                                    class Ability‣ CanCan is an                                      include CanCan:...
RSpec‣ RSpec is testing tool for the   require bowling  Ruby programming language.      describe Bowling, "#score" do  Bor...
Cucumber                               Feature: Search courses‣ Cucumber is a tool that        In order to ensure better u...
SLIM
The Future is to the Polyglot                          Client                   HTML                     CSS          Java...
DSL toolbox   META-PROGRAMMING *code* that generates *code*
But beware
But beware
Swords, Guns, and other toys‣ symbols. These have less line-noise than strings and tend to be favored by DSL writers.‣ pro...
Properties :)      ‣ monkey patch Object                         class Developer                                          ...
Class Macroclass << Object  def macro(args)    puts args  endendclass C  macro :testend
Hooks$INHERITORS = []class Animal  def self.inherited(subclass)    $INHERITORS << subclass  endendclass    Fish < Animal  ...
Q&A
Upcoming SlideShare
Loading in …5
×

Ruby talk romania

849 views
798 views

Published on

an overview of typical ruby dsl's and a little bit on metaprogramming

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
849
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
4
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Typically, this approach is used in conjunction with instance_eval and friends, so that some configuration file is loaded (or a block is given) and executed within the context of the sandbox. (This sounds similar to the top-level methods technique, with the exception that theDSL is restricted to the sandbox&amp;#x2014;there no global methods involved.) \n Capistrano and Needle both use this approach\n
  • \n
  • \n
  • Ruby talk romania

    1. 1. A Polyglot worldon DSLs
    2. 2. Who Am I‣ koen.handekyn@up-nxt.com CEO UP-nxt, R&D division of the UnifiedPost Group. Electronic Document Handling (Archiving, Legal Delivery, eInvoicing, Payment, Workflow)‣ Education: Computer Science / Business Administration‣ Background: Telecommunications
    3. 3. Why Ruby?PRODUCTIVITY
    4. 4. Why Ruby? FUN
    5. 5. Why Ruby?
    6. 6. Why is Ruby productive‣ Simplicity - next time :) ?‣ Functional Programming - next time :) ?‣ DSL’s and Meta-Programming
    7. 7. Simplicity‣ DRY‣ KISS‣ YAGNI‣ Least Surprise‣ Convention over Configuration (meaningful defaults)
    8. 8. DSL (domain specific languages)‣ The DSL does not solve every problem in the universe but rather focuses on one little domain • such as building software, querying data, or constructing UIs‣ Notation conforms to meaning • if you read a sentence (statement) in the DSL, you have a clear, unambiguous idea of what it does.‣ A DSL uses high-level concepts that the programmer can use, and translates those to a lower- level implementation (internally).
    9. 9. Internal vs External‣ An external DSL has it’s own custom scanner and parser or uses a standard one, like XML. example DSL’s : mvn, ANT, SQL, dot, regexp, CSS.‣ An internal DSL uses a GPL with meta-programming facilities and is hence embedded inside a GPL like Ruby, LISP, Scala. This approach has recently been popularized by the Ruby community. Aka FluentInterfaces‣ http://martinfowler.com/bliki/DomainSpecificLanguage.html
    10. 10. ActiveAdmin
    11. 11. ActiveAdmin.register Product do # Create sections on the index screen scope :all, :default => true scope :available scope :drafts # Filterable attributes on the index screen filter :title filter :author, :as => :select, :collection => lambda{ Product.authors } filter :price filter :created_at # Customize columns displayed on the index screen in the table index do column :title column "Price", :sortable => :price do |product| number_to_currency product.price end default_actions endend
    12. 12. ActiveRecord‣ Properties are dynamically defined. For every column found in the database, a class Client < ActiveRecord::Base property is added to the # the interesting part is ‘the nothing’ class.   has_one :address   has_many :orders‣ Relations also dynamically   has_and_belongs_to_many :roles   belongs_to :client add methods for working scope :published, where(:published => true)   scope :published_and_commented, with the corresponding published.and(self.arel_table[:comments_count].gt(0)) relations in the ER domain end‣ Scopes express named query fragments in an SQL like DSL
    13. 13. Example DSL: rake namespace :morning do desc "Turn off alarm."‣ task :turn_off_alarm do An ANT like DSL for puts "Turned off alarm. Would have liked 5 more minutes, though." expressing tasks and task end dependencies between desc "Take care of normal hygiene tasks." task :groom_myself do them puts "Brushed teeth." puts "Showered." puts "Shaved."‣ end rake desc "Make coffee" morning:ready_for_the_day task :make_coffee do cups = ENV["COFFEE_CUPS"] || 2 puts "Made #{cups} cups of coffee. Shakes are gone." • Turned off alarm. Would have liked 5 end more minutes, though. • Brushed teeth. desc "Walk the dog" task :walk_dog do • Showered. puts "Dog walked." • Shaved. end • Styled hair. desc "Get ready for the day" • Made 2 cups of coffee. Shakes are gone. task :ready_for_the_day => • Dog walked. [:turn_off_alarm, :groom_myself, ...] do • Ready for the day! puts "Ready for the day!" end end
    14. 14. Example DSL: rails routes‣ The Rails router match "/patients/:id" => "patients#show" recognizes URLs and resources :photos dispatches them to a namespace :admin do controller’s action. It can resources :posts, :comments end also generate paths and URLs, avoiding the need resources :photos to hardcode strings in • • GET /photos => index GET /photos/new => new • POST /photos => create your views with shortcuts • • GET /photos/:id => show GET /photos/:id/edit => edit for REST-full resource • • POST /photos/:id => update DELETE /photos/:id => destroy • photos_path|url => /photos • new_photo_path|url => photos/new • edit_photo_path|url(:id) => photos/:id/edit • photo_path|url(:id) => photos/:id
    15. 15. Capistrino‣ Capistrano is a utility and framework for executing commands in parallel on multiple remote machines, via SSH.‣ http://en.wikipedia.org/wiki/Capistrano task :xml_libs, :hosts => "www.capify.org" do run "ls -x1 /usr/lib | grep -i xml" end
    16. 16. Slop‣ Slop is a simple option parser with an easy to remember syntax and friendly API.‣ https://github.com/injekt/slop opts = Slop.parse do banner "ruby foo.rb [options]n" on :name=, Your name on :p, :password, Your password, :argument => :optional on :v, :verbose, Enable verbose mode end
    17. 17. Workflow class Article‣ Workflow is a finite-state- include Workflow workflow do machine-inspired API for state :new do modeling and interacting with event :submit, :transitions_to what we tend to refer to as => :awaiting_review end ‘workflow’. state :awaiting_review do‣ A lot of business modeling event :review, :transitions_to => :being_reviewed tends to involve workflow-like end concepts, and the aim of this state :being_reviewed do event :accept, :transitions_to library is to make the => :accepted expression of these concepts event :reject, :transitions_to as clear as possible, using => :rejected end similar terminology as found in state :accepted state machine theory. state :rejected‣ http://www.geekq.net/ end end workflow/
    18. 18. Sinatra: A DSL for REST apps
    19. 19. CanCan class Ability‣ CanCan is an include CanCan::Ability def initialize(user) authorization library for if user.admin? # user can perform any action on Ruby on Rails which any object can :manage, :all restricts what resources # user can perform any action on a given user is allowed to the article can :manage, Article access. # negative cannot :destroy, Project # conditions‣ Define abilities can :read, Project, :category => { :visible => true • can :manage, Article } else‣ Check abilities # user can read any object can :read, :all end • cannot? :destroy, @article end end • authorize! :read, @article cannot? :destroy, @article authorize! :read, @article
    20. 20. RSpec‣ RSpec is testing tool for the require bowling Ruby programming language. describe Bowling, "#score" do Born under the banner of it "returns 0 for all gutter game" do bowling = Bowling.new Behaviour-Driven 20.times { bowling.hit(0) } bowling.score.should eq(0) end Development. end describe Order do context "with no items" do it "behaves one way" do # ... end end context "with one item" do it "behaves another way" do # ... end end end
    21. 21. Cucumber Feature: Search courses‣ Cucumber is a tool that In order to ensure better utilization of courses Potential students should be able to executes plain-text search for courses functional descriptions as Scenario: Search by topic automated tests. The Given there are 240 courses which do not have the topic "biology" And there are 2 courses A001, B205 language that Cucumber that each have "biology" as one of the topics understands is called When I search for "biology" Then I should see the following Gherkin (external DSL) courses: | Course code | | A001 |‣ Applicable for BDD for | B205 | Ruby, Java, C#, etc IMPLEMENTING phrases (ruby example) Given /there are (d+) coffees left in the machine/ do |n| @machine = Machine.new(n.to_i) end
    22. 22. SLIM
    23. 23. The Future is to the Polyglot Client HTML CSS Javascript Client Coffeescript SLIM SASS Source JQuery Server Activ CanC Work Rout (Business Ruby ... e an flwo es Layer) Persistence SQL REDIS MongoDB Layer Infrastructur Gem Pupp RSpe Cucu Rake ... e file et c mberI thank God that I speak in tongues more than all of you (1 Corinthians 14:18)
    24. 24. DSL toolbox META-PROGRAMMING *code* that generates *code*
    25. 25. But beware
    26. 26. But beware
    27. 27. Swords, Guns, and other toys‣ symbols. These have less line-noise than strings and tend to be favored by DSL writers.‣ procs. More than anything else, these make DSL’s in Ruby read and work naturally. They allow simple encapsulation of functionality (so you can write augmented branching constructs), and also let you do delayed evaluation of code.‣ modules. With modules you can easily specialize individual objects with DSL methods.‣ eval, instance_eval, and class_eval. It is definitely worth learning the difference between these three, and how they can be used. These are critical to many different dynamic techniques.‣ define_method. This lets you define new methods that can reference their closure, which you can’t do so easily using the eval methods.‣ alias_method. Rails uses this to good effect to allow modules to override behavior of the classes they are included in.‣ Module#included lets you do additional processing at the moment that a module is included in a class.‣ Class#inherited lets you keep track of who is inheriting from what
    28. 28. Properties :) ‣ monkey patch Object class Developer   properties :level, :name, :surname ‣ yield self from   def initialize     yield ( self ) if block_given? constructor   end end # Test our Setters superduperdev = Developer.new do |d|class << Object   d.level = "journeyman" def property( *names )   d.name = "Edmore"" names.each do |name|   d.surname = "Moyo"" define_method( "#{name}=" ) do |value| end" instance_variable_set( "@#{name}", value )" end anotherdev = Developer.new(name: "koen", define_method( name ) do" surname: "handekyn", eval("@#{name}") level: "ceo") end end end alias_method :properties, :property"end
    29. 29. Class Macroclass << Object def macro(args) puts args endendclass C macro :testend
    30. 30. Hooks$INHERITORS = []class Animal def self.inherited(subclass) $INHERITORS << subclass endendclass Fish < Animal def a() endendclass Dog < Animal def b() endendclass Cat < Animal def c() endendputs $INHERITORS.map { |c| c.name }.sort# Cat# Dog# Fish
    31. 31. Q&A

    ×