Thursday 25 June 2015

Strategy Pattern in Java 8

These are two examples on how to implement a Strategy pattern design using Java 8 functional style together with Cyclops pattern matching and Hamcrest libraries.

PrintDependingOnInput method is a strategy that will System.println some message based on the log passed.

AddPrefix is another strategy that will add a prefix to a message based on the message content.

package com.marco.patternmatching; 

 

import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.startsWith;
import static org.hamcrest.core.AllOf.allOf;
import java.util.ArrayList;
import java.util.List;
import com.aol.cyclops.matcher.builders.Matching; 

 

public class FunctionalStrategy {

  public static void main(String[] args) {
     List<String> toTest = new ArrayList<>();
     toTest.add("INFO everything is fine");
     toTest.add("WARN something weird happened");
     toTest.add("ERROR NullPointerException");
     toTest.add("ERROR IOException");
     
     toTest.stream().forEach(FunctionalStrategy::printDependingOnInput);

     System.out.println("--------------------");

     List<String> messages = new ArrayList<>();
     messages.add("everything is fine");
     messages.add("something weird happened");
     messages.add("NullPointerException");
     messages.add("IOException");

     messages.stream().map(FunctionalStrategy::addPrefix).forEach(System.out::println);
  }

        
  public static void printDependingOnInput(String log) {

     Matching
        .when().isMatch(startsWith("INFO"))
                   .thenConsume(System.out::println)
        .when().isMatch(startsWith("WARN"))
                   .thenConsume(message -> System.out.println("Found one warning : " + message))
        .when().isMatch(allOf(startsWith("ERROR"), containsString("NullPointerException")))
                   .thenConsume(message -> System.err.println(message))
        .when().isMatch(allOf(startsWith("ERROR"), containsString("IOException")))
                   .thenConsume(message -> System.err.println(message + " Retrying a couple of times"))
        .match(log);

   }

   public static String addPrefix(String log) {

     return Matching
        .when().isMatch(allOf(not(containsString("Exception")), not(containsString("weird"))))
                    .thenApply(message -> "INFO " + message)
        .when().isMatch(containsString("weird"))
                    .thenApply(message -> "WARN " + message)
        .when().isMatch(containsString("Exception"))
                    .thenApply(message -> "ERROR " + message)
        .match(log).get();

  }
}


Nice and clean ;)

Tuesday 16 June 2015

Java 8 and how Optional removes the need for == null

I was confused initially when the Optional concept entered the Java world.
I was wondering how the hell can Optional remove the need to check for null? At some point I will need to use optional.isPresent() before using whatever is inside. So what's the point to replace == null with isPresent()?


The main concept to keep in mind is that Optional is a monad and as a monad contains map(), flatmap(), filter() and other methods that can be used directly against the optional instance.


Here, with the following simple code, I hope I will clarify a bit more the power of java.util.Optional.

In this example we have a list of logs and we want to apply 3 different operations based on the the type of log (INFO, ERROR, WARN).


package com.marco.optional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class TestOptional {

        public static void main(String[] args) {
                List<Optional<String>> logs = new ArrayList<Optional<String>>();
                logs.add(Optional.ofNullable("INFO:: some info here 1"));
                logs.add(Optional.ofNullable("INFO:: some info here 2"));
                logs.add(Optional.ofNullable("ERROR:: some error here 3"));
                logs.add(Optional.ofNullable("INFO:: some info here 4"));
                logs.add(Optional.ofNullable("WARN:: some info here 5"));
                logs.add(Optional.ofNullable(null));
                logs.add(Optional.ofNullable("INFO:: some info here 7"));
                logs.add(Optional.ofNullable("WARN:: some info here 8"));

                for (Optional<String> singleLog : logs) {
                        printErrors(singleLog);
                        printInfos(singleLog);
                        printWarnOnlyNumber(singleLog);
                }

        }

        public static void printErrors(Optional<String> singleLog) {
                singleLog.filter(entry -> entry.startsWith("ERROR")).ifPresent(System.out::println);
        }

        public static void printInfos(Optional<String> singleLog) {
                singleLog.filter(entry -> entry.startsWith("INFO")).ifPresent(System.out::println);
        }

        public static void printWarnOnlyNumber(Optional<String> singleLog) {
                singleLog.filter(entry -> entry.startsWith("WARN"))

                          .map(warn -> warn.substring(warn.length() - 1))

                          .ifPresent(System.out::println);
        }
}

