For example:
rabbit_jumps_in_the_hole :hole_size => 10
Even if you don't understand Ruby Syntax, you know what the function call does.
Think of it this way:
- Function/methods are really 'verbs'.
- Function Options are 'adverbs'
- Object Identifiers are 'nouns'
- Object Attributes are 'adjectives'
- Class Names are 'class names' [gottcha!!!!]
This can be either a good thing or very bad.
Size Matters
Which is easier to learn: A language with 10 verbs or one with 1,000?
Just for the heck of it, I recently tried to get a count of the 'verbs' in Rails 2.0.2. I ran 'egrep -r 'def [a-z]' on all lib directories and came up with:
- actionmailer/lib 694
- actionpack/lib 1393
- activerecord/lib 1134
- activeresource/lib 125
- activesupport/lib 577
- Total 3923
- merb 713
- merb.rb 19
- tasks.rb 0
- Total 732
But Merb gives you a choice of ActiveRecord - with it's 1,100 verbs; DataMapper - with about 500 methods; or Sequel - with about 600.
So learning Merb should be easier than Rails because the vocabulary is about 1/3 to 1/2 the size.
Synonyms are Bad
Which is easier to Learn: a language with one word for each concept or with two or more?
A programming language or environment isn't meant for composing poetry, novels, or movies. It's supposed to precisely express a procedure. Period. It should be concise. That makes it easier for Programmers to understand.
Case closed. DSL's should be concise, singular, and boring - but very, very accurate.
Corollary:
The Rails Inflector is a mistake in every possible way:
- It Expands rather than Tightens the vocabulary of the Rails DSL
- It injects confusion because Programmers now have to worry about singular and plural forms depending on context
- It doesn't work:
- 'XMLClass'.underscore -> 'xml_class'
- 'XMLClass'.underscore.camelize => 'XmlClass'
- 'slave'.pluralize == 'slaves'
- 'slave'.pluralize.singularize == 'slafe'
- It wastes lots of cycles doing it - machine, programmer, and learning
I'm talking about the distance between words. For example frog is very close to frogs but far from toads. That makes it easier to tell a frog from a toad in print than in real life.
Good DSL design should not only use expressive and concise identifiers, but should also keep them far apart, especially when the referents do significantly different things.
Again, picking on Rails, the methods update_attribute(attribute) and update_attributes(attributes) are very close together, but one bypasses attribute Validation. Can you tell which one by the names? Don't you think it's important to know?
DSL is Not Documentation
Most DSL seem to grow more or less organically. The Ruby universe is filled a lot of apparently useful packages with virtually no documentation. Almost all of them have fairly reasonable API documentation - which allows 'one' to learn what each of the 'verbs' in the DSL do, but that's like learning to drive a car by reading Glossary of the Parts! It Just Don't Work.
It's hard as hell to learn a system without some sense of what the thing is supposed to be doing and how it's put together.
Don't belive me?
Figure out a Car from stuff like this:
Wheel - 1. circular object in contact with ground; 2. circular object interfacing driver to directional controls.
Nut - 1. Device for attaching wheel; 2. driver in other automobile; 3. nutritious snack
etc.
That's API doc and that's what you've got when all there is is the DSL.
'nuff for now
2 comments:
Why do you feel that a DSL has to read like a natural language? While this can be the case with some DSLs, it does not seem to me to be a requirement.
Actually, that's the point: DSL's shouldn't be 'natural language' and attempts to make them 'more natural' by adding synonyms, tenses, plurality, etc make them difficult to use.
In other words, I think DSL's should be similar to natural languages, but not as flexible.
Post a Comment