Functional Programming Made Easy in JAVA & C#

9489b8d6f2dbdc3e7d26b8702143b86e?s=47 Yoan
April 30, 2020

Functional Programming Made Easy in JAVA & C#

Let's demystify together what is Functional Programming (FP) !!!
We will deep dive into FP paradigms like monads, pure functions, high order functions, and much more.
We will share why and how to apply those in Object Oriented languages like java (with vavr) & C# (with language-ext).

We will demonstrate how to write Functional code that is:
* More robust
* Easier to read
* Easier to maintain

This session is built as a mix of theory and practice. You will be able to use your favorite IDE to practice through code katas.

To be able to practice, please clone one of the below repository on your machine before the event :
* Repo for java friends : https://github.com/ythirion/vavr-kata.git

9489b8d6f2dbdc3e7d26b8702143b86e?s=128

Yoan

April 30, 2020
Tweet

Transcript

  1. @algrison @yot88 FUNCTIONAL PROGRAMMING MADE EASY IN JAVA & C#

    SOFTWARE CRAFTSMANSHIP LUXEMBOURG 30 April at 5PM on ZOOM Free registration : HTTPS://BIT.LY/2RMKPFD
  2. WHO ARE WE ? YOAN THIRION Agile/craft coach freelance Software

    craftsman yoan-thirion.com ALEXANDRE GRISON Tech Lead, Coach, Solutions Architect, Software Craftsman at BIL Loves #Clojure grison.me
  3. @algrison @yot88

  4. None
  5. @algrison @yot88 FUNCTIONAL PROGRAMMING IS ALL ABOUT FUNCTIONS Lazy evaluation

    Pure functions (no side effect) Lambda functions (anonymous) Higher order functions Composition Closures (returning functions from functions) Currying & partial application Immutability Pattern matching Recursion
  6. @algrison @yot88 PURE FUNCTIONS Pure functions don’t refer to any

    global state. The same inputs will always get the same output. Combined with immutable data types this means you can be sure the same inputs will give the same outputs.
  7. CONTEXT Source : http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html#just-what-is-a-functor,-really? Here’s a simple value And we

    know how to apply a function to this value: Let’s extend this by saying that any value can be in a context. For now you can think of a context as a box that you can put a value in Now when you apply a function to this value, you'll get different results depending on the context. This is the idea that Functors, Applicatives, Monads, Arrows etc are all based on. The Maybe data type defines two related contexts
  8. FUNCTORS A functor is any type that defines how map

    works. When a value is wrapped in a box, you can’t apply a normal function to it This is where map comes in! map knows how to apply functions to values that are wrapped in a box.
  9. FUNCTORS Here’s what is happening behind the scenes when we

    write Here’s what is happening behind the scenes when we try to map a function on an empty box
  10. FUNCTORS What happens when you apply a function to a

    list? lists are functors too
  11. FUNCTORS What happens when you apply a function to another

    function? When you use map on a function, you're just doing function composition! functions are also functors In Java with vavr map is called compose or andThen In C# with language-ext is called Compose
  12. APPLICATIVES Applicatives are like functors, except that not only the

    value is being wrapped in a context, but the function to apply to it also !
  13. MONADS Functors apply a function to a wrapped value Monads

    apply a function that takes a value and returns a wrapped value. Applicatives apply a wrapped function to a wrapped value
  14. MONADS What if we feed it with a wrapped value?

    This is where bind also called flatMap or chain comes in! If you pass in Nothing it’s even simpler
  15. MONADS We can chain calls to bind

  16. MONADS by example Another example: user types a path then

    we want to load the file content and display it
  17. @algrison @yot88 FP IN JAVA / C#

  18. @algrison @yot88 FP in Java / C# Already a lot

    of things in : With the Stream API : since Java 8 LinQ : since .NET 3.5 (2007) Some cool new features in the latest versions of the languages.
  19. @algrison @yot88 C# 8 Pattern matching Record types in 8.x

    Immutable data types Free equality Easier pure functions
  20. None
  21. @algrison @yot88 2 LIBS TO RESCUE US

  22. @algrison @yot88 Vavr is an object-functional language extension to Java,

    aiming at reducing lines of code and increase code quality. It provides persistent collections, functional abstractions for error handling, concurrent programming, and much more. Vavr fuses the power of object-oriented programming with the elegance and robustness of FP. Including a feature-rich, immutable, persistent collection library that smoothly integrates with Java's standard collections. We’re using it at BIL in a lot of µServices Integration with Spring Data & Jackson It is awesome This library uses and abuses the features of C# to provide a functional- programming 'base class library' that, if you squint, can look like extensions to the language itself. The desire here is to make programming in C# much more reliable and to make the engineer's inertia flow in the direction of declarative and functional code rather than imperative. https://github.com/vavr-io/vavr https://github.com/louthy/language-ext
  23. @algrison @yot88 Maven <dependency> <groupId>io.vavr</groupId> <artifactId>vavr</artifactId> <version>0.10.2</version> </dependency> Gradle compile

    group: 'io.vavr', name: 'vavr', version: '0.10.2' Nuget Lombok for C#
  24. @algrison @yot88 Monads (io.vavr.control): λ Option λ Either λ Try

    λ Validation APIs (io.vavr): λ Tuples (0 -> 8) λ Functions (0 -> 8) λ CheckedFunctions (0 -> 8)
  25. @algrison @yot88 978-0521663502 Purely functional collections (io.vavr.collection):

  26. @algrison @yot88 Performance characteristics of Vavr Collections:

  27. @algrison @yot88 MAIN FEATURES Immutable collections Useful monads Records Validation

  28. @algrison @yot88 ONE MORE THING No more out parameters LINQ

    mapping
  29. @algrison @yot88 PARTIAL APPLICATION Partial application allows us to create

    new function from an existing one by setting some arguments.
  30. @algrison @yot88 CURRYING Currying is the same as converting a

    function that takes n arguments into n functions taking a single argument each. F(x, y, z) = z(x(y)) Curried: F(x, y, z) = F(y) { F(z) { F(x) } } To get the full application: F(x)(y)(z)
  31. @algrison @yot88 MEMOIZATION Memoization is some kind of caching if

    you memoize a function, it will be only executed once for a specific input
  32. @algrison @yot88 OPTION Option is a monadic container with additions

    Represents an optional value : None / Some(value) map, flatMap, filter, peek, … Map, Bind, Filter, Do, …
  33. @algrison @yot88 TRY Try is a monadic container which represents

    a computation that may either throw an exception or successfully completes map, flatMap, filter, mapTry, peek, recover, onFailure, onSuccess, … Map, Bind, Filter, Do, Match, IfFail, IfSucc, …
  34. @algrison @yot88 HANDS ON : LET’S WRITE CODE

  35. @algrison @yot88 BEFORE WE START One namespace to rule them

    all using static LanguageExt.Prelude;
  36. @algrison @yot88 HOW TO ? Clone the repository in your

    favorite language : Java : https://github.com/ythirion/vavr-kata.git C# : https://github.com/ythirion/language-ext-kata.git Let’s start with (stay on master branch) OptionExercises TryExercises RealLifeExample Java pre-requesite : Install lombok plugin here
  37. REAL LIFE EXAMPLE Imperative, not safe, redundant checks, …

  38. REAL LIFE EXAMPLE Try, use a context, chain calls ->

    pipeline
  39. @algrison @yot88 await REAL LIFE EXAMPLE

  40. @algrison @yot88 WHAT ABOUT PERFORMANCES ?

  41. @algrison @yot88 Generate fake users by using Bogus Map data

    with LINQ Map data with Language-Ext https://github.com/ythirion/fp-cs-benchmark C#
  42. @algrison @yot88 With 100 Users With 10_000 Users 3.5 x

    faster with LINQ 2.94 x faster with LINQ C#
  43. @algrison @yot88 Generate fake users at startup Map data with

    Java Stream API Map data with Vavr (directly from Spring Data) https://github.com/agrison/fp-java-benchmark Java
  44. 5 000 requests with 100 Users Similar performance Finished 5000

    requests Concurrency Level: 100 Time taken for tests: 4.931 seconds Complete requests: 5000 Failed requests: 0 Requests per second: 1014.05 [#/sec] (mean) Time per request: 98.614 [ms] (mean) Time per request: 0.986 [ms] (mean, across all concurrent requests) Transfer rate: 6834.96 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 1.2 0 12 Processing: 9 97 14.3 98 193 Waiting: 9 97 14.3 98 193 Total: 9 98 13.8 98 193 Percentage of the requests served within a certain time (ms) 50% 98 66% 99 75% 99 80% 100 90% 102 95% 103 98% 105 99% 107 100% 193 (longest request) Java Finished 5000 requests Concurrency Level: 100 Time taken for tests: 4.889 seconds Complete requests: 5000 Failed requests: 0 Requests per second: 1022.66 [#/sec] (mean) Time per request: 97.784 [ms] (mean) Time per request: 0.978 [ms] (mean, across all concurrent requests) Transfer rate: 6893.00 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 1.1 0 12 Processing: 8 96 15.0 97 188 Waiting: 8 96 15.0 97 188 Total: 9 97 14.6 97 188 Percentage of the requests served within a certain time (ms) 50% 97 66% 98 75% 99 80% 99 90% 100 95% 100 98% 101 99% 182 100% 188 (longest request) Vavr Finished 5000 requests Concurrency Level: 100 Time taken for tests: 7.510 seconds Complete requests: 5000 Failed requests: 0 Requests per second: 665.76 [#/sec] (mean) Time per request: 150.205 [ms] (mean) Time per request: 1.502 [ms] (mean, across all concurrent requests) Transfer rate: 0.00 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.0 0 0 Processing: 1 1 3.8 1 52 Waiting: 0 0 0.0 0 0 Total: 1 1 3.8 1 52 Percentage of the requests served within a certain time (ms) 50% 1 66% 1 75% 1 80% 1 90% 1 95% 2 98% 23 99% 26 100% 52 (longest request) Linq Finished 5000 requests Concurrency Level: 100 Time taken for tests: 6.928 seconds Complete requests: 5000 Failed requests: 0 Requests per second: 721.67 [#/sec] (mean) Time per request: 138.567 [ms] (mean) Time per request: 1.386 [ms] (mean, across all concurrent requests) Transfer rate: 0.00 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.0 0 1 Processing: 1 1 3.3 1 49 Waiting: 0 0 0.0 0 0 Total: 1 1 3.3 1 49 Percentage of the requests served within a certain time (ms) 50% 1 66% 1 75% 1 80% 1 90% 1 95% 2 98% 3 99% 26 100% 49 (longest request) Lang-ext ab -c 100 -n 5000 -r localhost:port/path
  45. 10 000 requests with 1 000 Users Similar performance Finished

    10000 requests Concurrency Level: 1000 Time taken for tests: 9.942 seconds Complete requests: 10000 Failed requests: 0 Requests per second: 1005.87 [#/sec] (mean) Time per request: 994.162 [ms] (mean) Time per request: 0.994 [ms] (mean, across all concurrent requests) Transfer rate: 6779.81 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 9 27.3 0 130 Processing: 36 931 173.1 979 1183 Waiting: 36 931 173.1 979 1182 Total: 137 940 147.5 979 1183 Percentage of the requests served within a certain time (ms) 50% 979 66% 982 75% 986 80% 988 90% 991 95% 993 98% 995 99% 1004 100% 1183 (longest request) Java Finished 10000 requests Concurrency Level: 1000 Time taken for tests: 9.898 seconds Complete requests: 10000 Failed requests: 0 Requests per second: 1010.31 [#/sec] (mean) Time per request: 989.795 [ms] (mean) Time per request: 0.990 [ms] (mean, across all concurrent requests) Transfer rate: 6809.72 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 8 25.5 0 122 Processing: 37 928 175.4 979 1352 Waiting: 31 928 175.5 978 1352 Total: 142 936 151.0 979 1352 Percentage of the requests served within a certain time (ms) 50% 979 66% 980 75% 981 80% 982 90% 983 95% 985 98% 986 99% 1156 100% 1352 (longest request) Vavr Finished 10000 requests Concurrency Level: 1000 Time taken for tests: 16.666 seconds Complete requests: 10000 Failed requests: 0 Requests per second: 600.04 [#/sec] (mean) Time per request: 1666.564 [ms] (mean) Time per request: 1.667 [ms] (mean, across all concurrent requests) Transfer rate: 0.00 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 15.1 0 1088 Processing: 1 1 3.7 1 100 Waiting: 0 0 0.0 0 0 Total: 1 2 15.6 1 1090 Percentage of the requests served within a certain time (ms) 50% 1 66% 1 75% 1 80% 1 90% 1 95% 2 98% 4 99% 25 100% 1090 (longest request) Finished 10000 requests Concurrency Level: 1000 Time taken for tests: 16.827 seconds Complete requests: 10000 Failed requests: 0 Requests per second: 594.27 [#/sec] (mean) Time per request: 1682.738 [ms] (mean) Time per request: 1.683 [ms] (mean, across all concurrent requests) Transfer rate: 0.00 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 18.6 0 1081 Processing: 1 1 3.4 1 88 Waiting: 0 0 0.0 0 0 Total: 1 2 18.9 1 1084 Percentage of the requests served within a certain time (ms) 50% 1 66% 1 75% 1 80% 1 90% 1 95% 2 98% 3 99% 25 100% 1084 (longest request) ab -c 1000 -n 10000 -r localhost:port/path Linq Lang-ext
  46. @algrison @yot88 WHAT DO YOU THINK ABOUT IT ?

  47. How & why we use it @BIL In µServices &

    batches. To make code: safer implicit less verbose
  48. @algrison @yot88 TO GO FURTHER • Functional Core, Imperative shell

    • You can play with true FP languages on JVM or .NET F# on .NET Clojure, Kotlin, Scala Scott Wlaschin F# guru Paul Louth lang-ext Rich Hickey Clojure yoda Daniel Dietrich Vavr
  49. Option.of(“THANK YOU”) YOAN THIRION Agile/craft coach freelance Software craftsman yoan-thirion.com

    ALEXANDRE GRISON Tech Lead, Coach, Solutions Architect, Software Craftsman at BIL Loves #Clojure grison.me