Output :


INFO:: some info here 1
INFO:: some info here 2
ERROR:: some error here 3
INFO:: some info here 4
5
INFO:: some info here 7
8


No == null and no if

Optional takes care of it for you ;)

Friday 12 June 2015

Java 8, easier with Cyclops : Try


Cyclops is another promising open source library from John McClean in AOL, that aims to extends and simplify Java 8 functionality.

One of its feature is Try that offers an alternative way to manage exception handling.

Imagine you have a method that load files from some location :

private List<File> loadFiles() { 
     return Lists.newArrayList(new File("somePath_one"), new File("somePath_two"));
} 

Many things could go wrong there, file does not exist, network is down, etc.
 
Traditionally, we could have manage exceptions surrounding the loadFiles() method with try and catch and handle each exception within a catch statement.

Cyclops Try made things easier and cleaner :

Try.withCatch(this::loadFiles, Exception.class)


    .onFail(FileNotFoundException.class, e -> System.err.println("Something specific to do here if file does not exists" + e))


    .onFail(IOException.class, e -> System.err.println("Maybe retry a couple of times before dropping the operation" + e))


    .forEach(System.out::println);

Based on the exception, different functions can be triggered.

http://media.giphy.com/media/U0uowJVj7ewO4/giphy.gif

Thursday 11 June 2015

10 team building tips

1) Good Morning


http://media.giphy.com/media/RbVOveSAHkk2A/giphy.gif

When you enter in the office, before sitting on your desk, smile and say good morning to the team. Yes, E V E R Y day.

2) Listen when someone is talking to you.

http://media.giphy.com/media/kwNSxdqqutsEE/giphy.gif

When a team member is talking to you, look him in the eyes and show interest in what he is saying.

3) Give space, build trust


http://media.giphy.com/media/HdsLiowsPuoso/giphy.gif

Let team member fail sometimes and repair from their failures.
You may be always right, but who cares?! Other people need to learn to fail and take responsibilities.


4) Connect


http://media.giphy.com/media/LPAohuvTif0ek/giphy.gif

Go and take a coffee with each person in the team separately.

5) Congratulate


http://media.giphy.com/media/IAFlOwj4XsNlm/giphy.gif

When someone does something good, tell her/him!

6) Keep your personal problems out of work.


 http://media.giphy.com/media/dIDae8s93pave/giphy.gif

Don't shout at people because your last evening was bad.

7) Do pair programming


http://media.giphy.com/media/ggKMDmjkGZ5ZK/giphy.gif

Great way to share knowledge and build solid work relationships.

8)  Feedback


http://media.giphy.com/media/ql89wsWoAgTAI/giphy.gif

Do code reviews without sounding the king of the programming universe. Explain in a calm and friendly tone whatever you want to say.

9) Have lunch together


http://media.giphy.com/media/PvBnBEr7CUUDK/giphy.gif

If possible go regularly to lunch with as many team members as possible.


10) See you tomorrow


http://media.giphy.com/media/77ggDHDT372j6/giphy.gif

When you leave in the evening, if you are not the last person in the team left, say goodbye.


Thursday 4 June 2015

Memoize functions in java 8

Memoization is not a grammar error,  memoization is an optimization technique used primarily to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again.

http://en.wikipedia.org/wiki/Memoization

I will explain it with a simple example.

Context :

Table PIZZA, columns ID, NAME

We have a java function called "hereThePizzaGiveMeTheId" where you pass a String representing a pizza name and it will return the correspondent id retrieved from the DB.

Function<String, Integer> hereThePizzaGiveMeTheId = name -> {

            int pizzaId = -1;


            System.out.println("Select ID from PIZZA where name = '" + name + "'");

            pizzaId = pizzaDao.get(name);


            return pizzaId;

        };

