Slide 1

Slide 1 text

@algrison @yot88 FUNCTIONAL PROGRAMMING MADE EASY IN JAVA & C# SOFTWARE CRAFTSMANSHIP LUXEMBOURG 30 April at 5PM on ZOOM Free registration : HTTPS://BIT.LY/2RMKPFD

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

@algrison @yot88

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

@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

Slide 6

Slide 6 text

@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.

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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.

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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 !

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

MONADS We can chain calls to bind

Slide 16

Slide 16 text

MONADS by example Another example: user types a path then we want to load the file content and display it

Slide 17

Slide 17 text

@algrison @yot88 FP IN JAVA / C#

Slide 18

Slide 18 text

@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.

Slide 19

Slide 19 text

@algrison @yot88 C# 8 Pattern matching Record types in 8.x Immutable data types Free equality Easier pure functions

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

@algrison @yot88 2 LIBS TO RESCUE US

Slide 22

Slide 22 text

@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

Slide 23

Slide 23 text

@algrison @yot88 Maven io.vavr vavr 0.10.2 Gradle compile group: 'io.vavr', name: 'vavr', version: '0.10.2' Nuget Lombok for C#

Slide 24

Slide 24 text

@algrison @yot88 Monads (io.vavr.control): λ Option λ Either λ Try λ Validation APIs (io.vavr): λ Tuples (0 -> 8) λ Functions (0 -> 8) λ CheckedFunctions (0 -> 8)

Slide 25

Slide 25 text

@algrison @yot88 978-0521663502 Purely functional collections (io.vavr.collection):

Slide 26

Slide 26 text

@algrison @yot88 Performance characteristics of Vavr Collections:

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

@algrison @yot88 ONE MORE THING No more out parameters LINQ mapping

Slide 29

Slide 29 text

@algrison @yot88 PARTIAL APPLICATION Partial application allows us to create new function from an existing one by setting some arguments.

Slide 30

Slide 30 text

@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)

Slide 31

Slide 31 text

@algrison @yot88 MEMOIZATION Memoization is some kind of caching if you memoize a function, it will be only executed once for a specific input

Slide 32

Slide 32 text

@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, …

Slide 33

Slide 33 text

@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, …

Slide 34

Slide 34 text

@algrison @yot88 HANDS ON : LET’S WRITE CODE

Slide 35

Slide 35 text

@algrison @yot88 BEFORE WE START One namespace to rule them all using static LanguageExt.Prelude;

Slide 36

Slide 36 text

@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

Slide 37

Slide 37 text

REAL LIFE EXAMPLE Imperative, not safe, redundant checks, …

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

@algrison @yot88 await REAL LIFE EXAMPLE

Slide 40

Slide 40 text

@algrison @yot88 WHAT ABOUT PERFORMANCES ?

Slide 41

Slide 41 text

@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#

Slide 42

Slide 42 text

@algrison @yot88 With 100 Users With 10_000 Users 3.5 x faster with LINQ 2.94 x faster with LINQ C#

Slide 43

Slide 43 text

@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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

@algrison @yot88 WHAT DO YOU THINK ABOUT IT ?

Slide 47

Slide 47 text

How & why we use it @BIL In µServices & batches. To make code: safer implicit less verbose

Slide 48

Slide 48 text

@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

Slide 49

Slide 49 text

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