SlideShare una empresa de Scribd logo
1 de 31
Descargar para leer sin conexión
A Polyglot world
on DSLs
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
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
  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).
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
ActiveAdmin
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
  end

end
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
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
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
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
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
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/
Sinatra: A DSL for REST apps
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
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
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
SLIM
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     mber

I thank God that I speak in tongues more than all of you (1 Corinthians 14:18)
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.
‣ 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
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
Class Macro


class << Object
  def macro(args)
    puts args
  end
end

class C
  macro :test
end
Hooks
$INHERITORS = []

class Animal
  def self.inherited(subclass)
    $INHERITORS << subclass
  end
end

class    Fish < Animal
  def    a() end
end
class    Dog < Animal
  def    b() end
end
class    Cat < Animal
  def    c() end
end

puts $INHERITORS.map { |c| c.name }.sort

# Cat
# Dog
# Fish
Q&A

Más contenido relacionado

La actualidad más candente

Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasminePaulo Ragonha
 
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory CourseRuby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Coursepeter_marklund
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - IntroductionVagmi Mudumbai
 
Migrating PriceChirp to Rails 3.0: The Pain Points
Migrating PriceChirp to Rails 3.0: The Pain PointsMigrating PriceChirp to Rails 3.0: The Pain Points
Migrating PriceChirp to Rails 3.0: The Pain PointsSteven Evatt
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...bobmcwhirter
 
TorqueBox for Rubyists
TorqueBox for RubyistsTorqueBox for Rubyists
TorqueBox for Rubyistsbobmcwhirter
 
TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011bobmcwhirter
 
Introducing RaveJS: Spring Boot concepts for JavaScript applications
Introducing RaveJS: Spring Boot concepts for JavaScript applicationsIntroducing RaveJS: Spring Boot concepts for JavaScript applications
Introducing RaveJS: Spring Boot concepts for JavaScript applicationsJohn Hann
 
Immutable Deployments with AWS CloudFormation and AWS Lambda
Immutable Deployments with AWS CloudFormation and AWS LambdaImmutable Deployments with AWS CloudFormation and AWS Lambda
Immutable Deployments with AWS CloudFormation and AWS LambdaAOE
 
Security Goodness with Ruby on Rails
Security Goodness with Ruby on RailsSecurity Goodness with Ruby on Rails
Security Goodness with Ruby on RailsSource Conference
 
O que há de novo no Rails 3
O que há de novo no Rails 3O que há de novo no Rails 3
O que há de novo no Rails 3Hugo Baraúna
 
Ruby on Rails survival guide of an aged Java developer
Ruby on Rails survival guide of an aged Java developerRuby on Rails survival guide of an aged Java developer
Ruby on Rails survival guide of an aged Java developergicappa
 
DataMapper on Infinispan
DataMapper on InfinispanDataMapper on Infinispan
DataMapper on InfinispanLance Ball
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackIgnacio Martín
 
Introduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman OrtegaIntroduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman Ortegaarman o
 

La actualidad más candente (20)

Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
Debugging on rails
Debugging on railsDebugging on rails
Debugging on rails
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory CourseRuby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Course
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - Introduction
 
Migrating PriceChirp to Rails 3.0: The Pain Points
Migrating PriceChirp to Rails 3.0: The Pain PointsMigrating PriceChirp to Rails 3.0: The Pain Points
Migrating PriceChirp to Rails 3.0: The Pain Points
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
 
TorqueBox for Rubyists
TorqueBox for RubyistsTorqueBox for Rubyists
TorqueBox for Rubyists
 
Django in the Real World
Django in the Real WorldDjango in the Real World
Django in the Real World
 
TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011
 
Introducing RaveJS: Spring Boot concepts for JavaScript applications
Introducing RaveJS: Spring Boot concepts for JavaScript applicationsIntroducing RaveJS: Spring Boot concepts for JavaScript applications
Introducing RaveJS: Spring Boot concepts for JavaScript applications
 
