Software Development Via Functional Programming
Get a look at how to implement a functional approach to Java, complete with examples.
Join the DZone community and get the full member experience.
Join For FreeIntroduction
When I started my career back in 2009, I had to work on an IVR (Interactive Voice Response) application developed in Java. It was a lightweight server-side application but after some time, the way it was structured as well, was not able to evolve well. Code and configuration duplications, being unable to use the same call flows with minor changes as per client request, without refactoring, or in some cases like tight deadlines, developers resorted to duplication. So after some time, a very simple application became a nightmare to manage and maintain.
At that time, an initiative was started to cope with this. I thought of an application design and even created a PoC. The idea is to develop smaller configurable independent functions based on an interface having a single abstract method (SAM). Such functions would represent a unit of work just like a class method in Java. To what level of detail a unit of work is defined is up to the implementor. But such functions shouldn't be broader in the sense that they perform multiple tasks in a single implementation or perform very minute tasks.
Now what to do with such functions. Well, we could configure them not only to initialize them but also to loosely wire them to create a flow or multiple flows. By loosely wiring them, I mean that the functions will not have a direct reference of other functions. No direct dependency among them. Based on what the case is the function will provide the name of the next function as configured. But to provide to what is the next question. Well, there'll a simple container that will contain all the functions mapped by their names. So it'll simply look for the name of next function, get its reference & call its process
method.
Example
Enough of the boring theory. Let's see some example Java code so that it makes some sense.
Here's my proposed interface:
@FunctionalInterface // Not needed but just to show that FP was possible prior to Java 8 as well
public interface Task {
void process(Map<String, Object> data);
}
Now a simple example. The purpose of this example is to help in understanding the above concept only.
Let's create a simple IVR flow where the caller is played a welcome message and then given a language selection choice. This doesn't imply that idea only applies to IVR or IVR like applications.
We create a function that plays some sound files and may wait for input as configured. This is just an example code:
public class IvrInputTask implements Task {
private String soundFile;
private int waitTime; //0 means no input allowed
private String defaultNextTask;
private String userInputNextTask;
// assume necessary constructors or setters exist
@Override
public void process(Map<String, Object> dataMap) {
String nextTask;
char userInput = playAndWait(soundFile, waitTime);// assume such lib function exists
if(userInput == '\0') { // means no input
nextTask = defaultNextTask;
} else {
dataMap.put("userInput", userInput);
nextTask = userInputNextTask;
}
dataMap.put("nextTask", nextTask);
}
}
Now we create instances of above function and run the flow in a very basic way:
public class DemoApp {
public static void main(String args[]) {
IvrInputTask welcome = new IvrInputTask();
// set soundFile="welcome.wav", waitTime=0, defaultNextTask="languageSelection"
IvrInputTask langSel = new IvrInputTask();
// set soundFile="langSel.wav", waitTime=3000, defaultNextTask="bye", userInputNextTask="whatever"
IvrInputTask bye = new IvrInputTask();
// set soundFile="bye.wav", waitTime=0, defaultNextTask=""
Map<String, Task> taskMap = new HashMap<>();
Map<String, Object> dataMap = new HashMap<>();
String nextTask = "welcome";
Task task;
taskMap.put("welcome", welcome);
taskMap.put("languageSelection", langSel);
taskMap.put("bye", bye);
while((task=taskMap.get(nextTask))!=null) {
task.process(dataMap);
nextTask = (String)dataMap.get("nextTask");
}
}
}
Hopefully, the example is self-explanatory. As we can see, we only created the function once but reused it by simply reconfiguring it. Also, we managed the flow-through configurations, as seen from above.
I have created a sample project on GitHub that can create, initialize, and run such task instances. It's very basic for now but does work. Check out the links in the references.
Conclusion
So we can see that the world of software development could be transformed so simply. Just create a function once and then use it anywhere anytime. No code changes or even application restarts required. A GUI could be provided as well to build or alter flows.
References
https://www.linkedin.com/pulse/software-development-management-mobasher-khan
https://www.linkedin.com/pulse/software-development-management-ii-mobasher-khan
Opinions expressed by DZone contributors are their own.
Comments