Functional Programming in Java Code For Maintainability 1 KrkDataLink Kraków 2017-02-15 @marcinstepien www.smart.biz.pl
Marcin Stepien Developer, Consultant @marcinstepien www.smart.biz.pl 2005 www.whenvi.com 2014 2
What is here 3 Code for maintainability Functional Programing intro Object vs Functional Code examples
So the next developer doesn’t hate you Code For Maintainability 4
Maintainable Code 5 Reusable Expressive Clear > Clever Separate of concerns
Closure Lisp Frege kind of Haskell Scala Java 8, Kotlin, Groovy Functional Programming on JVM 6
Functional Programming Java 7
➔ Streams ➔ Lambda expressions ➔ Functions as first class citizens ➔ Functional Interfaces 8 Java 8 FP
➔ No side effects ➔ Final variables ➔ y = f(x) always same y for given x 9 (pure) function
Function<Integer,Integer> increase = x -> x + 1; #parameter -> body 10 Java 8 function
11 Functional interface Function descriptor Predicate<T> T -> boolean Consumer<T> T -> void Function<T,R> T -> R Supplier<T> () -> T UnaryOperator<T> T -> T BinaryOperator<T> (T,T) -> T BiPredicate<L,R> (L,R) -> boolean BiConsumer<T,U> (T,U) -> void BiFunction<T,U,R> (T,U) -> R
#instead of Runnable task = new Runnable() { public void run() { System.out.println(”no arg consumer” ) } } 12 Replace ceremony with Lambda Runnable task = () -> { System.out.println(”no arg consumer” ); };
13 Internal iterators #instead of loops for(String name : names) { System.out.println(name) } #use internal iterators names.forEach(e -> System.out.println(e)) #with method reference names.forEach(System.out::println)
public int getSumOfEvens(List<Integer> nums){ Integer sum = 0; for(Integer num : nums) { if(num != null && num % 2 == 0) { sum += num; } } return sum; } 14 Fight verbosity with streams nums.stream() .filter(Objects::nonNull) .filter( number -> number % 2 == 0) .reduce(0, Integer::sum);
15 Passing functions public int getSum(List<Integer>nums,Predicate<Integer> filter, Bifunction<Integer,Integer,Integer> accumulator) { return nums.stream() .filter(filter) .filter(Objects::nonNull) .reduce(0, accumulator); } Predicate<Integer> isEven = n -> n % 2 == 0; int sum = getSum(numbers, isEven, Integer::sum);
16 Map reduce, lazy evaluation public int getTranactions(List<User> users) { return users.stream() # or parallelStream() .filter(u -> u.isActivated()) .map( u -> u.getTranTotal()) .reduce(0, Integer::sum);} #terminal op public Stream<Integer> get(List<User> users) { #no computation is happening here return users.stream() .filter(u -> u.isActivated()) .map( u -> u.getTranTotal()); }
17 Lazy evaluation, infinite series Stream<Integer> infiniteSeries = Stream.iterate(1, e -> e + 1)
18 Slimmer patterns: decorator ← https://en.wikipedia.org/wiki/Decorator_pattern#Second_example_.28coffee_making_scenario.29 ← Hierarchy of types can be replaced with Function Composition: ● .compose(Function f) ● .andThan(Function f)
19 Function composition class Barista { public static Coffee makeCoffee (Coffee baseCoffee, Function<Coffee, Coffee>... addIngredients) { return Stream.of(addIngredients) .reduce( Function.<Coffee>identity(), //or Function::andThan (addIngr1, addIngr2) -> addIngr1.andThan(addIngr2)) Coffee coffee = Barista.makeCoffee( new Arabica(), Coffee::withMilk, Coffee::withSprinkles));
Object vs Functional 20 ● Imperative ● Mutability ● Lower abstraction ● Reveals impl. details ● Eager by default ● nulls ● Hierarchy of types ● Declarative ● Favors Immutability ● Expressive ● Hides impl. details ● Lazy by default ● Optionals ● Function composition
marcin@smart.biz.pl @marcinstepien 21 Thank you

Functional Programming in Java - Code for Maintainability

  • 1.
    Functional Programming inJava Code For Maintainability 1 KrkDataLink Kraków 2017-02-15 @marcinstepien www.smart.biz.pl
  • 2.
  • 3.
    What is here 3 Codefor maintainability Functional Programing intro Object vs Functional Code examples
  • 4.
    So the nextdeveloper doesn’t hate you Code For Maintainability 4
  • 5.
    Maintainable Code 5 Reusable Expressive Clear> Clever Separate of concerns
  • 6.
    Closure Lisp Frege kindof Haskell Scala Java 8, Kotlin, Groovy Functional Programming on JVM 6
  • 7.
  • 8.
    ➔ Streams ➔ Lambdaexpressions ➔ Functions as first class citizens ➔ Functional Interfaces 8 Java 8 FP
  • 9.
    ➔ No sideeffects ➔ Final variables ➔ y = f(x) always same y for given x 9 (pure) function
  • 10.
    Function<Integer,Integer> increase =x -> x + 1; #parameter -> body 10 Java 8 function
  • 11.
    11 Functional interface Functiondescriptor Predicate<T> T -> boolean Consumer<T> T -> void Function<T,R> T -> R Supplier<T> () -> T UnaryOperator<T> T -> T BinaryOperator<T> (T,T) -> T BiPredicate<L,R> (L,R) -> boolean BiConsumer<T,U> (T,U) -> void BiFunction<T,U,R> (T,U) -> R
  • 12.
    #instead of Runnable task= new Runnable() { public void run() { System.out.println(”no arg consumer” ) } } 12 Replace ceremony with Lambda Runnable task = () -> { System.out.println(”no arg consumer” ); };
  • 13.
    13 Internal iterators #instead ofloops for(String name : names) { System.out.println(name) } #use internal iterators names.forEach(e -> System.out.println(e)) #with method reference names.forEach(System.out::println)
  • 14.
    public int getSumOfEvens(List<Integer>nums){ Integer sum = 0; for(Integer num : nums) { if(num != null && num % 2 == 0) { sum += num; } } return sum; } 14 Fight verbosity with streams nums.stream() .filter(Objects::nonNull) .filter( number -> number % 2 == 0) .reduce(0, Integer::sum);
  • 15.
    15 Passing functions public int getSum(List<Integer>nums,Predicate<Integer>filter, Bifunction<Integer,Integer,Integer> accumulator) { return nums.stream() .filter(filter) .filter(Objects::nonNull) .reduce(0, accumulator); } Predicate<Integer> isEven = n -> n % 2 == 0; int sum = getSum(numbers, isEven, Integer::sum);
  • 16.
    16 Map reduce, lazyevaluation public int getTranactions(List<User> users) { return users.stream() # or parallelStream() .filter(u -> u.isActivated()) .map( u -> u.getTranTotal()) .reduce(0, Integer::sum);} #terminal op public Stream<Integer> get(List<User> users) { #no computation is happening here return users.stream() .filter(u -> u.isActivated()) .map( u -> u.getTranTotal()); }
  • 17.
    17 Lazy evaluation, infiniteseries Stream<Integer> infiniteSeries = Stream.iterate(1, e -> e + 1)
  • 18.
    18 Slimmer patterns: decorator ←https://en.wikipedia.org/wiki/Decorator_pattern#Second_example_.28coffee_making_scenario.29 ← Hierarchy of types can be replaced with Function Composition: ● .compose(Function f) ● .andThan(Function f)
  • 19.
    19 Function composition class Barista{ public static Coffee makeCoffee (Coffee baseCoffee, Function<Coffee, Coffee>... addIngredients) { return Stream.of(addIngredients) .reduce( Function.<Coffee>identity(), //or Function::andThan (addIngr1, addIngr2) -> addIngr1.andThan(addIngr2)) Coffee coffee = Barista.makeCoffee( new Arabica(), Coffee::withMilk, Coffee::withSprinkles));
  • 20.
    Object vs Functional 20 ●Imperative ● Mutability ● Lower abstraction ● Reveals impl. details ● Eager by default ● nulls ● Hierarchy of types ● Declarative ● Favors Immutability ● Expressive ● Hides impl. details ● Lazy by default ● Optionals ● Function composition
  • 21.