Using java beans(ii)
Using java beans(ii)Using java beans(ii)
Using java beans(ii)
 
Immutable Deployments with AWS CloudFormation and AWS Lambda
Immutable Deployments with AWS CloudFormation and AWS LambdaImmutable Deployments with AWS CloudFormation and AWS Lambda
Immutable Deployments with AWS CloudFormation and AWS Lambda
 
Security Goodness with Ruby on Rails
Security Goodness with Ruby on RailsSecurity Goodness with Ruby on Rails
Security Goodness with Ruby on Rails
 
O que há de novo no Rails 3
O que há de novo no Rails 3O que há de novo no Rails 3
O que há de novo no Rails 3
 
Os Bunce
Os BunceOs Bunce
Os Bunce
 
Ruby on Rails survival guide of an aged Java developer
Ruby on Rails survival guide of an aged Java developerRuby on Rails survival guide of an aged Java developer
Ruby on Rails survival guide of an aged Java developer
 
DataMapper on Infinispan
DataMapper on InfinispanDataMapper on Infinispan
DataMapper on Infinispan
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and Webpack
 
Introduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman OrtegaIntroduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman Ortega
 

Similar a A Polyglot world on DSLs

Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Railsrstankov
 
Android Bootstrap
Android BootstrapAndroid Bootstrap
Android Bootstrapdonnfelker
 
RubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - KeynoteRubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - KeynoteDr Nic Williams
 
Migrating Legacy Data (Ruby Midwest)
Migrating Legacy Data (Ruby Midwest)Migrating Legacy Data (Ruby Midwest)
Migrating Legacy Data (Ruby Midwest)Patrick Crowley
 
Rails web api 开发
Rails web api 开发Rails web api 开发
Rails web api 开发shaokun
 
DevOps for Humans - Ansible for Drupal Deployment Victory!
DevOps for Humans - Ansible for Drupal Deployment Victory!DevOps for Humans - Ansible for Drupal Deployment Victory!
DevOps for Humans - Ansible for Drupal Deployment Victory!Jeff Geerling
 
Catalyst - refactor large apps with it and have fun!
Catalyst - refactor large apps with it and have fun!Catalyst - refactor large apps with it and have fun!
Catalyst - refactor large apps with it and have fun!mold
 
To Batch Or Not To Batch
To Batch Or Not To BatchTo Batch Or Not To Batch
To Batch Or Not To BatchLuca Mearelli
 
Ruby on Rails at PROMPT ISEL '11
Ruby on Rails at PROMPT ISEL '11Ruby on Rails at PROMPT ISEL '11
Ruby on Rails at PROMPT ISEL '11Pedro Cunha
 
Rails 3 (beta) Roundup
Rails 3 (beta) RoundupRails 3 (beta) Roundup
Rails 3 (beta) RoundupWayne Carter
 
Practical Chef and Capistrano for Your Rails App
Practical Chef and Capistrano for Your Rails AppPractical Chef and Capistrano for Your Rails App
Practical Chef and Capistrano for Your Rails AppSmartLogic
 
DevOps Hackathon: Session 3 - Test Driven Infrastructure
DevOps Hackathon: Session 3 - Test Driven InfrastructureDevOps Hackathon: Session 3 - Test Driven Infrastructure
DevOps Hackathon: Session 3 - Test Driven InfrastructureAntons Kranga
 
Linux Shell Scripting Craftsmanship
Linux Shell Scripting CraftsmanshipLinux Shell Scripting Craftsmanship
Linux Shell Scripting Craftsmanshipbokonen
 
Phoenix for Rails Devs
Phoenix for Rails DevsPhoenix for Rails Devs
Phoenix for Rails DevsDiacode
 
Introduction à Ruby
Introduction à RubyIntroduction à Ruby
Introduction à RubyMicrosoft
 

Similar a A Polyglot world on DSLs (20)

Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Android Bootstrap
Android BootstrapAndroid Bootstrap
Android Bootstrap
 
