Upload
david-schmitz
View
218
Download
2
Embed Size (px)
Citation preview
#JavalandJavaslang @koenighotze
java slang
The Monad strikes back
#JavalandJavaslang @koenighotze
David Schmitz - koenighotze
Senacor Technologies Principal Architect
Programmer! Thats me coding Scala
#JavalandJavaslang @koenighotze
Whats in it for you?
Functional programming is hip
How Javaslang helped us
Live Code - OMG!
Becaus
e of B
eamer
#JavalandJavaslang @koenighotze
Functors, applicatives, monads
stay home
#JavalandJavaslang @koenighotze
Code that is easier to reason about
#JavalandJavaslang @koenighotze
Side-effects are eviltry { int i = 1/0; } catch (Throwable t) { }Exceptions are goto-statements
:(
#JavalandJavaslang @koenighotze
Referential Transparency
Math.random();
Math.max(1, 2);
Math.random();
Math.max(1, 2);
Pure functions are a Good ThingTm
:(
#JavalandJavaslang @koenighotze
Thinking in values
Immutability
Performance
Safety
#JavalandJavaslang @koenighotze
In a nutshell, think about what to code
not how to code
#JavalandJavaslang @koenighotze
Enter java Eight
(a) -> a + 2
list.stream().filter
Excitement
#JavalandJavaslang @koenighotze
Try filtering all invalid users from
a list of users
#JavalandJavaslang @koenighotze
Excitement?untilusers.stream() .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}) .collect(Collectors.toList());
#JavalandJavaslang @koenighotze
import static javaslang.API.*;
#JavalandJavaslang @koenighotze
What well coverImmutable collections
Some functional sugar
Pattern matching
Property based testing
Circuit breaker
#JavalandJavaslang @koenighotze
Before we get to the details
Lets fix that ugly code
#JavalandJavaslang @koenighotze
Fixing Things.users.stream() .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}) .collect(Collectors.toList());
#JavalandJavaslang @koenighotze
Functional collectionsList.ofAll(users) .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}) .collect(Collectors.toList());
#JavalandJavaslang @koenighotze
No need for CollectorsList.ofAll(users) .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}) .collect(Collectors.toList());
#JavalandJavaslang @koenighotze
No need for CollectorsList.ofAll(users) .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}); .collect(Collectors.toList());
#JavalandJavaslang @koenighotze
Wrapping ExceptionsList.ofAll(users) .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}); .collect(Collectors.toList());
#JavalandJavaslang @koenighotze
Wrapping ExceptionsList.ofAll(users) .filter(user ->
Try.of(user::validateAddress) .getOrElse(false) ); } catch (IllegalStateException ex) { return ); .collect(Collectors.toList();
#JavalandJavaslang @koenighotze
List.ofAll(users) List.filter(user -> Try.of(user::validateAddress) .getOrElse(false));
#JavalandJavaslang @koenighotze
immutable Collections
#JavalandJavaslang @koenighotze
Mutable Collections are Evil
Returning void == Side-Effect!
interface Collection { void clear(); }
interface Collection { void clear(); }
#JavalandJavaslang @koenighotze
java.util.Collections
Collections .unmodifiableList(list); .add()
#JavalandJavaslang @koenighotze
java.util.Collections
Collections .unmodifiableList(list) .add();
#JavalandJavaslang @koenighotzePainting by Gustav Courbet
java.lang.UnsupportedOperationException at java.util.Collections$UnmodifiableCollection.add(Collections.java:1055) at java.util.stream.AbstractPipeline. (AbstractPipeline.java:203) at java.util.stream.ReferencePipeline. (ReferencePipeline.java:94)
#JavalandJavaslang @koenighotze
Javaslang Collections
https://cdn.infoq.com/statics_s2_20170314-0434/resource/news/2016/11/the-road-to-javaslang-3/en/resources/1infoq-version2.0-library.png
#JavalandJavaslang @koenighotze
Functional data structures
Immutable
Referentially transparent
Persistent
#JavalandJavaslang @koenighotze
heroes = List.of("Han", "Luke")
Cons@661 Han T
Cons@666 Luke ()
heroes
Effectively immutable
#JavalandJavaslang @koenighotze
Cons@661 Han T
Cons@666 Luke ()
heroes
Cons@662 Ben Tmore
more = heroes.prepend("Ben")
Effectively immutable
#JavalandJavaslang @koenighotze
droids = TreeSet.of( "C3PO", "R2D2", "K2SO" )
Node@676
Node@679 Node@681K2SO
() ()C3PO
() ()R2D2
Effectively immutable
#JavalandJavaslang @koenighotze
droids.add("Chopper");
Effectively immutable
#JavalandJavaslang @koenighotze
Node@689
Node@691
() Node@694
() ()Chopper
Node@676
Node@679 Node@681K2SO
() ()C3PO
() ()R2D2
Effectively immutable
#JavalandJavaslang @koenighotze
old == new
Checking for updates?
#JavalandJavaslang @koenighotze
Streams are glorified iterators
Stream jdk = Stream.of("a", B");
jdk.map(String::toUpperCase); jdk.map(String::toLowerCase);
#JavalandJavaslang @koenighotzePainting by Gustav Courbet
java.lang.IllegalStateException: stream has already been operated upon or closed at java.util.stream.AbstractPipeline. (AbstractPipeline.java:203) at java.util.stream.ReferencePipeline. (ReferencePipeline.java:94)
#JavalandJavaslang @koenighotze
Stream slang = Stream.of("a", "B"); slang.map(String::toUpperCase); // A,B slang.map(String::toLowerCase); // a,b
Javaslang streams
#JavalandJavaslang @koenighotze
Javaslang StreamsStream slang = Stream.of("a", "B"); slang.map(String::toUpperCase) .take(2); slang.map(String::toLowerCase) .take(2);
#JavalandJavaslang @koenighotze
Javaslang StreamsStream slang = Stream.of("a", "B"); slang.map(String::toUpperCase) .take(2);// A,B slang.map(String::toLowerCase) .take(2);// a,b
#JavalandJavaslang @koenighotze
Better performance Less unexpected behaviour
#Devoxx #Javaslang @koenighotze
functional Sugar
#JavalandJavaslang @koenighotze
find a user and, if an address is
available, fetch the users street
#JavalandJavaslang @koenighotze
Cascading Pile of ShameUser user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) {
return address.getStreet(); } }
#JavalandJavaslang @koenighotze
optional?
Optional opt = Optional.ofNullable(user);
if (optional.isPresent()) { User user = optional.get(); }
#JavalandJavaslang @koenighotze
And now, young coder...
you will die.
#JavalandJavaslang @koenighotze
#JavalandJavaslang @koenighotze
map or flatmap There is no isPresent()
#JavalandJavaslang @koenighotze
optional or option?
Optional
#JavalandJavaslang @koenighotze
optional or option?
Option
Some None
#JavalandJavaslang @koenighotze
optional or option?
Option
Some None
Value
Iterable
#JavalandJavaslang @koenighotze
optional or option?
Option
Some None
Value
Iterable
#JavalandJavaslang @koenighotze
optional or option?
Option
Some None
Value
Iterable
Serializable
#JavalandJavaslang @koenighotze
An option is like a Gift Box
NoneSome
#JavalandJavaslang @koenighotze
Map opens the Gift Box
MapSome Some
( )->
#JavalandJavaslang @koenighotze
nothing from nothing
( )->
MapNone None
#JavalandJavaslang @koenighotze
Fixing the Pile of ShameUser user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) {
return address.getStreet(); } }
#JavalandJavaslang @koenighotze
option all the ThingsUser user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) {
return address.getStreet(); } }
#JavalandJavaslang @koenighotze
option all the ThingsOption user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) {
return address.getStreet(); } }
#JavalandJavaslang @koenighotze
option all the ThingsOption user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) {
return address.getStreet(); } }
#JavalandJavaslang @koenighotze
option all the ThingsOption user = repo.findOne("id"); user.flatMap(User::getAddress) Address address = user.getAddress(); if (null != address) {
return address.getStreet(); } }
Option user = repo.findOne("id"); user.flatMap(User::getAddress) Address address = user.getAddress(); if (null != address) {
return address.getStreet(); } } Option getAddress()
#JavalandJavaslang @koenighotze
option all the ThingsOption user = repo.findOne("id"); user.flatMap(User::getAddress) Address address = user.getAddress(); if (null != address) {
return address.getStreet(); } }
#JavalandJavaslang @koenighotze
option all the ThingsOption user = repo.findOne("id"); user.flatMap(User::getAddress) Address address = user.getAddress(); .map(Address::getStreet)
return address.getStreet(); } }
#JavalandJavaslang @koenighotze
repo.findOne("id") .flatMap(User::getAddress) .map(Address::getStreet) .getOrElse("");
#JavalandJavaslang @koenighotze
option.of(value) .map(nested code) == understandable story
#JavalandJavaslang @koenighotze
working with legacy code
#JavalandJavaslang @koenighotze
Nice validation Codepublic static String check(String iban){ if (validationMagic(iban)) { return iban; }
throw new IllegalArgumentException(Peng); }
#JavalandJavaslang @koenighotze
Awesome WTF Code String iban; try { iban = check(AL47); } catch (IllegalArgumentException ex) { iban = ""; }
#JavalandJavaslang @koenighotze
From Exceptions to options
String iban = lift(Iban::check) .apply("AL47...") .getOrElse("");
#JavalandJavaslang @koenighotze
From Exceptions to options
String iban = lift(Iban::check) .apply("AL47...") .getOrElse("");
#JavalandJavaslang @koenighotze
Wrapping Exceptions with Try
Try.of(() -> stuffToDo())
#JavalandJavaslang @koenighotze
Wrapping Exceptions with Try
FailureException
SuccessResult
Try.of(() -> stuffToDo())
#JavalandJavaslang @koenighotze
Exceptions to options with Try
Try.of(() -> check("AL..")) .getOrElse("")
#JavalandJavaslang @koenighotze
Exceptions to options with Try
Try.of(() -> check("AL..")) .getOrElse("")
#JavalandJavaslang @koenighotze
Lifting and Try-ing reduce exception handling
clutter and side-effects
#JavalandJavaslang @koenighotze
Structural Decomposition
#JavalandJavaslang @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
#JavalandJavaslang @koenighotze
Pattern Matching Basics
Match(expression) .of(cases)
#JavalandJavaslang @koenighotze
Cases map patterns to function
Case(pattern, function)
#JavalandJavaslang @koenighotze
Example Patterns
$() wildcard pattern $(foo) equals pattern isIn(a, b) conditional pattern
#JavalandJavaslang @koenighotze
Classic HTTP Handlingif (OK.equals(res.getStatusCode())) { return res.getBody(); }
return emptyList();
#JavalandJavaslang @koenighotze
HTTP Handling Fixed
*Note: some type details missing
Match(res.getStatusCode()) .of( Case($(OK), res.getBody()), Case($(), emptyList()) );
#JavalandJavaslang @koenighotze
Match(res.getStatusCode()) .of( Case($(OK), res.getBody()), Case($(), emptyList()) );
HTTP Handling Fixed
*Note: some type details missing
OK or anything else
#JavalandJavaslang @koenighotze
HTTP Handling Fixed
*Note: some type details missing
Match(res.getStatusCode()) .of( Case($(OK), res.getBody()), Case($(), emptyList()) );
#JavalandJavaslang @koenighotze
HTTP Handling Fixed
*Note: some type details missing
Match(res.getStatusCode()) .of( Case($(OK), res.getBody()), Case($(), emptyList()) );
#JavalandJavaslang @koenighotze
HTTP Handling Fixed
Match(res.getStatusCode()) .of( Case($(OK), res.getBody()), Case($(), emptyList()) );
*Note: some type details missing
#JavalandJavaslang @koenighotze
Matching a Try
public Try fetchFromUrl() { }
#JavalandJavaslang @koenighotze
Matching a Try
Match(fetchFromUrl()) .of( Case(Success($()), identity()), Case(Failure($()), emptyList()) );
#JavalandJavaslang @koenighotze
Matching a Try
Match(fetchFromUrl()) .of( Case(Success($()), identity()), Case(Failure($()), emptyList()) );
#JavalandJavaslang @koenighotze
Matching a Try
Match(fetchFromUrl()) .of( Case(Success($()), identity()), Case(Failure($()), emptyList()) );
#JavalandJavaslang @koenighotze
Presto
Match(fetchFromUrl()) .of( Case(Success($()), identity()), Case(Failure($()), emptyList()) );
#JavalandJavaslang @koenighotze
Pattern matching replaces complex if-then-else sequences
with clear expressions
#JavalandJavaslang @koenighotze
property tEST
#JavalandJavaslang @koenighotze
property Based - The idea
Describe the arguments
Describe the results
Let the olde computer prove you wrong
#JavalandJavaslang @koenighotze
Javaslang property test
Property.def(Add works") .forAll(Generated Data) .suchThat(Checked Function) .check() .assertIsSatisfied();
#JavalandJavaslang @koenighotze
Javaslang property test
Property.def(Add works") .forAll(integer(), integer()) .suchThat( (a,b)-> calc.add(a, b) == a + b) .check() .assertIsSatisfied();
#JavalandJavaslang @koenighotze
Running tests2017-03-21 10:45:59.913 INFO 45701 --- FrameworkServlet '': initialization started 2017-03-21 10:45:59.925 INFO 45701 --- FrameworkServlet '': initialization completed in 12 ms Storing User@217b0952[username=rwxbeoigyesbeqqz,email=W`[email protected], Storing User@4e6280de[username=vptafghfwuwwrwall,[email protected],,, Storing User@2fca282c[username=qmhkjdtvbtjzfciwcceqgzfznzkhhcokiyoipdefbr,[email protected]. Storing User@64d53f0d[publicId=e9d7a121-9f23-483a-828a-f9e3045fc297,username=unflrpvztxtmi...
...
Storing User@1b10f60e[publicId=6f084c18-415c-42c4-b1a8-00c5c1fc9e67,username=xwhpdpjowirsmjym... Storing User@4b916cc2[publicId=a2b9db2c-0189-4fe8-843d-e709ef3886fa,username=yxdidpexnayyjpzo...
Should not go boom: OK, passed 1000 tests in 3719 ms.
#JavalandJavaslang @koenighotze
FailuresShould not go boom: Falsified after 23 passed tests in 3005 ms.
java.lang.AssertionError: Expected satisfied check result but was Falsified(,
sample = (, ?,
fzqlbkljxhfrghllzcthvgqiglaabihkzgsqwgfcichamyonmayiewwsfwmwntzvozqqydkqillhpyi, [email protected]))
#JavalandJavaslang @koenighotze
Why property Based tests?Declarative, infinit test cases
Have you tested for all characters even for ?
Have you tested usernames like ?
#JavalandJavaslang @koenighotze
functional resilience
#JavalandJavaslang @koenighotze
Circuit breaker one-o-one
Consumer Backend
#JavalandJavaslang @koenighotze
Fallback
Resilience decorator
Circuit breaker one-o-oneClosed
Open
Half-Open
Consumer
#JavalandJavaslang @koenighotze
Resilience decorator
Circuit breaker one-o-oneClosed
Open
Half-Open
Consumer
Fallback
#JavalandJavaslang @koenighotze
Fallback
Resilience decorator
Circuit breaker one-o-oneClosed
Open
Half-Open
Consumer
#JavalandJavaslang @koenighotze
Fallback
Resilience decorator
Circuit breaker one-o-oneClosed
Open
Half-Open
Consumer
#JavalandJavaslang @koenighotze
Resilience For J
BackendConsumerBackend Service
Resilience decorator
Circuit Breaker
Retry
Cache
#JavalandJavaslang @koenighotze
Option fetchBoard(String id) { result = restTemplate.getForEntity();
return Match(result.getStatusCode()) .option(); }
flakey functions
#JavalandJavaslang @koenighotze
Option fetchBoard(String id) { result = restTemplate.getForEntity();
return Match(result.getStatusCode()) .option(); }
flakey functions
#JavalandJavaslang @koenighotze
Decorators.ofCheckedFunction(db::fetchBoard) .withCircuitBreaker(circuitBreaker) .decorate();
Decorating a function
#JavalandJavaslang @koenighotze
Try.of(() -> decorated.apply(stationId)) .getOrElse(Option.of(empty()))
Functional resilience
#JavalandJavaslang @koenighotze
final celebration
#JavalandJavaslang @koenighotze
HashMap.of("Foo", "Bar", "Qux", "Baz")
Tuple.of("Foo", 1)
String help = TODO("Implement me")
Javaslang offers much more
#JavalandJavaslang @koenighotze
Javaslang offers much more
#JavalandJavaslang @koenighotze
So, is this is the mother of all free
lunches?
#JavalandJavaslang @koenighotze
What are the drawbacks?
#JavalandJavaslang @koenighotze
What are the drawbacks?
count(Collection-libs)
>
count(Logging-libs)
#JavalandJavaslang @koenighotze
What are the drawbacks?Option.of(foo) .map .filter .flatMap .map .flatMap .getOrElse(null)
NOT a drawback!
#JavalandJavaslang @koenighotze
Wrapping up
Slick, stable, consistent API
Object-functional advantages now
Complex(?)
Version 3 coming soon!
#JavalandJavaslang @koenighotze
RESISTTHE TYRANNY OF THE
COLLECTIONS FRAMEWORKJOIN THE RESISTANCE!
#JavalandJavaslang @koenighotze
thank you
david.schmitz at senacor.com