agile dsl development in ruby

49
1 Agile DSL Development in Ruby Obie Fernandez http://obiefernandez.com ThoughtWorks Technologist InfoQ.com Ruby Editor

Upload: elliando-dias

Post on 16-Nov-2014

3.884 views

Category:

Technology


0 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Agile DSL Development in Ruby

1

Agile DSL Development in Ruby

Obie Fernandezhttp://obiefernandez.com

ThoughtWorks TechnologistInfoQ.com Ruby Editor

Page 2: Agile DSL Development in Ruby

2

• DSL Primer

• Frameworks vs. DSLs

• Implementing DSLs in Ruby

• Real-world lessons learned

Session Topics

Page 3: Agile DSL Development in Ruby

jargon: the language, esp. the vocabulary, peculiar to a particular trade, profession, or group

Page 4: Agile DSL Development in Ruby

• Designed for a specific domain

• Captures jargon in executable form

• Can be internal or external (as per Fowler)

Domain Specific Languages

Page 5: Agile DSL Development in Ruby

Ruby-based DSLs are internal

Page 6: Agile DSL Development in Ruby

6

• “Venti half-caf, non-fat, no foam, no whip latte”

• “Route 66, swinging, easy on the chorus, extra solo at the coda, and bump at the end”

Domain Specific Language Examples

Page 7: Agile DSL Development in Ruby

7

The coffee example as normal code...

Page 8: Agile DSL Development in Ruby
Page 9: Agile DSL Development in Ruby

9

depends on an API

Page 10: Agile DSL Development in Ruby
Page 11: Agile DSL Development in Ruby

That code doesn’t match the way that the

domain is described

Page 12: Agile DSL Development in Ruby

It’s difficult to verify too!

Page 13: Agile DSL Development in Ruby

Is this right? Hmm

Page 14: Agile DSL Development in Ruby

What about DSL style?

Page 15: Agile DSL Development in Ruby
Page 16: Agile DSL Development in Ruby

Designing Ruby DSLs

• Don’t try to do an abstract metamodel first

• Capture your DSL concepts in valid Ruby syntax, but don’t worry about implementation

• Iterate over your Ruby DSL syntax until authors agree that it faithfully represents the domain, then work on the implementation

Page 17: Agile DSL Development in Ruby
Page 18: Agile DSL Development in Ruby

18

Let the DSL you devise guide your implementation

Kind of like TDD, don’t do morethan what you need to make your

DSL execute correctly.

Page 19: Agile DSL Development in Ruby

DSLs that reflect business documents such as contracts are great

Designing a DSL that’s as close as possible to the document it reflects makes verification of the system much easier!

Page 20: Agile DSL Development in Ruby

Agile DSL Development?

• Start with short iterations over the design

• Incorporate end-user feedback, pair with them if possible

• Do TDD your context code

• Do refactor your context code often, but avoid over-engineering it

Page 21: Agile DSL Development in Ruby
Page 22: Agile DSL Development in Ruby

“The fascinating thing is that, in my experience, most well-written Ruby programs are already a DSL, just by

nature of Ruby’s syntax.”

Jamis Buck, 37signals

Page 23: Agile DSL Development in Ruby

Sweet DSL Syntax Sugar

• Optional parentheses

• Symbols

• Blocks

• Literal arrays and hashes

• Variable-length arguments

Page 24: Agile DSL Development in Ruby

Most of the time,Rails feels like a DSL for

writing web apps

Page 25: Agile DSL Development in Ruby
Page 26: Agile DSL Development in Ruby

“the trick to writing DSL’s in Ruby is really knowing what you can and

can’t do with Ruby’s metaprogramming features”

Jamis Buck, 37signals

Page 27: Agile DSL Development in Ruby
Page 28: Agile DSL Development in Ruby

Different types of Ruby DSL designs

Page 29: Agile DSL Development in Ruby

InstantiationYour DSL is simply methods on an object

Page 30: Agile DSL Development in Ruby
Page 31: Agile DSL Development in Ruby
Page 32: Agile DSL Development in Ruby

Class MacrosDSL as methods on some ancestor class, and subclasses can then use those methods to tweak the behavior of

themselves and their subclasses

Page 33: Agile DSL Development in Ruby
Page 34: Agile DSL Development in Ruby

Top-Level MethodsYour application defines the DSL as top-level methods, and then invokes load with the path to your DSL script. When

those methods are called in the configuration file, they modify some central (typically global) data, which your application uses to determine how it should execute.

Page 35: Agile DSL Development in Ruby
Page 36: Agile DSL Development in Ruby

Sandboxingaka Contexts

Your DSL is defined as methods of some object, but that object is really just a “sandbox”. Interacting with the

object’s methods modify some state in the sandbox, which is then queried by the application.

Page 37: Agile DSL Development in Ruby
Page 38: Agile DSL Development in Ruby

Sandboxing is useful for processing user-

maintained scripts kept in your database

Just load up the script and execute it in the sandbox at runtime. Vary behavior by changing the execution context.

Page 39: Agile DSL Development in Ruby

You’ll end up coding a metamodel when writing

your sandboxesYour metamodel will be better than if you had tried to

write it first based on pure analysis!

Page 40: Agile DSL Development in Ruby

Ruby Features used by DSL implementors

• Symbols, less noisy than strings

• Blocks, enabling delayed evaluation of code

• Modules, for cleaner separation of code

• Splats, for handling parameter arrays

• eval, instance_eval, and class_eval

• define_method and alias_method

Page 41: Agile DSL Development in Ruby

It’s a different way of thinking about writing code, and as such needs to be

learned by doing, not by reading. Experimentation is the key!

Jamis Buck, 37signals

Page 42: Agile DSL Development in Ruby

Business Natural Language (BNL)

DSLs that are maintained by business users

Page 43: Agile DSL Development in Ruby

Incorporating user editable BNL scripts into

your application...How crazy do you want to get?

Page 44: Agile DSL Development in Ruby

Programmers can deal with more complexity than domain expertsInternal DSLs might not be the best choice

Page 45: Agile DSL Development in Ruby
Page 46: Agile DSL Development in Ruby

That wasn’t even valid Ruby syntax!

Page 47: Agile DSL Development in Ruby

Hybrid Ruby BNLs

• Our experiment with an external DSLs

• Business rules are stored in the database as text

• Pre-parser appends an underscore to each word, replaces white space with '.' and changes each number to be an argument to a method that stores the numeric values

• Once the preparse has executed, each line is instance_eval’d to create rule objects

• Rule objects are then evaluated using the appropriate context

Page 48: Agile DSL Development in Ruby

Real-world lessons learned doing BNLs

• Keep the language consistent

• Creating a language that can execute a line at a time greatly simplifies syntax checking

• Keep the language simple. Subject matter experts get fussy about complexity.

• BNL code is DAMP, not DRYDescriptive and Maintainable Phrases

Page 49: Agile DSL Development in Ruby

More on Ruby DSLs

• obiefernandez.com

• jayfields.com

• weblog.jamisbuck.org

• onestepback.org