DSL Styles - Imperative vs. Declarative
I posted yesterday about building a rule engine using a DSL. After I wrote that, I tried to think about what style it was. That made me realize that I had no clear distinction between imperative and declarative DSL. At least not a coherent, internally consistent one.
I asked the Alt.net mailing list, and a lively discussion enthused. Contrary to my opinion, a lot of people disagreed with my opinion that this is a declarative style DSL:
when User.IsPreferred and Order.TotalCost > 1000:
addDiscountPrecentage 5
applyFreeShipping
when not User.IsPreferred and Order.TotalCost > 1000:
suggestUpgradeToPreferred
applyFreeShipping
when User.IsNotPreferred and Order.TotalCost > 500:
applyFreeShipping
It looks too much like code apperantely. After some debate, we now have the following candidates for declarative DSL:
From Chad:
about User
when Preferred and OrderTotal > 1000:
Discount is 0.05
And Shipping is FREE;
when not Preferred and OrderTotal > 1000:
Upgrade Suggested
And Shipping is FREE;
when not Preferred and OrderTotal > 500:
Shipping is FREE;
Based on Berry's ideas:
applyDiscount 5.precent:
when User.IsPreferred and Order.TotalCost > 1000
suggestPreferred:
when not User.IsPreferred and Order.TotalCost > 1000
freeShipping:
when Order.TotalCost > 500
The really interesting thing to me, so far, is that they are all functionality equivalents. From the point of view of the implementer, there isn't much difference at all betwee them.
My own, loosely defined and likely wrong definition was based on what the DSL actually did. If the DSL performed all the work internally, I would call it imperative. If the DSL performed some work that produced an object graph, which another part of the system would tehn consume, I would call it declarative.
Thoughts?
Comments
Usually, I define a piece of code to be imperative if it tells the computer what to do and declarative if it describes something (the outcome or the requirements). Doesn't matter whether its written in a DSL or something else.
Wikipedia explains this as follows:
<quote>
According to one definition, a program is "declarative" if it describes what something is like, rather than how to create it. For example, HTML web pages are declarative because they describe what the page should contain — title, text, images — but not how to actually display the page on a computer screen. This is a different approach from imperative programming languages such as Fortran, C, and Java, which require the programmer to specify an algorithm to be run.
</quote>
Although Wikipedia contrasts this with the notion of declarative (functional, logic-oriented) vs. imperative (procedural, object-oriented) languages, I think this fits quite nicely, as the concepts of functional or logic-oriented programs are based on descriptions (of functions, facts, and rules), whereas procedural or object-oriented programs are made up of a sequence of commands. Of course, the borders are blurred when you have I/O predicates in Prolog (which work very procedurally) or custom attributes in C# (which are purely descriptive).
Still, for me, the word "imperative" means "commands" and "declarative" means "descriptions".
Another way of seeing it is that with a declarative DSL you specify metadata.
My own definition is that an imperative DSL run and that is it.
A declarative DSL output some object graph to another stage to execute.
I think mine is better, is shorter and implies yours ;)
I don't think so.
Because specifying metadata and conditionals doesn't really go very well in my opinion
You mean that conditionals are not metadata?
The code you wrote in first place qualifies as metadata if instead of executing it you load it in "some object graph to another stage to execute", for example, you can use that turn that metadata into javascript and use it in the client so you can turn on the "free shipping" textbox without roundtripping.
I need to think about this...
I'd probably go with how powerful your reasoning can be about the DSL when it is converted to an abstract syntax tree (AST). If your DSL is Turing Complete (or perhaps close enough), the Halting Problem applies and your ability to reason about your code is limited. If, on the other hand, you can do lots of powerful reasoning, that means you can transform the AST to many different forms, one of which probably parameter-drives some imperative code.
One could almost say that one of the essences of my company is to make things parameter-driven, so I know a little about the declarative side of things. :-D
Comment preview