Wednesday, August 30, 2017

Java 8 - Restructure legacy code


How do we convert the ledgacy code into Lamda Style ?  In Java 8, you may encounter that one function can be done in Java 8 with multiple approaches , So which implementation shall we choose ?



                   Restructure 1 - Anonymous Class to Lamda 

// convert from anonymous class into lamda
Runnable r2 = (Runnable) () -> System.out.println("Hello");

Restructure 2 - Use predefined implementations


// Don't use
int totalCalories = menu.stream().map(Dish::getCalories).reduce(0, (c1, c2) -> c1 + c2);
// recommend 
int totalCalories = menu.stream().collect(Collectors.summingInt(Dish::getCalories));    
// Don't use
inventory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));
// recommend 
inventory.sort(comparing(Apple::getWeight));

Restructure 3 - Use Stream 


menu.parallelStream().filter(d -> d.getCalories() > 300).map(Dish::getName)
                     .collect(toList());

The code above is a transfer from normal collection loop into Stream way , However, In our real work, This kind of code is hard to be implemented. as In the collection loopping, we may use break, continue or return , situations are complex . Now, this issue can be solved by some third party library


Restructure 4 - short & frequent data retrival 



public static void main(String[] args) {
   // generateDiagnostic() is frequently triggered
   log(Level.FINER, () -> "Problem: " + generateDiagnostic());
}
 
public static void log(Level level, Supplier<String> msgSupplier) {
 //...
}
 
public static String generateDiagnostic() { return "ok"; }

Restructure 5 - Strategy Pattern


The above Image is the old Strategy Pattern Demo , Now, We don't need it any more and we don't need to create extra classes to implement an interface but can declare and use strategy directly.


// Strategy A
Validator numericValidator = new Validator((String s) -> s.matches("[a-z]+"));
boolean b1 = numericValidator.validate("aaaa");
  
// Strategy B
Validator lowerCaseValidator = new Validator((String s) -> s.matches("\\d+"));
boolean b2 = lowerCaseValidator.validate("bbbb");

Restructure 6 - Template Pattern


The above illustration is a normal template pattern , well what if you need another template with just a samll difference with original template, in Java 7, You need to recreate a new template , In Java 8, It's very simple & dynamic.


public abstract class OnlineBanking {
   // overrall template
   public void processCustomer(int id, Consumer<Customer> makeCustomerHappyBehaviours) {
 Customer c = DataBase.getCustomerWithId(id);
 makeCustomerHappyBehaviours.accept(c); // can accept differnt behaviours
   }
}


public class BankOfTokoyOnlineBanking extends OnlineBanking {
        // bank of tokoy's template
public void myTemplate() { new BankOfTokoyOnlineBanking().processCustomer(1337, 
                       (Customer c) -> System.out.println("Hello " + c.getName()));
 }
}

Restructure  7 - Chain Of Responsibility

This is so StraitForward with the help of Function interface discussed in previous article. 


public String processLineA() {
     UnaryOperator<String> headerProcessing = (String text) -> "From Raoul Alan: " + text;
    
     UnaryOperator<String> spellCheckerProcessing = (String text) -> 
                                                     text.replaceAll("labda", "lambda");
    
     Function<String, String> pipeline = headerProcessing.andThen(spellCheckerProcessing);
    
     String result = pipeline.apply("sexy?!!");
     return result;
}

Restructure 8 - Factory Pattern

we have discussed this previously in method reference.


final static Map<String, Supplier<Product>> map = new HashMap<>();
static {
 map.put("loan", Loan::new);
 map.put("stock", Stock::new);
 map.put("bond", Bond::new);
}
 
public static Product createProduct(String name){
 Supplier<Product> p = map.get(name);
 if(p != null)  {
      return p.get();
 }
 throw new IllegalArgumentException("No such product " + name);
}

Restructure 9 - Debug

Lamda's Stream is a flow/pipleline process. then How do we debug them step by step like what we did previously adding those break point in application ? We use peek()


List<Integer> result = numbers.stream()
  .peek(x -> System.out.println("from stream: " + x))
  .map(x -> x + 17)
  .peek(x -> System.out.println("after map: " + x))
  .filter(x -> x % 2 == 0)
  .peek(x -> System.out.println("after filter: " + x))
  .limit(3)
  .peek(x -> System.out.println("after limit: " + x))
  .collect(toList());

from stream: 3
after map: 20
after filter: 20
after limit: 20
from stream: 4
after map: 21
from stream: 5
after map: 22
after filter: 22
after limit: 22



No comments:

Post a Comment

Add Loading Spinner for web request.

when web page is busily loading. normally we need to add a spinner for the user to kill their waiting impatience. Here, 2 steps we need to d...