6. Domain Specific
Language Examples
• “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”
6
16. 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
17.
18. Let the DSL you devise
guide your implementation
Kind of like TDD, don’t do more
than what you need to make your
DSL execute correctly.
18
19. 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!
20. 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
21.
22. “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
32. Class Macros
DSL as methods on some ancestor class, and subclasses
can then use those methods to tweak the behavior of
themselves and their subclasses
33.
34. Top-Level Methods
Your 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.
35.
36. Sandboxing
aka 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.
37.
38. 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.
39. You’ll end up coding a
metamodel when writing
your sandboxes
Your metamodel will be better than if you had tried to
write it first based on pure analysis!
40. 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
41. 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
42. Business Natural
Language (BNL)
DSLs that are maintained by business users
47. 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
48. 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 DRY
Descriptive and Maintainable Phrases
49. More on Ruby DSLs
• obiefernandez.com
• jayfields.com
• weblog.jamisbuck.org
• onestepback.org