javaslang @ devoxx

97
#Devoxx #Javaslang @koenighotze JΛVΛSLΛNG Functional Sugar For Java

Upload: david-schmitz

Post on 15-Feb-2017

348 views

Category:

Engineering


0 download

TRANSCRIPT

Page 1: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

JΛVΛSLΛNGFunctional Sugar For Java

Page 2: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Senacor Technologies Programmer!

That’s me coding Scala

David Schmitz / @koenighotzeSenacor Technologies

Programmer! That’s me coding Scala

Page 3: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

What’s in it for you?Functional programming is hip

How Javaslang helped us

Examples, Code!

Page 4: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Functors, applicatives,

monads and friends stay home

Page 5: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Code that is easier to reason about

Page 6: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Side-effects are eviltry { int i = 1/0; } catch (Throwable t) { … }Exceptions are goto-statements

:(

Page 7: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Referential TransparencyMath.random();

Math.max(1, 2);

Math.random();

Math.max(1, 2);

Pure functions are a Good ThingTm

:(

Page 8: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Thinking in ValuesImmutability

Performance

Safety

Page 9: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

In a nutshell, think about “what to code“

not “how to code”

Page 10: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Enter Java 8(a) -> a + 2

list.stream().filter…

Excitement…

Page 11: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

“Try filtering all invalid users from a list of users”

Page 12: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Excitement?…untilusers.stream() .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}) .collect(Collectors.toList());

Page 13: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotzePainting by Gustav Courbet

Page 14: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

import static javaslang.API.*;

+

Page 15: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

What we’ll coverImmutable collections

Some functional sugar

Pattern matching

Page 16: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Before we get to the details… Let’s fix that ugly code

Page 17: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Fixing Things….users.stream() .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}) .collect(Collectors.toList());

Page 18: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Functional collectionsList.ofAll(users) .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}) .collect(Collectors.toList());

Page 19: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

No need for CollectorsList.ofAll(users) .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}) .collect(Collectors.toList());

Page 20: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

No need for CollectorsList.ofAll(users) .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}); .collect(Collectors.toList());

Page 21: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Wrapping ExceptionsList.ofAll(users) .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}); .collect(Collectors.toList());

Page 22: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Wrapping ExceptionsList.ofAll(users) .filter(user ->

Try.of(user::validateAddress) .getOrElse(false) ); } catch (IllegalStateException ex) { return ); .collect(Collectors.toList();

Page 23: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

List.ofAll(users) List.filter(user -> Try.of(user::validateAddress) .getOrElse(false));

“Try filtering all invalid users from a list of users”

Page 24: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Immutable Collections Image by Douglas Muth, https://flic.kr/p/acFwxG

Page 25: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Mutable Collections are Evil

Returning void == Side-Effect!

interface Collection<E> { … void clear(); }

interface Collection<E> { … void clear(); }

Page 26: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Easy solution? Collections

Collections .unmodifiableList(list); .add("BUMM");

Page 27: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Easy solution? Collections

Collections .unmodifiableList(list) .add("BUMM");

Page 28: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Page 29: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Javaslang CollectionsList<~> t = List.of(“F95”);

List<~> t2 = t.append(withName(“FCK”));

F95 /t

Page 30: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

ImmutableList<~> t = List.of(“F95”);

List<~> t2 = t.prepend(“FCK”);

F95 /t

FCKt2

Page 31: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

List<~> t = List.of(“F95”);

List<~> t2 = t.prepend(“FCK”);

F95 /

FCK

t

t2

Persistent and Efficient

Page 32: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Streams are glorified IteratorsStream<String> jdk = Stream.of("a", “B");

jdk.map(String::toUpperCase); jdk.map(String::toLowerCase);

Page 33: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

java.lang.IllegalStateException: stream has already been operated upon or closed at java.util.stream.AbstractPipeline.<init>(AbstractPipeline.java:203) at java.util.stream.ReferencePipeline.<init>(ReferencePipeline.java:94) at java.util.stream.ReferencePipeline$StatelessOp.<init>(ReferencePipeline.java:618) at java.util.stream.ReferencePipeline$3.<init>(ReferencePipeline.java:187) at java.util.stream.ReferencePipeline.map(ReferencePipeline.java:186)

Page 34: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Javaslang StreamsStream<String> slang = Stream.of("a", "B"); slang.map(String::toUpperCase); // “A”,“B” slang.map(String::toLowerCase); // “a”,“b”

Page 35: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Javaslang StreamsStream<String> slang = Stream.of("a", "B"); slang.map(String::toUpperCase) .take(2); slang.map(String::toLowerCase) .take(2);

Page 36: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Javaslang StreamsStream<String> slang = Stream.of("a", "B"); slang.map(String::toUpperCase) .take(2);// “A”,“B” slang.map(String::toLowerCase) .take(2);// “a”,“b”

Page 37: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Functional data structures improve performance and

reduce the chance of unexpected behaviour

Page 38: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Functional Sugar

Page 39: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

“Find a user and, if an address is available, fetch

the user’s street”

Page 40: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Cascading Pile of ShameUser user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) {

return address.getStreet(); } }

