Thursday 23 February 2017

A Natural Progression Towards Lambda

At my work, in order to deal with a grid1 in the frontend and a list at the backend, we use a DataModel at the backend.

It seems simple enough, and used to work as follows:
private List<Person> list = Arrays.asList(new Person("Jim"), new Person("Jack"));

private ListDataModel<Person> dataModel = new ListDataModel<>(list);
This had some shortcomings when for example the user decided to select a different department, executing this code:
list = findPersonsByDepartment(department);
This seems to work just fine. A person selects a different department, and the employees data model updates itself. Or so one would think.
What happens is that the ListDataModel retains the old list. So, the frontend is never updated.

Reusing the same list

Because of this little problem, our code retains a lot of the following statements, to make sure the same list is used over and over again:
list.clear();
list.addAll(findPersonsByDepartment(department));
It seems a slightly convoluted way to doing things.

Anonymous inner classes

We soon found out that anonymous inner classes would solve this problem better, and in fact there are more anonymous inner classes than there are named DataModels in our current code base.

It looks like the following:
private ListDataModel<Person> dataModel = new ListDataModel<Person>() 
{
   @Override
   public List<Person> getList() 
   {
     return findPersonsByDepartment(department);
   }
};
There now, any time the contents of the ListDataModel is requested in the frontend, a new and accurate List containing the department employees is returned.

Passing code

Instead of creating an entire new anonymous inner subclass of a ListDataModel, it might be more elegant to create an interface especially for this purpose, call it the ListProvider interface.

As follows:
public interface ListProvider<T> 
{
  List<T> getList();
}

private ListDataModel<Person> dataModel = new ListDataModel<Person>(new ListProvider<>() 
{
   @Override
   public List<Person> getList() 
   {
     return findPersonsByDepartment(department);
   }
});

Using lambdas


The good part is that now with Java 8 we can start using Lambdas.

And in this case, we have an interface containing just one method. This is in essence the definition of a lambda.

So now the proper way to write this would be the following:
public interface ListProvider<T> 
{
  List<T> getList();
}

private ListDataModel<Person> dataModel = 
    new ListDataModel<Person>(() -> findPersonsByDepartment(department));
Convenient, isn't it?
In this case, the lambda is called a Supplier2 .

References

[1] Welcome to the SlickGrid! (outdated sadly)
https://github.com/mleibman/SlickGrid/wiki
[2] Supplier (Java Platform SE 8)
https://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html

No comments:

Post a Comment