I was writing some functional test case with Cucumber for JVM and opted to use Groovy for my step definitions. While I am not yet comfortable enough to start any big project with an untyped language like groovy, its super cool for writing test cases. Specially when we write functional test cases, we want to write as less code as possible and achieve as much as possible. I think groovy is a perfect candidate for that. I am also writing my shell/perl scripts with Groovy now. Call me old school but I still like my java 🙂
Anyway, I was fetching the XML from the server and was asserting various attributes on it. Here is how the power of functional programming made it elegant.
def xmlFetchedFromWebservice = ''' <SchedRemote> <!-- Long Form: Room, Service, and Resource --> <WorkOrderDetails ConflictLevel="0" SEQNUM="232323"> <Fields> <Field STAT="10" /> <Field STATUSEX='0'/> </Fields> </WorkOrderDetails> </SchedRemote> ''' def xmlFind = { xmlFields, fieldName -> def field = xmlFields.find { return it['@' + fieldName] != null } return field?.( '@' + fieldName) } def selectXmlFields = {xmlText -> new XmlParser().parseText(xmlText).WorkOrderDetails.Fields.Field} def workOrder = xmlFind.curry(selectXmlFields(xmlFetchedFromWebservice)) assert workOrder('STAT') == 10 assert workOrder('STATUSEX') == 0 //..... many more assersions like this
I refactored some of the implementation details , In a nutshell We have two part task, 1st select the correct section from xml and then perform a search on that section to select the field value.
So once I get the xml from webservice, I select the right fields with selectXmlFields and curry the result in the xmlFind method.
Now, the resulting function can be used almost as object like fashion. The core concept of functional programming which took me quite a while to grasp is that functions are the building blocks, not the objects. If I wanted to do the same thing with java, may be I would create a WorkOrder class, parse the XML in the constructor and use workOrder object. In functional language, I am using the function composition from the currying to perform the same thing. In other words, I am using curry here to bind xmlFind to the perticular workorder instance. How cool is that?