Supa fast Ruby + Rails
Supa fast Ruby + RailsSupa fast Ruby + Rails
Supa fast Ruby + Rails
 
RubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - KeynoteRubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - Keynote
 
Migrating Legacy Data (Ruby Midwest)
Migrating Legacy Data (Ruby Midwest)Migrating Legacy Data (Ruby Midwest)
Migrating Legacy Data (Ruby Midwest)
 
Rails web api 开发
Rails web api 开发Rails web api 开发
Rails web api 开发
 
DevOps for Humans - Ansible for Drupal Deployment Victory!
DevOps for Humans - Ansible for Drupal Deployment Victory!DevOps for Humans - Ansible for Drupal Deployment Victory!
DevOps for Humans - Ansible for Drupal Deployment Victory!
 
Catalyst - refactor large apps with it and have fun!
Catalyst - refactor large apps with it and have fun!Catalyst - refactor large apps with it and have fun!
Catalyst - refactor large apps with it and have fun!
 
To Batch Or Not To Batch
To Batch Or Not To BatchTo Batch Or Not To Batch
To Batch Or Not To Batch
 
Ruby on Rails at PROMPT ISEL '11
Ruby on Rails at PROMPT ISEL '11Ruby on Rails at PROMPT ISEL '11
Ruby on Rails at PROMPT ISEL '11
 
Rails cantrips
Rails cantripsRails cantrips
Rails cantrips
 
Rails 3 (beta) Roundup
Rails 3 (beta) RoundupRails 3 (beta) Roundup
Rails 3 (beta) Roundup
 
Practical Chef and Capistrano for Your Rails App
Practical Chef and Capistrano for Your Rails AppPractical Chef and Capistrano for Your Rails App
Practical Chef and Capistrano for Your Rails App
 
Chef advance
Chef advanceChef advance
Chef advance
 
Chef advance
Chef advanceChef advance
Chef advance
 
DevOps Hackathon: Session 3 - Test Driven Infrastructure
DevOps Hackathon: Session 3 - Test Driven InfrastructureDevOps Hackathon: Session 3 - Test Driven Infrastructure
DevOps Hackathon: Session 3 - Test Driven Infrastructure
 
Linux Shell Scripting Craftsmanship
Linux Shell Scripting CraftsmanshipLinux Shell Scripting Craftsmanship
Linux Shell Scripting Craftsmanship
 
Phoenix for Rails Devs
Phoenix for Rails DevsPhoenix for Rails Devs
Phoenix for Rails Devs
 
Introduction à Ruby
Introduction à RubyIntroduction à Ruby
Introduction à Ruby
 
Ruby For Startups
Ruby For StartupsRuby For Startups
Ruby For Startups
 

A Polyglot world on DSLs

  • 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
  • 6. Why is Ruby productive ‣ Simplicity - next time :) ? ‣ Functional Programming - next time :) ? ‣ DSL’s and Meta-Programming
  • 7. Simplicity ‣ DRY ‣ KISS ‣ YAGNI ‣ Least Surprise ‣ Convention over Configuration (meaningful defaults)
  • 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. 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
  • 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 end end
  • 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. 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. 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. 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. 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. 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. Sinatra: A DSL for REST apps
  • 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. 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. 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. SLIM
  • 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 mber I thank God that I speak in tongues more than all of you (1 Corinthians 14:18)
  • 24. DSL toolbox META- PROGRAMMING *code* that generates *code*
  • 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. 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. Class Macro class << Object def macro(args) puts args end end class C macro :test end
  • 30. Hooks $INHERITORS = [] class Animal def self.inherited(subclass) $INHERITORS << subclass end end class Fish < Animal def a() end end class Dog < Animal def b() end end class Cat < Animal def c() end end puts $INHERITORS.map { |c| c.name }.sort # Cat # Dog # Fish
  • 31. Q&A

Notas del editor

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. 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
  38. \n
  39. \n