Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Javaslang @ Devoxx

733 views

Published on

@Devoxx 2016

This talk will introduce you to Javaslang, a library that borrows heavily from Scala and applies Scala's ideas to plain old Java. We will cover some of the productivity enhancements and syntactic sugar that Javaslang offers, such as pattern matching aka. structural composition, value types and functional data types. Javaslang can be a building block for functional business code, that is easy to maintain and understand.

Published in: Engineering
  • Login to see the comments

Javaslang @ Devoxx

  1. 1. #Devoxx #Javaslang @koenighotze JΛVΛSLΛNGFunctional Sugar For Java
  2. 2. #Devoxx #Javaslang @koenighotze Senacor Technologies Programmer! That’s me coding Scala David Schmitz / @koenighotze Senacor Technologies Programmer! That’s me coding Scala
  3. 3. #Devoxx #Javaslang @koenighotze What’s in it for you? Functional programming is hip How Javaslang helped us Examples, Code!
  4. 4. #Devoxx #Javaslang @koenighotze Functors, applicatives, monads and friends stay home
  5. 5. #Devoxx #Javaslang @koenighotze Code that is easier to reason about
  6. 6. #Devoxx #Javaslang @koenighotze Side-effects are evil try { int i = 1/0; } catch (Throwable t) { … } Exceptions are goto-statements :(
  7. 7. #Devoxx #Javaslang @koenighotze Referential Transparency Math.random(); Math.max(1, 2); Math.random(); Math.max(1, 2); Pure functions are a Good ThingTm :(
  8. 8. #Devoxx #Javaslang @koenighotze Thinking in Values Immutability Performance Safety
  9. 9. #Devoxx #Javaslang @koenighotze In a nutshell, think about “what to code“ not “how to code”
  10. 10. #Devoxx #Javaslang @koenighotze Enter Java 8 (a) -> a + 2 list.stream().filter… Excitement…
  11. 11. #Devoxx #Javaslang @koenighotze “Try filtering all invalid users from a list of users”
  12. 12. #Devoxx #Javaslang @koenighotze Excitement?…until users.stream() .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}) .collect(Collectors.toList());
  13. 13. #Devoxx #Javaslang @koenighotzePainting by Gustav Courbet
  14. 14. #Devoxx #Javaslang @koenighotze import static javaslang.API.*; +
  15. 15. #Devoxx #Javaslang @koenighotze What we’ll cover Immutable collections Some functional sugar Pattern matching
  16. 16. #Devoxx #Javaslang @koenighotze Before we get to the details… Let’s fix that ugly code
  17. 17. #Devoxx #Javaslang @koenighotze Fixing Things…. users.stream() .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}) .collect(Collectors.toList());
  18. 18. #Devoxx #Javaslang @koenighotze Functional collections List.ofAll(users) .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}) .collect(Collectors.toList());
  19. 19. #Devoxx #Javaslang @koenighotze No need for Collectors List.ofAll(users) .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}) .collect(Collectors.toList());
  20. 20. #Devoxx #Javaslang @koenighotze No need for Collectors List.ofAll(users) .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}); .collect(Collectors.toLis t());
  21. 21. #Devoxx #Javaslang @koenighotze Wrapping Exceptions List.ofAll(users) .filter(user -> { try { return user.validate(); } catch (Exception ex) { return false; }}); .collect(Collectors.toLis t());
  22. 22. #Devoxx #Javaslang @koenighotze Wrapping Exceptions List.ofAll(users) .filter(user -> Try.of(user::validateAddress) .getOrElse(false) ); } catch (IllegalStateException ex) { return ); .collect(Collectors.toList();
  23. 23. #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”
  24. 24. #Devoxx #Javaslang @koenighotze Immutable Collections Image by Douglas Muth, https://flic.kr/p/acFwxG
  25. 25. #Devoxx #Javaslang @koenighotze Mutable Collections are Evil Returning void == Side-Effect! interface Collection<E> { … void clear(); } interface Collection<E> { … void clear(); }
  26. 26. #Devoxx #Javaslang @koenighotze Easy solution? Collections Collections .unmodifiableList(list); .add("BUMM");
  27. 27. #Devoxx #Javaslang @koenighotze Easy solution? Collections Collections .unmodifiableList(list) .add("BUMM");
  28. 28. #Devoxx #Javaslang @koenighotze
  29. 29. #Devoxx #Javaslang @koenighotze Javaslang Collections List<~> t = List.of(“F95”); List<~> t2 = t.append(withName(“FCK”)); F95 /t
  30. 30. #Devoxx #Javaslang @koenighotze Immutable List<~> t = List.of(“F95”); List<~> t2 = t.prepend(“FCK”); F95 /t FCKt2
  31. 31. #Devoxx #Javaslang @koenighotze List<~> t = List.of(“F95”); List<~> t2 = t.prepend(“FCK”); F95 / FCK t t2 Persistent and Efficient
  32. 32. #Devoxx #Javaslang @koenighotze Streams are glorified Iterators Stream<String> jdk = Stream.of("a", “B"); jdk.map(String::toUpperCase); jdk.map(String::toLowerCase);
  33. 33. #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)
  34. 34. #Devoxx #Javaslang @koenighotze Javaslang Streams Stream<String> slang = Stream.of("a", "B"); slang.map(String::toUpperCase); // “A”,“B” slang.map(String::toLowerCase); // “a”,“b”
  35. 35. #Devoxx #Javaslang @koenighotze Javaslang Streams Stream<String> slang = Stream.of("a", "B"); slang.map(String::toUpperCase) .take(2); slang.map(String::toLowerCase) .take(2);
  36. 36. #Devoxx #Javaslang @koenighotze Javaslang Streams Stream<String> slang = Stream.of("a", "B"); slang.map(String::toUpperCase) .take(2);// “A”,“B” slang.map(String::toLowerCase) .take(2);// “a”,“b”
  37. 37. #Devoxx #Javaslang @koenighotze Functional data structures improve performance and reduce the chance of unexpected behaviour
  38. 38. #Devoxx #Javaslang @koenighotze Functional Sugar
  39. 39. #Devoxx #Javaslang @koenighotze “Find a user and, if an address is available, fetch the user’s street”
  40. 40. #Devoxx #Javaslang @koenighotze Cascading Pile of Shame User user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) { return address.getStreet(); } }
  41. 41. #Devoxx #Javaslang @koenighotze We’ve got java.util.Optional Optional<User> opt = Optional.ofNullable(user); if (optional.isPresent()) { … }
  42. 42. #Devoxx #Javaslang @koenighotze
  43. 43. #Devoxx #Javaslang @koenighotze Please stop using Optional#isPresent()
  44. 44. #Devoxx #Javaslang @koenighotze An Option is like a Gift Box NoneSome
  45. 45. #Devoxx #Javaslang @koenighotze Map opens the Gift Box Map Some Some ( )->
  46. 46. #Devoxx #Javaslang @koenighotze Nothing from Nothing ( )-> Map None None
  47. 47. #Devoxx #Javaslang @koenighotze Optional or Option? Optional
  48. 48. #Devoxx #Javaslang @koenighotze Optional or Option? Option Some None
  49. 49. #Devoxx #Javaslang @koenighotze Optional or Option? Option Some None Value Iterable
  50. 50. #Devoxx #Javaslang @koenighotze Optional or Option? Option Some None Value Iterable
  51. 51. #Devoxx #Javaslang @koenighotze Optional or Option? Option Some None Value Iterable Serializable
  52. 52. #Devoxx #Javaslang @koenighotze Fixing the Pile of Shame User user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) { return address.getStreet(); } }
  53. 53. #Devoxx #Javaslang @koenighotze Option all the Things User user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) { return address.getStreet(); } }
  54. 54. #Devoxx #Javaslang @koenighotze Option all the Things Option<User> user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) { return address.getStreet(); } }
  55. 55. #Devoxx #Javaslang @koenighotze Option all the Things Option<User> user = repo.findOne("id"); if (user != null) { Address address = user.getAddress(); if (null != address) { return address.getStreet(); } }
  56. 56. #Devoxx #Javaslang @koenighotze Option all the Things Option<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()
  57. 57. #Devoxx #Javaslang @koenighotze Option all the Things Option<User> user = repo.findOne("id"); user.flatMap(User::getAddress) Address address = user.getAddress(); if (null != address) { return address.getStreet(); } }
  58. 58. #Devoxx #Javaslang @koenighotze Option all the Things Option<User> user = repo.findOne("id"); user.flatMap(User::getAddress) Address address = user.getAddress(); .map(Address::getStreet) return address.getStreet(); } }
  59. 59. #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”
  60. 60. #Devoxx #Javaslang @koenighotze Option and map transform nested code into an understandable story
  61. 61. #Devoxx #Javaslang @koenighotze Working with legacy code Painting by Eero Järnefelt
  62. 62. #Devoxx #Javaslang @koenighotze Nice Validation Code public static String check(String iban){ if (validationMagic(iban)) { return iban; } throw new IllegalArgumentException(“Peng”); }
  63. 63. #Devoxx #Javaslang @koenighotze Awesome WTF Code String iban; try { iban = check("AL47"); } catch (IllegalArgumentException ex) { iban = ""; }
  64. 64. #Devoxx #Javaslang @koenighotze From Exceptions to Options String iban = lift(Iban::check) .apply("AL47...") .getOrElse("");
  65. 65. #Devoxx #Javaslang @koenighotze From Exceptions to Options String iban = lift(Iban::check) .apply("AL47...") .getOrElse("");
  66. 66. #Devoxx #Javaslang @koenighotze Wrapping Exceptions with Try Try.of(() -> stuffToDo())
  67. 67. #Devoxx #Javaslang @koenighotze Wrapping Exceptions with Try Failure Exception Success Result Try.of(() -> stuffToDo())
  68. 68. #Devoxx #Javaslang @koenighotze Exceptions to Options with Try Try.of(() -> check("AL..")) .getOrElse("")
  69. 69. #Devoxx #Javaslang @koenighotze Exceptions to Options with Try Try.of(() -> check("AL..")) .getOrElse("")
  70. 70. #Devoxx #Javaslang @koenighotze Lifting and Try-ing reduce exception handling clutter and side-effects
  71. 71. #Devoxx #Javaslang @koenighotze Structural Decomposition Image by Arend, https://flic.kr/p/pkBe4g
  72. 72. #Devoxx #Javaslang @koenighotze Classic HTTP Handling if (OK.equals(res.getStatusCode())) { return res.getBody(); } return emptyList();
  73. 73. #Devoxx #Javaslang @koenighotze (?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:.[a-z0-9!#$%&'*+/=? ^_`{|}~-]+)*|"(?:[x01-x08x0bx0cx0e-x1fx21x23- x5bx5d-x7f]|[x01-x09x0bx0cx0e-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-x08x0bx0cx0e-x1fx21- x5ax53-x7f]|[x01-x09x0bx0cx0e-x7f])+)]) Pattern Matching Basics
  74. 74. #Devoxx #Javaslang @koenighotze Pattern Matching Basics Match(expression) .of(cases)
  75. 75. #Devoxx #Javaslang @koenighotze Cases map functions to patterns Case(pattern, function)
  76. 76. #Devoxx #Javaslang @koenighotze Example Patterns $() wildcard pattern $(“foo”) equals pattern isIn(“a”, “b”) conditional pattern
  77. 77. #Devoxx #Javaslang @koenighotze HTTP Handling Fixed *Note: some type details missing Match(res.getStatusCode()) .of(
 Case($(OK), res.getBody()),
 Case($(), emptyList())
 );
  78. 78. #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
  79. 79. #Devoxx #Javaslang @koenighotze HTTP Handling Fixed *Note: some type details missing Match(res.getStatusCode()) .of(
 Case($(OK), res.getBody()),
 Case($(), emptyList())
 );
  80. 80. #Devoxx #Javaslang @koenighotze HTTP Handling Fixed *Note: some type details missing Match(res.getStatusCode()) .of(
 Case($(OK), res.getBody()),
 Case($(), emptyList())
 );
  81. 81. #Devoxx #Javaslang @koenighotze HTTP Handling Fixed Match(res.getStatusCode()) .of(
 Case($(OK), res.getBody()),
 Case($(), emptyList())
 ); *Note: some type details missing
  82. 82. #Devoxx #Javaslang @koenighotze Matching a Try public Try<…> fetchFromUrl(…) { … }
  83. 83. #Devoxx #Javaslang @koenighotze Matching a Try Match(fetchFromUrl(“…”)) .of( Case(Success($()), identity()), Case(Failure($()), emptyList()) );
  84. 84. #Devoxx #Javaslang @koenighotze Matching a Try Match(fetchFromUrl(“…”)) .of( Case(Success($()), identity()), Case(Failure($()), emptyList()) );
  85. 85. #Devoxx #Javaslang @koenighotze Matching a Try Match(fetchFromUrl(“…”)) .of( Case(Success($()), identity()), Case(Failure($()), emptyList()) );
  86. 86. #Devoxx #Javaslang @koenighotze Presto! Match(fetchFromUrl(“…”)) .of( Case(Success($()), identity()), Case(Failure($()), emptyList()) );
  87. 87. #Devoxx #Javaslang @koenighotze Pattern matching replaces complex if- then-else sequences with clear expressions
  88. 88. #Devoxx #Javaslang @koenighotze HashMap.of("Foo", "Bar", "Qux", "Baz") .bimap(String::toLowerCase, String::toUpperCase) .get("qux"); // BAZ Javaslang offers much more
  89. 89. #Devoxx #Javaslang @koenighotze Javaslang offers much more Tuple.of("Foo", 1) .map((s, i) -> Tuple.of(s + "Bar", i + 5)) // “FooBar”, 6
  90. 90. #Devoxx #Javaslang @koenighotze Javaslang offers much more
  91. 91. #Devoxx #Javaslang @koenighotze So, is this is the mother of all free lunches?
  92. 92. #Devoxx #Javaslang @koenighotze What are the drawbacks?
  93. 93. #Devoxx #Javaslang @koenighotze What are the drawbacks? count(Collection-libs) > count(Logging-libs)
  94. 94. #Devoxx #Javaslang @koenighotze What are the drawbacks? Option.of(foo) .map .filter .flatMap
  95. 95. #Devoxx #Javaslang @koenighotze Wrapping up Slick, stable, consistent API Object-functional Complex(?) Version 3 in 2017
  96. 96. #Devoxx #Javaslang @koenighotze .iohttp:// Do you want to know more?
  97. 97. #Devoxx #Javaslang @koenighotze Thank You! <david.schmitz@senacor.com>

×