Week 10: Lab 6

Objectives

To learn the functional programming style using the new Java language syntax (λ-expression) and library (Stream APIs) by practicing refactoring of an old-fashioned code.

Refactoring

… is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior.

Its heart is a series of small behavior preserving transformations. Each transformation (called a “refactoring”) does little, but a sequence of transformations can produce a significant restructuring. Since each refactoring is small, it’s less likely to go wrong. The system is kept fully working after each small refactoring, reducing the chances that a system can get seriously broken during the restructuring.

Martin Fowler, https://refactoring.com/

Exercise One

Begin with the original program which is written in the “old”, pre-Java 8 style, with the aim of replacing the anonymous inner classes on lambda-expressions. This should have immediate consequences in reducing the number of source files which are required by the program.

If you are doing this lab in your cloned GitLab repository, the following source code and data should already be in homeworks/hw6:

  1. Assimilation.java
  2. Selection.java
  3. Operation.java
  4. Individual.java
  5. Borg.java
  6. star_trek.txt

The Assimilation program simulates an attack by The Borg, an evil collective of cyborgs who force all those they deem “worthy” to submit to cybernetic enhancement and integration into their “hive mind”.

The program accepts one command line argument: the name of the file containing a list of people to assimilate. For example:

java Assimilation star_trek.txt

Once you have successfully converted the original code into streams-based code using λ-expressions, the interfaces Selection.java and Operation.java will no longer be required.

Refactor the code of Assimilation.java by employing lambdas and streams of Java 8. The code of Individual.java and Borg.java do not require any change. In Assimilation.java, first deal with mankind listing and selection processes, originally in Assimilation:65-66 and Assimilation:71-77 (lines of relevant code in the source file are shown). Your solution should include stream creation from list object mankind, and stream operations forEach() and filter(). Think how to assign value to the consumer and predicate objects (in forEach and filter correspondingly). Once you’ve done with re-implementing the selection, you will see that the auxiliary method cull() (Assimilation:16-25) is no longer used and can be removed.

Exercise Two

As the second step, re-implement using streams the conversion process Individual -> Borg. Here, the stream operation is map(..), which is run on a stream of individuals who passed the filter process. Think what java.util.function.Function is required here. Can it be initialised as a lambda expression, or an existing method reference (which class and which method?) can be used? (Hint: both are possible.) Think how the Borg objects (which are the result of mapping individuals by map(Individual -> Borg)) can be collected back to a list for final merging with pre-existing Borg (this part, Assimilation:90, needs no change). This has to be a terminal operation; more than one solution is possible. Similar in Exercise One, an auxiliary method convert() (Assimilation:27-33) is no longer required and can be removed.

Exercise Three (praxis postmortem)

Use git diff command (learn how to use it if on the command line) to view total changes in the original code whence you’ve done both exercises. If you run macOS or Linux you can install the utility called sloccount (or its analogs) to intelligently count how many non-comment and non-empty lines of code a program has. Use it to count number of lines in the original and final solutions. All-in-all, two interfaces, two methods and most of the loops gone! — significant reduction in the code size (in my solution, about 35%).

Updated:  03 May 2017/ Responsible Officer:  Head of School/ Page Contact:  Alexei Khorev