Page 41: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

We’ve got java.util.Optional

Optional<User> opt = Optional.ofNullable(user);

if (optional.isPresent()) { … }

Page 42: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Page 43: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Please stop usingOptional#isPresent()

Page 44: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

An Option is like a Gift Box

NoneSome

Page 45: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Map opens the Gift Box

MapSome Some

( )->

Page 46: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Nothing from Nothing( )->

MapNone None

Page 47: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Optional or Option?

Optional

Page 48: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Optional or Option?

Option

Some None

Page 49: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Optional or Option?

Option

Some None

Value

Iterable

Page 50: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Optional or Option?

Option

Some None

Value

Iterable

Page 51: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Optional or Option?

Option

Some None

Value

Iterable

Serializable

Page 52: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Fixing the Pile of ShameUser user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) {

return address.getStreet(); } }

Page 53: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Option all the ThingsUser user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) {

return address.getStreet(); } }

Page 54: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Option all the ThingsOption<User> user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) {

return address.getStreet(); } }

Page 55: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Option all the ThingsOption<User> user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) {

return address.getStreet(); } }

Page 56: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Option all the ThingsOption<User> user = repo.findOne("id"); user.flatMap(User::getAddress) Address address = user.getAddress(); if (null != address) {

return address.getStreet(); } }

Option<User> user = repo.findOne("id"); user.flatMap(User::getAddress) Address address = user.getAddress(); if (null != address) {

return address.getStreet(); } } Option<Address> getAddress()

Page 57: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Option all the ThingsOption<User> user = repo.findOne("id"); user.flatMap(User::getAddress) Address address = user.getAddress(); if (null != address) {

return address.getStreet(); } }

Page 58: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Option all the ThingsOption<User> user = repo.findOne("id"); user.flatMap(User::getAddress) Address address = user.getAddress(); .map(Address::getStreet)

return address.getStreet(); } }

Page 59: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

repo.findOne("id") .flatMap(User::getAddress) .map(Address::getStreet) .getOrElse("");

“Find a user and, if an address is available, fetch the user’s street”

Page 60: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Option and map transform nested code into an

understandable story

Page 61: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Working with legacy codePainting by Eero Järnefelt

Page 62: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Nice Validation Codepublic static String check(String iban){ if (validationMagic(iban)) { return iban; }

throw new IllegalArgumentException(“Peng”); }

Page 63: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Awesome WTF Code String iban; try { iban = check("AL47"); } catch (IllegalArgumentException ex) { iban = ""; }

Page 64: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

From Exceptions to Options

String iban = lift(Iban::check) .apply("AL47...") .getOrElse("");

Page 65: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