Now, if I call this function with the same pizza name I will hit the DB each time :

        System.out.println(hereThePizzaGiveMeTheId.apply("Margherita"));
        System.out.println(hereThePizzaGiveMeTheId.apply("Margherita"));
        System.out.println(hereThePizzaGiveMeTheId.apply("Margherita"));
        System.out.println(hereThePizzaGiveMeTheId.apply("Margherita"));
        System.out.println(hereThePizzaGiveMeTheId.apply("Four Season"));
        System.out.println(hereThePizzaGiveMeTheId.apply("Four Season"));
        System.out.println(hereThePizzaGiveMeTheId.apply("Four Season"));
        System.out.println(hereThePizzaGiveMeTheId.apply("Four Season"));
        System.out.println(hereThePizzaGiveMeTheId.apply("Gorgonzola and figs"));
        System.out.println(hereThePizzaGiveMeTheId.apply("Gorgonzola and figs"));
        System.out.println(hereThePizzaGiveMeTheId.apply("Gorgonzola and figs"));
        System.out.println(hereThePizzaGiveMeTheId.apply("Gorgonzola and figs"));


OUTPUT:


Select ID from PIZZA where name = 'Margherita'
1
Select ID from PIZZA where name = 'Margherita'
1
Select ID from PIZZA where name = 'Margherita'
1
Select ID from PIZZA where name = 'Margherita'
1
Select ID from PIZZA where name = 'Four Season'
2
Select ID from PIZZA where name = 'Four Season'
2
Select ID from PIZZA where name = 'Four Season'
2
Select ID from PIZZA where name = 'Four Season'
2
Select ID from PIZZA where name = 'Gorgonzola and figs'
3
Select ID from PIZZA where name = 'Gorgonzola and figs'
3
Select ID from PIZZA where name = 'Gorgonzola and figs'
3
Select ID from PIZZA where name = 'Gorgonzola and figs'
3



Fantastic, but I don't want to run that function every time, if I already know the result based on the pizza name.
So, lets memoize (cache) the result of that function.

First we create a generic method that wraps a function into another function that will behave the same as the input one, but will check if the result is already computed : 

public static <X, Y> Function<X, Y> memoise(Function<X, Y> fn) {

        Map<X, Y> pp = new ConcurrentHashMap<X, Y>();

        return (a) -> pp.computeIfAbsent(a, fn);

    }


 Then we wrap our "hereThePizzaGiveMeTheId"  function :

Function<String, Integer> memoziedHereThePizzaGiveMeTheId = memoise(hereThePizzaGiveMeTheId);
 
Lastly, we call again the same logic as before, but using the new memoziedHereThePizzaGiveMeTheId function :

      
        System.out.println(memoziedHereThePizzaGiveMeTheId.apply("Margherita"));

        System.out.println(memoziedHereThePizzaGiveMeTheId.apply("Margherita"));

        System.out.println(memoziedHereThePizzaGiveMeTheId.apply("Margherita"));

        System.out.println(memoziedHereThePizzaGiveMeTheId.apply("Margherita"));

        System.out.println(memoziedHereThePizzaGiveMeTheId.apply("Four Season"));

        System.out.println(memoziedHereThePizzaGiveMeTheId.apply("Four Season"));

        System.out.println(memoziedHereThePizzaGiveMeTheId.apply("Four Season"));

        System.out.println(memoziedHereThePizzaGiveMeTheId.apply("Four Season"));

        System.out.println(memoziedHereThePizzaGiveMeTheId.apply("Gorgonzola and figs"));

        System.out.println(memoziedHereThePizzaGiveMeTheId.apply("Gorgonzola and figs"));

        System.out.println(memoziedHereThePizzaGiveMeTheId.apply("Gorgonzola and figs"));

        System.out.println(memoziedHereThePizzaGiveMeTheId.apply("Gorgonzola and figs"));



OUTPUT:

Select ID from PIZZA where name = 'Margherita'
1
1
1
1
Select ID from PIZZA where name = 'Four Season'
2
2
2
2
Select ID from PIZZA where name = 'Gorgonzola and figs'
3
3
3
3







We will hit the DB only if the result of the function is not already present in the map.

That's it.

p.s.

Gorgonzola and figs is a fantastic pizza :