Refactoring code to add lambda laziness – Functional style programming – extending API
182. Refactoring code to add lambda laziness
In this problem let’s have a refactoring session meant to transform a dysfunctional code into a functional one. We start from the following given code – a simple class mapping information about applications dependencies:
public class ApplicationDependency {
private final long id;
private final String name;
private String dependencies;
public ApplicationDependency(long id, String name) {
this.id = id;
this.name = name;
}
public long getId() {
return id;
}
public String getName() {
return name;
}
public String getDependencies() {
return dependencies;
}
private void downloadDependencies() {
dependencies = “list of dependencies
downloaded from repository ” + Math.random();
}
}
Why did we highlight the getDependencies() method? Because this is the point in the application having a dysfunctionality. More precisely, the following class needs the dependencies of an application in order to process them accordingly:
public class DependencyManager {
private Map<Long,String> apps = new HashMap<>();
public void processDependencies(ApplicationDependency appd){
System.out.println();
System.out.println(“Processing app: ” + appd.getName());
System.out.println(“Dependencies: “
+ appd.getDependencies());
apps.put(appd.getId(),appd.getDependencies());
}
}
This class relies on the ApplicationDependency#getDependecies() method which just returns null (the default value of the dependencies fields). The expected application’s dependencies were not downloaded since the downloadDependecies() method was not called. Most probably, a code reviewer will signal this issue and raise a ticket to fix it.
Fixing in imperative fashion
A possible fix will be as follows (in ApplicationDependency):
public class ApplicationDependency {
private String dependencies = downloadDependencies();
…
public String getDependencies() {
return dependencies;
}
…
private String downloadDependencies() {
return “list of dependencies downloaded from repository “
+ Math.random();
}
}
Calling downloadDependencies() at dependencies initialization will definitely fix the problem of loading the dependencies. When the DependencyManager will call getDependencies() it will have access to the downloaded dependencies. But, is this a good approach? I mean downloading the dependencies is a costly operation and we do it every time an ApplicationDependency instance is created. If the getDependencies() method is never called then this costly operation doesn’t pay off the effort.So, a better approach will be to postpone the download of the application’s dependencies until getDependencies() is actually called:
public class ApplicationDependency {
private String dependencies;
…
public String getDependencies() {
downloadDependencies();
return dependencies;
}
…
private void downloadDependencies() {
dependencies = “list of dependencies
downloaded from repository ” + Math.random();
}
}
This is better but is not the best! This time, the application’s dependencies are downloaded every time the getDependencies() method is called. Fortunately, there is a quick fix for this. We just need to add a null check before performing the download:
public String getDependencies() {
if (dependencies == null) {
downloadDependencies();
}
return dependencies;
}
Done! Now, the application’s dependencies are downloaded only at the first call of the getDependencies() method. This imperative solution works like a charm and will pass the code review.
Leave a Reply