JVM Functional Language Battle Orientation in Objects GmbH Weinheimer Str. 68 68309 Mannheim www.oio.de [email protected] Version: 1.0 Ihr Sprecher Falk Sippach (@sippsack) Trainer, Berater, Entwickler Co-Organisator © Orientation in Objects GmbH Architektur Agile Softwareentwicklung Codequalität JVM Functional Language Battle 2 1 Java, XML und Open Source seit 1998 ) Software Factory ) ) Object Rangers ) • Schlüsselfertige Realisierung von Java Software • Unterstützung laufender • Individualsoftware • Pilot- und Migrationsprojekte • Sanierung von Software • Software Wartung • Perfect Match • Rent-a-team • Coaching on the project • Inhouse Outsourcing © Orientation in Objects GmbH Java Projekte ) Competence Center) • Schulungen, Coaching, Weiterbildungsberatung, Train & Solve-Programme • Methoden, Standards und Tools für die Entwicklung von offenen, unternehmensweiten Systemen JVM Functional Language Battle 3 Abstract Funktionale Programmierung soll so viel ausdrucksstärker sein, aber leider ist dieses Programmier-Paradigma nicht ganz kompatibel zu der prozedural- und objektorientierten Denkweise von uns Java-Entwicklern. Anhand eines kleinen Algorithmus werden wir uns verschiedene Lösungen zunächst im klassischem imperativen Java (vor Java 8) und als Vergleich dazu in alternativen JVM-Sprachen (Groovy, Frege, ggf. Scala bzw. JavaScript) anschauen und die verschiedenen Lösungen diskutieren. Herauskommen soll eine saubere und verständlichere Struktur, die zu besser les- und wartbarem Code führen wird. Die gewonnenen Erkenntnisse wollen wir dann letztendlich in Java 8 mittels Streams und Lambda-Ausdrücken umsetzen, so dass jeder Zuhörer die Grundideen der funktionalen Programmierung mit in seine tägliche Arbeit nehmen kann. Es sind keine speziellen Vorkenntnisse in den angesprochenen alternativen Sprachen notwendig, ein solides Verständnis für die Programmiersprache Java genügt. © Orientation in Objects GmbH JVM Functional Language Battle 4 2 Gliederung • Warum von Imperativ zu Funktional? • Sprachwettkampf • Functional Java 8+ © Orientation in Objects GmbH JVM Functional Language Battle Java Groovy Imperativ © Orientation in Objects GmbH 5 Scala Clojure Haskell Frege Funktional JVM Functional Language Battle 6 3 Imperativ: Wie erreiche ich mein Ziel? Funktional: Was will ich erreichen? Foto von tomwieden, CC0 Public Domain Lizenz, https://pixabay.com/de/boule-kugeln-spielen-frankreich-141004/ © Orientation in Objects GmbH Foto von Mohamed Nuzrath, CC0 Public Domain Lizenz, https://pixabay.com/de/kick-martial-arts-krieger-185384/ JVM Functional Language Battle 7 Problemstellung Foto von Manfred Antranias Zimmer, CC0 Public Domain Lizenz, https://pixabay.com/de/aussichtspunkt-fernrohr-ferne-sicht-1021337/ © Orientation in Objects GmbH JVM Functional Language Battle 8 4 Foto von Media Publishing, CC0 Public Domain Lizenz, https://pixabay.com/de/kreditkarte-kredit-karte-bank-geld-1680347/ © Orientation in Objects GmbH JVM Functional Language Battle 9 Prüfsummen-Berechnung Luhn-Algorithmus rein clientseitige Prüfung möglich Luhn-Formel "Modulo 10"-Algorithmus Double-Add-Double-Methode © Orientation in Objects GmbH JVM Functional Language Battle 10 5 Beispiel 4716347184862961 1 4 2 3 7 1 6 3 1 6 9 2 1 12 9 4 4 1 1 2 9 5 1 3 9 6 4 7 1 8 6 8 6 16 4 6 4 6 4 8 6 2 9 6 1 4 8 4 16 1 7 4 3 6 1 7 4 1 14 4 6 6 2 7 8 1 6 4 7 4 1 6 1 1 4 4 6 6 2 7 8 7 1 5 4 6 6 2 7 8 1+3+9+4+6+7+4+7+1+5+4+6+6+2+7+8 80 80 % 10 == 0 gültig 7 © Orientation in Objects GmbH JVM Functional Language Battle 11 Der Kampf beginnt Foto von Marco Montoya, CC0 Public Domain Lizenz, https://pixabay.com/de/ajedrez-k%C3%B6nig-schach-spiel-640386/ © Orientation in Objects GmbH JVM Functional Language Battle 12 6 © Orientation in Objects GmbH JVM Functional Language Battle 13 Java klassisch – Variante 1 Variablen Schleifen Verzweigungen Tiefe der Verschachtelung Zustandsänderungen Reihenfolge der Anweisungen © Orientation in Objects GmbH JVM Functional Language Battle 14 7 Java klassisch – Variante 2 © Orientation in Objects GmbH JVM Functional Language Battle 15 OOP? SRP? DRY? SoC? Wie vs. Was? Lesbarkeit? Testbarkeit? Wartbarkeit? Erweiterbarkeit? Wiederverwendbarkeit? Parallelisierbarkeit? Foto von Christopher Kuszajewski, CC0 Public Domain Lizenz, https://pixabay.com/en/source-code-code-programming-c-583537/ © Orientation in Objects GmbH JVM Functional Language Battle 16 8 Java klassisch mit sprechenden Methodennamen © Orientation in Objects GmbH JVM Functional Language Battle • 17 Folge von Statements – mit Schleifen, Verzweigungen, Sprüngen Typische Eigenschaften • Verändern von Zuständen (Variablen) • Vermischung von Was und Wie (bei Schleifen) • Vorsicht bei Nebenläufigkeit Foto von tomwieden, CC0 Public Domain Lizenz, https://pixabay.com/de/boule-kugeln-spielen-frankreich-141004/ © Orientation in Objects GmbH JVM Functional Language Battle 18 9 Funktional https://twitter.com/mariofusco/status/571999216039542784 © Orientation in Objects GmbH JVM Functional Language Battle 19 Java klassisch – Spaghetti-Code Aufspalten in Ziffern Reihenfolge drehen Jede 2. Ziffer verdoppeln Aufsummieren Validierungsprüfung © Orientation in Objects GmbH JVM Functional Language Battle 20 10 Imperativ Funktional https://twitter.com/mariofusco/status/571999216039542784 © Orientation in Objects GmbH JVM Functional Language Battle 21 Wie sieht es in anderen Sprachen aus? Foto von Marco Montoya, CC0 Public Domain Lizenz, https://pixabay.com/de/ajedrez-k%C3%B6nig-schach-spiel-640386/ © Orientation in Objects GmbH JVM Functional Language Battle 22 11 Groovy • objektorientiert • dynamisch und/statisch typisiert • ausdrucksstarke/prägnante Syntax • sehr gute Integration mit Java (JVM, Bibliotheken, Vererbung, …) • Metaprogrammierung, Closures, Operatorüberladung • Funktionsliterale (Closures) sind First Class Citizens © Orientation in Objects GmbH JVM Functional Language Battle 23 JVM Functional Language Battle 24 Beispiele in Groovy © Orientation in Objects GmbH 12 Viele Beispiele in vielen anderen Sprache später … Foto von Marco Montoya, CC0 Public Domain Lizenz, https://pixabay.com/de/ajedrez-k%C3%B6nig-schach-spiel-640386/ © Orientation in Objects GmbH JVM Functional Language Battle 25 Frege • Haskell for the JVM • rein funktionale Programmiersprache • statisch typisiert mit Typinferenz und Typvariablen • frei von Nebeneffekten • Monaden zur Kapselung von imperativen Konstrukten • Pattern Matching • Typklassen © Orientation in Objects GmbH JVM Functional Language Battle 26 13 toDigits reverse sumDigits divisible10 true false double2nd Funktionskaskade n isValid n = divisibleBy10(sumDigits(double2nd(reverse(toDigits(n))))) JVM Functional Language Battle © Orientation in Objects GmbH 27 Algorithmus in Frege isValid n = divisibleBy10( sumDigits( double2nd( reverse( toDigits(n) Validierungsfunktion Teilbar durch 10? Aufsummieren jede 2. verdoppeln Ziffern umdrehen Aufsplitten in Ziffern ) ) ) ) © Orientation in Objects GmbH JVM Functional Language Battle 28 14 • • • • Typische Eigenschaften Foto von Mohamed Nuzrath, CC0 Public Domain Lizenz, https://pixabay.com/de/kick-martial-arts-krieger-185384/ © Orientation in Objects GmbH • • • • • • • • Immutability pure/seiteneffektfrei referentielle Transparenz Funktionen als First-ClassCitizens Higher-Order Functions Lambdas/Closures Lazy Evaluation Rekursion Pattern Matching Currying/Partial Function Application Function Composition … JVM Functional Language Battle 29 Validierungsfunktion toDigits n | n < 0 = error "n must be 0 or greater" toDigits 0 = [] toDigits n = toDigits (n `div` 10) ++ [(n `mod` 10)] double2nd = zipWith (\x y -> x * y) (cycle [1, 2]) double2nd' = zipWith (*) (cycle [1, 2]) sumDigits xs = sum (concat (map toDigits xs)) sumDigits' = sum . concat . map toDigits divisibleBy10 n = mod n 10 == 0 isValid = divisibleBy10 . sumDigits . double2nd . reverse . toDigits © Orientation in Objects GmbH JVM Functional Language Battle 30 15 Umwandlung in Ziffern toDigits n | n < 0 = error "n must be 0 or greater" toDigits 0 = [] toDigits n = toDigits (n `div` 10) ++ [(n `mod` 10)] double2nd = zipWith (\x y -> x * y) (cycle [1, 2]) Pattern Matching Rekursion double2nd' = zipWith (*) (cycle [1, 2]) sumDigits xs = sum (concat (map toDigits xs)) sumDigits' = sum . concat . map toDigits divisibleBy10 n = mod n 10 == 0 isValid = divisibleBy10 . sumDigits . double2nd . reverse . toDigits © Orientation in Objects GmbH JVM Functional Language Battle 31 Jeweils 2. Ziffer verdoppeln toDigits n | n < 0 = error "n must be 0 or greater" toDigits 0 = [] toDigits n = toDigits (n `div` 10) ++Lazy [(nEvaluation `mod` 10)] Lambda-Ausdruck double2nd = zipWith (\x y -> x * y) (cycle [1, 2]) double2nd' = zipWith (*) (cycle [1, 2]) Persistente Partialxs Function Higher Order Datenstrukturen sumDigits = sum (concat (map Function toDigits xs)) Application sumDigits' = sum . concat . map toDigits divisibleBy10 n = mod n 10 == 0 isValid = divisibleBy10 . sumDigits . double2nd . reverse . toDigits © Orientation in Objects GmbH JVM Functional Language Battle 32 16 Aufsummieren der Ziffern toDigits n | n < 0 = error "n must be 0 or greater" toDigits 0 = [] toDigits n = toDigits (n `div` 10) ++ [(n `mod` 10)] double2nd = zipWith (\x y -> x * y) (cycle [1, 2]) double2nd' = zipWith (*) (cycle [1, 2]) sumDigits xs = sum (concat (map toDigits xs)) sumDigits' = sum . concat . map toDigits Function Function divisibleBy10 n Composition: = mod n 10 == Partial 0 f . g (x) == f(g(x)) Application isValid = divisibleBy10 . sumDigits . double2nd . reverse . toDigits © Orientation in Objects GmbH JVM Functional Language Battle 33 Teilbar durch 10? toDigits n | n < 0 = error "n must be 0 or greater" toDigits 0 = [] toDigits n = toDigits (n `div` 10) ++ [(n `mod` 10)] double2nd = zipWith (\x y -> x * y) (cycle [1, 2]) double2nd' = zipWith (*) (cycle [1, 2]) sumDigits xs = sum (concat (map toDigits xs)) sumDigits' = sum . concat . map toDigits Infix- statt Postfix-Notation divisibleBy10 n = n `mod` 10 == 0 isValid = divisibleBy10 . sumDigits . double2nd . reverse . toDigits © Orientation in Objects GmbH JVM Functional Language Battle 34 17 Vorteile • leicht verständlich • seiteneffektfrei • einfach test-/debugbar • leicht parallelisierbar • modularisierbar und einfach wieder zusammenführbar • hohe Code-Qualität Foto von Mohamed Nuzrath, CC0 Public Domain Lizenz, https://pixabay.com/de/kick-martial-arts-krieger-185384/ © Orientation in Objects GmbH JVM Functional Language Battle 36 OO vs. Funktional https://twitter.com/mariofusco/status/63573247425384448 https://twitter.com/mfeathers/status/29581296216 © Orientation in Objects GmbH JVM Functional Language Battle 37 18 Ist Java 8 funktional? Foto von Marco Montoya, CC0 Public Domain Lizenz, https://pixabay.com/de/ajedrez-k%C3%B6nig-schach-spiel-640386/ © Orientation in Objects GmbH JVM Functional Language Battle 38 Luhn-Algorithmus in Java 8 – Variante 1 © Orientation in Objects GmbH JVM Functional Language Battle 39 19 Was ist "Funktional Programmieren" mit Java 8? • Lambdas: Funktionsliterale als First-Class-Citizens • Higher-Order Functions (map, forEach) • Currying und Funktionskomposition • Bedarfsauswertung durch Streams (bedingt) • (Rekursion) © Orientation in Objects GmbH JVM Functional Language Battle 40 Java 8: Currying und partielle Funktionsaufrufe Currying: Konvertierung einer Funktion mit n Argumenten in n Funktionen mit jeweils einem Argument. © Orientation in Objects GmbH JVM Functional Language Battle 41 20 Java 8: Funktionskomposition Wiederverwendung von kleinen Funktionen: (f . g)(x) == f(g(x)) © Orientation in Objects GmbH JVM Functional Language Battle 42 Was fehlt Java 8 zur besseren funktionalen Unterstützung? • Erzwingen von Immutability • persistente/unveränderbare Datenstrukturen • Vermeidung von Seiteneffekten (erzwingen) • beliebige Bedarfsauswertungen (mehr als unendliche Streams) • funktionale Bibliotheksfunktionen © Orientation in Objects GmbH JVM Functional Language Battle 43 21 Luhn-Algorithmus in Java 8 – Variante 2 © Orientation in Objects GmbH JVM Functional Language Battle 44 Funktionale Erweiterungen für Java Project Lombok © Orientation in Objects GmbH JVM Functional Language Battle 45 22 FunctionalJava • funktionale Programmierbibliothek für Java • Lernplattform für funktionale Programmierung mit der gewohnten Sprache • unterstützt Java 6+ (mit Retro Lambda) • Basis Datenstrukturen (Funktionen, partielle Funktionen, Unit, Void, Option, Either, … • Immutable Collections (Array, List, Stream, Set, Map, …) • Monaden, Zipper © Orientation in Objects GmbH JVM Functional Language Battle 48 Luhn-Algorithmus in Java 8 mit Functional Java © Orientation in Objects GmbH JVM Functional Language Battle 49 23 Javaslang • "Javaslang is a functional library for Java 8+ that provides persistent data types and functional control structures." • Persistent Data Structures – LinkedList, Queue, Sorted Set, Stream • Tuple • Functions, CheckedFunctions © Orientation in Objects GmbH JVM Functional Language Battle 50 JVM Functional Language Battle 52 Javaslang: Currying © Orientation in Objects GmbH 24 Javaslang: Partielle Funktionsaufrufe und Komposition © Orientation in Objects GmbH JVM Functional Language Battle 53 Luhn-Algorithmus in Java 8 mit Javaslang © Orientation in Objects GmbH JVM Functional Language Battle 55 25 Fazit Foto von Marco Montoya, CC0 Public Domain Lizenz, https://pixabay.com/de/ajedrez-k%C3%B6nig-schach-spiel-640386/ © Orientation in Objects GmbH JVM Functional Language Battle 56 Foto von Hans Braxmeier, CC0 Public Domain Lizenz, https://pixabay.com/de/teller-suppenteller-essteller-1365805/ © Orientation in Objects GmbH JVM Functional Language Battle 57 26 + © Orientation in Objects GmbH JVM Functional Language Battle 58 Links • Code-Beispiele – https://github.com/sippsack/jvm-functional-language-battle • Learn You a Haskell for Great Good! – http://learnyouahaskell.com/chapters • LYAH (Learn You a Haskell) adaptions for Frege – https://github.com/Frege/frege/wiki/LYAH-adaptions-for-Frege • Project Lombok, Functional Java, Javaslang – https://projectlombok.org/ – http://www.functionaljava.org/ – http://www.javaslang.io/ © Orientation in Objects GmbH JVM Functional Language Battle 59 27 Literaturhinweise • Functional Programming in Java: Harnessing the Power Of Java 8 Lambda Expressions – Venkat Subramaniam – The Pragmatic Programmers, Erscheinungsdatum: Februar 2014 – ISBN: 978-1-93778-546-8 – Sprache: Englisch • Mastering Lambdas – – – – – Maurice Naftalin Oracle Press Erscheinungsdatum: Oktober 2014 ISBN: 0071829628 Sprache: Englisch JVM Functional Language Battle © Orientation in Objects GmbH 60 Literaturhinweise • Learn You a Haskell for Great Good!: A Beginner's Guide – – – – • Real World Haskell – – – – © Orientation in Objects GmbH Miran Lipovaca No Starch Press, Erscheinungsdatum: April 2011 ISBN: 978-1593272838 Sprache: Englisch Bryan O'Sullivan und John Goerzen O'Reilly, Erscheinungsdatum: 2010 ISBN: 978-0596514983 Sprache: Englisch JVM Functional Language Battle 61 28 ? ? ? ? ? ? ? ? Fragen ? Orientation in Objects GmbH Weinheimer Str. 68 68309 Mannheim www.oio.de [email protected] 62 Vielen Dank für Ihre Aufmerksamkeit ! Orientation in Objects GmbH Weinheimer Str. 68 68309 Mannheim www.oio.de [email protected] 29