Ayende @ Rahien

Unnatural acts on source code

Playing with Boo's DSLs

Boo has gotten a lot better in terms of flexibility lately, a lot better. I was able to churn this little DSL in about an hour:

OnCreate Account:
	Entity.AccountNumber = date.Now.Ticks
	
	
 OnCreate Order:
	if Entity.Total > Entity.Account.MaxOrderTotal:
BeginManualApprovalFor Entity

From the perspective of the DSL, it is very easy to use, and from the implementer perspective, this was ridiculously easy to implement.

The only half-way complex thing here is the introduce base class action, which is usually the first approach that you take, which is why I don't consider it complex. Then you can just do create the base class:

abstract class DslBase:

	[property(Entity)] 
entity as object
        def OnCreate(entity as System.Type, action as callable()):
		Actions.RegisterOnCreate(entity.Name, action)
		
	abstract def Execute():
		pass
	
	def BeginManualApprovalFor(order as Order):
		print "Starting approval process for Order #${order.Id}"

In the base class you just do what you would normally do, in this case, it just register the new action. Here is the implementation:

class Actions:
	
	static onCreateActions = {}
	
	static def RegisterOnCreate(entityName as string, action as callable()):
		onCreateActions[entityName] = action
		
	
	static def OnCreate(entity as object):
		entityName = entity.GetType().Name
		action = onCreateActions[entityName] as callable()
		if not action:
			print "No action defined for ${entityName}"
			return
		dsl = (action.Target as DslBase)
		dsl.Entity = entity
		action()

The client code is simply:

SampleDSL().Prepare("Sample.boo")

account = Account(MaxOrderTotal: 100)

print "Before: ${account.AccountNumber}"
Actions.OnCreate( account )
print "After: ${account.AccountNumber}"

order = Order(Account: account, Total: 500 )
Actions.OnCreate( order )

All you have left then is to get a rich enough library of methods on the DslBase, for the business user to work with, document how this is done, and that is it.

Comments

No comments posted yet.

Comments have been closed on this topic.