From Exceptions to Options

String iban = lift(Iban::check) .apply("AL47...") .getOrElse("");

Page 66: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Wrapping Exceptions with Try

Try.of(() -> stuffToDo())

Page 67: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Wrapping Exceptions with Try

FailureException

SuccessResult

Try.of(() -> stuffToDo())

Page 68: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Exceptions to Options with Try

Try.of(() -> check("AL..")) .getOrElse("")

Page 69: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Exceptions to Options with Try

Try.of(() -> check("AL..")) .getOrElse("")

Page 70: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Lifting and Try-ing reduce exception handling clutter

and side-effects

Page 71: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Structural DecompositionImage by Arend, https://flic.kr/p/pkBe4g

Page 72: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Classic HTTP Handlingif (OK.equals(res.getStatusCode())) { return res.getBody(); }

return emptyList();

Page 73: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

Pattern Matching Basics

Page 74: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Pattern Matching Basics

Match(expression) .of(cases)

Page 75: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Cases map functions to patterns

Case(pattern, function)

Page 76: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Example Patterns

$() wildcard pattern $(“foo”) equals pattern isIn(“a”, “b”) conditional pattern

Page 77: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

HTTP Handling Fixed

*Note: some type details missing

Match(res.getStatusCode()) .of( Case($(OK), res.getBody()), Case($(), emptyList()) );

Page 78: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Match(res.getStatusCode()) .of( Case($(OK), res.getBody()), Case($(), emptyList()) );

HTTP Handling Fixed

*Note: some type details missing

OK or anything else

Page 79: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

HTTP Handling Fixed

*Note: some type details missing

Match(res.getStatusCode()) .of( Case($(OK), res.getBody()), Case($(), emptyList()) );

Page 80: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

HTTP Handling Fixed

*Note: some type details missing

Match(res.getStatusCode()) .of( Case($(OK), res.getBody()), Case($(), emptyList()) );

Page 81: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

HTTP Handling FixedMatch(res.getStatusCode()) .of( Case($(OK), res.getBody()), Case($(), emptyList()) );

*Note: some type details missing

Page 82: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Matching a Try

public Try<…> fetchFromUrl(…) { … }

Page 83: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Matching a TryMatch(fetchFromUrl(“…”)) .of( Case(Success($()), identity()), Case(Failure($()), emptyList()) );

Page 84: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Matching a TryMatch(fetchFromUrl(“…”)) .of( Case(Success($()), identity()), Case(Failure($()), emptyList()) );

Page 85: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Matching a TryMatch(fetchFromUrl(“…”)) .of( Case(Success($()), identity()), Case(Failure($()), emptyList()) );

Page 86: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Presto!Match(fetchFromUrl(“…”)) .of( Case(Success($()), identity()), Case(Failure($()), emptyList()) );

Page 87: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Pattern matching replaces complex if-then-else sequences

with clear expressions

Page 88: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

HashMap.of("Foo", "Bar", "Qux", "Baz") .bimap(String::toLowerCase, String::toUpperCase) .get("qux"); // BAZ

Javaslang offers much more

Page 89: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Javaslang offers much moreTuple.of("Foo", 1) .map((s, i) -> Tuple.of(s + "Bar", i + 5)) // “FooBar”, 6

Page 90: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Javaslang offers much more

Page 91: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

So, is this is the mother of all free lunches?

Page 92: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

What are the drawbacks?

Page 93: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

What are the drawbacks?count(Collection-libs)

>

count(Logging-libs)

Page 94: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

What are the drawbacks?Option.of(foo)

.map

.filter

.flatMap

Page 95: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Wrapping upSlick, stable, consistent API

Object-functional

Complex(?)

Version 3 in 2017

Page 96: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

.iohttp://

Do you want to know more?

Page 97: Javaslang @ Devoxx

#Devoxx #Javaslang @koenighotze

Thank You!<[email protected]>