Slowly and steadily I have started realizing the power of DSL(Domain Specific Langauge) and I found Groovy a very powerful tool to write DSL. DSL takes programming to next level by allowing input to a program be given as set of actions than merely a function call.If you want to explore DSL in detail, I would recommend you to read Martin Fowler's book on DSL.
Closures play an important role while writing DSL in groovy. In Grails, DSL with closure has been used extensively. Take an example of GORM Criteria.
In above example we have passed closure to list method of criteria to get all Persons whose name matches "XYZ", gender is equal to male and age is greater than 30. Keywords like, eq and gt are very intuitive and anybody reading the code can tell what code is expected to do just by looking at it.
In my project also I have started using DSL at various places which I think are ideal places for DSL. Take an example of Email Service. The sendMail method of emailService expects certain data to be provided as input e.g. from, to, cc, bcc, subject etc.
*Note : This implementation is similar to one provided by MailService plugin in grails.
Behind the scene in EmailService I assign delegate of closure as EmailData instance. With this it is now possible to map to,cc,bcc,subject to methods like
void to(String to)
void cc(String cc)
and so on...Within these methods, the data is assigned to instance variables like to, cc, bcc. This data can then be used in actual logic to send mail.
This way, DSL makes code more readable and intuitive. Client of EmailService API do not need to create an instance of EmailData and set required variables. They can simply pass closure to sendMail method and can pass required data as action.
I have personally started liking DSL and will be using more and more going forward. Do let me know your thoughts/comments on this.
Closures play an important role while writing DSL in groovy. In Grails, DSL with closure has been used extensively. Take an example of GORM Criteria.
def criteria = Person.createCriteria()
def result = criteria.list{
like("name","%XYZ%")
eq("gender","male")
gt("age",30)
}
In above example we have passed closure to list method of criteria to get all Persons whose name matches "XYZ", gender is equal to male and age is greater than 30. Keywords like, eq and gt are very intuitive and anybody reading the code can tell what code is expected to do just by looking at it.
In my project also I have started using DSL at various places which I think are ideal places for DSL. Take an example of Email Service. The sendMail method of emailService expects certain data to be provided as input e.g. from, to, cc, bcc, subject etc.
*Note : This implementation is similar to one provided by MailService plugin in grails.
emailService.sendMail{
from admin@xyz.com
to to@xyz.com
cc cc@xyz.com
bcc bcc@xyz.com
subject Test
}
Behind the scene in EmailService I assign delegate of closure as EmailData instance. With this it is now possible to map to,cc,bcc,subject to methods like
void to(String to)
void cc(String cc)
and so on...Within these methods, the data is assigned to instance variables like to, cc, bcc. This data can then be used in actual logic to send mail.
class EmailService{
void sendMail(Closure closure){
EmailData emailData = new EmailData()
closure.delegate = emailData
closure.resolveStrategy = Closure.DELEGATE_FIRST
closure.call()
/*
Write the logic here to send email. Required data can be
accessed as ..
emailData.to
emailData.cc
emailData.bcc
emailData.subject
*/
}
class EmailData{
String to
String cc
String bcc
String subject
void to(String to){
this.to=to
}
void cc(String cc){
this.cc=cc
}
void bcc(String bcc){
this.bcc=bcc
}
void subject(String subject){
this.subject=subject
}
}
}
This way, DSL makes code more readable and intuitive. Client of EmailService API do not need to create an instance of EmailData and set required variables. They can simply pass closure to sendMail method and can pass required data as action.
I have personally started liking DSL and will be using more and more going forward. Do let me know your thoughts/comments on this.
No comments:
Post a Comment