JVM Functional Language Battle Orientation in Objects GmbH Weinheimer Str. 68 68309 Mannheim Version: 1.0 www.oio.de [email protected] Ihr Sprecher Falk Sippach (@sippsack) Trainer, Berater, Entwickler Co-Organisator © Orientation in Objects GmbH Architektur Agile Softwareentwicklung Codequalität JVM Functional Language Battle 2 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 Agenda <x> <y/> </x> Einführung © Orientation in Objects GmbH Imperativ Deklarativ JVM Functional Language Battle Functional Java 5 Experiment © Orientation in Objects GmbH JVM Functional Language Battle 6 Scala Clojure Haskell Frege Java Groovy Imperativ © Orientation in Objects GmbH Funktional JVM Functional Language Battle 7 Imperative Programmierung Imperative Programmierung (lat. imperare ‚anordnen‘, ‚befehlen‘) ist ein Programmierparadigma, nach dem „ein Programm aus einer Folge von Anweisungen besteht, die vorgeben, in welcher Reihenfolge was vom Computer getan werden soll“. https://de.wikipedia.org/wiki/Imperative_Programmierung © Orientation in Objects GmbH JVM Functional Language Battle 8 Imperativ © Orientation in Objects GmbH Funktional Deklarativ JVM Functional Language Battle 9 Funktionale Programmierung Funktionale Programmierung ist ein Programmierparadigma, bei dem Programme ausschließlich aus Funktionen bestehen. Dadurch wird bewusst auf die aus der imperativen Programmierung bekannten Nebenwirkungen verzichtet. © Orientation in Objects GmbH JVM Functional Language Battle 10 Problemstellung © Orientation in Objects GmbH JVM Functional Language Battle 11 ? © Orientation in Objects GmbH JVM Functional Language Battle 12 Prüfsummen-Berechnung Luhn-Algorithmus; Luhn-Formel; "Modulo 10"-Algorithmus; Double-Add-Double-Methode © Orientation in Objects GmbH JVM Functional Language Battle 13 Validierung von Kreditkarten • Luhn Algorithmus • Kreditkartennummern können sich selbst prüfen rein clientseitige Prüfung möglich • Berechnung einer Prüfsumme aus den einzelnen Ziffern • wenn Prüfsumme modulo 10 – = 0 => valide – <> 0 => nicht valide © Orientation in Objects GmbH JVM Functional Language Battle 14 Wie funktioniert die Validierung genau 1. (Umwandlung in Ziffern) 2. Reihenfolge vertauschen 3. jede zweite Zahl verdoppeln 4. einzelne Zahlen zusammenaddieren – bei Zahlen größer 9 werden die einzelnen Ziffern aufaddiert 5. valide, wenn die Summe modulo 10 == 0 © Orientation in Objects GmbH JVM Functional Language Battle 15 Beispiel "4716347184862961" 4 7 1 6 3 4 7 1 8 4 8 6 2 9 6 1 1 6 9 2 6 8 4 8 1 7 4 3 6 1 7 4 1 12 9 4 6 16 4 16 1 14 4 6 6 2 7 8 1 1 2 9 4 6 1 6 4 1 6 1 1 4 4 6 6 2 7 8 1 3 9 4 6 7 4 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 © Orientation in Objects GmbH JVM Functional Language Battle 16 © Orientation in Objects GmbH JVM Functional Language Battle 17 © Orientation in Objects GmbH JVM Functional Language Battle 18 Java klassisch – Variante 1 © Orientation in Objects GmbH JVM Functional Language Battle 19 Java klassisch – Variante 2 © Orientation in Objects GmbH JVM Functional Language Battle 20 Java klassisch mit sprechenden Methodennamen © Orientation in Objects GmbH JVM Functional Language Battle 21 Demo Kreditkarten-Nummer prüfen mit Java: public static void main(String[] args) { System.out.println(isValid("4716347184862961")); } © Orientation in Objects GmbH JVM Functional Language Battle 22 Programm: Folge von elementaren Schritten Typischer Schritt ist die Wertzuweisung Speicherung von Daten erfolgt in Variablen Kontrollstrukturen: • Sequenzen (…; …;) • Alternativen (if, switch) • Schleifen (for, while, do…while) • Sprünge und Unterprogrammaufrufe (goto) © Orientation in Objects GmbH JVM Functional Language Battle 23 Imperativ vs. Deklarativ Imperativ: Wie erreiche ich mein Ziel? Deklarativ: Was will ich erreichen? © Orientation in Objects GmbH JVM Functional Language Battle 24 Imperativ Funktional © Orientation in Objects GmbH JVM Functional Language Battle 25 Java klassisch – Spaghetti-Code Aufspalten in Ziffern Reihenfolge drehen Jede 2. Ziffer verdoppeln Aufsummieren Validierungsprüfung © Orientation in Objects GmbH JVM Functional Language Battle 26 Und in anderen Sprachen? © Orientation in Objects GmbH JVM Functional Language Battle 27 Groovy • objektorientiert • dynamisch und/statisch typisiert • ausdrucksstarke/prägnante Syntax • sehr gute Integration mit Java (JVM, Bibliotheken, Vererbung, …) • Metaprogrammierung, Closures, Operatorüberladung © Orientation in Objects GmbH JVM Functional Language Battle 28 Demo Kreditkarten-Nummer prüfen mit Groovy groovy> isValid 4716347184862961 true © Orientation in Objects GmbH JVM Functional Language Battle 29 JavaScript • objektorientierte Skriptsprache • aber klassenlos (Prototyp-basiert) • dynamisch typisiert • Funktionen sind First-Class-Citizens • Client (Browser) und Server (Node.js, Nashorn auf JVM) © Orientation in Objects GmbH JVM Functional Language Battle 30 Demo Kreditkarten-Nummer prüfen mit JavaScript > isValid(4716347184862961) true © Orientation in Objects GmbH JVM Functional Language Battle 31 Scala • funktional und objektorientiert • statisch typisiert (Typinferenz) • Funktionen als First-Class-Citizens • Pattern Matching • Java-Integration © Orientation in Objects GmbH JVM Functional Language Battle 32 Demo Kreditkarten-Nummer prüfen mit Scala scala> isValid(4716347184862961) true © Orientation in Objects GmbH JVM Functional Language Battle 33 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 34 Demo Kreditkarten-Nummer prüfen mit Frege (Haskell) frege> isValid 4716347184862961 True © Orientation in Objects GmbH JVM Functional Language Battle 35 Algorithmus in Frege Validierungsfunktion Kreditkartennummer isValid n = (sumDigits (double2nd (toDigitsRev n))) % 10 == 0 Summe der Ziffern © Orientation in Objects GmbH Verdoppeln jede 2. Ziffer Ziffern rückwärts JVM Functional Language Battle Teilbar durch 10? 36 Haskell/Frege toDigits n = toDigits (n `div` 10) ++ [(n `mod` 10)] toDigitsRev n = reverse (toDigits n) double2nd = zipWith (*) (cycle [1, 2]) sumDigits xs = sum (concat (map toDigits xs)) isValid n = mod (sumDigits (double2nd (toDigitsRev n))) 10 == 0 isValid n = (sumDigits (double2nd (toDigitsRev n))) % 10 == 0 © Orientation in Objects GmbH JVM Functional Language Battle 37 Keine veränderbaren Zustände Seiteneffekt-frei Referentielle Transparenz First-Class-Citizens Higher-Order Functions Lambdas/Closures Lazy Evaluation Rekursion © Orientation in Objects GmbH JVM Functional Language Battle 38 Funktionen © Orientation in Objects GmbH JVM Functional Language Battle 39 Warum Funktionale Programmierung • einfach zu testen, zu debuggen • einfach zu verstehen durch einfache Abstraktionen und referentielle Transparenz • seiteneffektfrei, lässt sich leicht parallelisieren • modularisierbar und einfach wieder zusammenführbar • erhöht Code-Qualität © Orientation in Objects GmbH JVM Functional Language Battle 40 OO vs. Funktional © Orientation in Objects GmbH JVM Functional Language Battle 41 Ist Java 8 funktional? © Orientation in Objects GmbH JVM Functional Language Battle 42 "Funktional Programmieren" mit Java 8 • Lambdas: Funktionsliterale als First-Class-Citizens • Higher-Order Functions • Currying und Funktionskomposition • Streams • Erweiterungen Collections mit Default-Methoden • (Rekursion) © Orientation in Objects GmbH JVM Functional Language Battle 43 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 44 Java 8: Funktionskomposition © Orientation in Objects GmbH JVM Functional Language Battle 45 Luhn-Algorithmus in Java 8 – Variante 1 © Orientation in Objects GmbH JVM Functional Language Battle 46 Was fehlt Java 8 zur besseren funktionalen Unterstützung? • Erzwingen von Immutability • persistente Datenstrukturen • Vermeidung von Seiteneffekten • referentielle Transparenz • Lazy Evaluation • funktionale Bibliotheksfunktionen © Orientation in Objects GmbH JVM Functional Language Battle 47 Immutable Klassen • genau ein Zustand – keine Prüfung von Invarianten und von Zustandsübergänge (API-Doc) – abgeleitete Größen können in Cache gehalten werden • Thread-safe – keine Zustandsänderung – keine Synchronisation • gemeinsame Nutzung von Instanzen – public Konstanten – Instanzkontrolle durch statische Factories – keine defensive Copies • gemeinsame Nutzung innerer Zustände – BigInteger#negate() – String#subString() © Orientation in Objects GmbH JVM Functional Language Battle 48 Funktionale Erweiterungen für Java Project Lombok © Orientation in Objects GmbH JVM Functional Language Battle 49 Project Lombok • Compile-Time Metaprogrammierung • Reducing Boilerplate Code durch Annotationen • Generation des Immutable-Gerüsts mit @Value • Lazy Evaluierung mit @Getter(lazy = true) © Orientation in Objects GmbH JVM Functional Language Battle 50 private, final, keine Setter, Argument-Konstruktor equals/hashcode Lazy-Evaluierung © Orientation in Objects GmbH JVM Functional Language Battle 51 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 52 © Orientation in Objects GmbH JVM Functional Language Battle 53 Demo Kreditkarten-Nummer prüfen mit Java 8 + FunctionalJava: public static void main(String[] args) { System.out.println(isValid("4716347184862961")); } © Orientation in Objects GmbH JVM Functional Language Battle 54 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 55 Javaslang: Tuple (bis Tuple8) © Orientation in Objects GmbH JVM Functional Language Battle 56 Javaslang: Partielle Funktionsaufrufe und Komposition © Orientation in Objects GmbH JVM Functional Language Battle 57 Javaslang: Currying © Orientation in Objects GmbH JVM Functional Language Battle 58 Javaslang: Function Lift (Fangen von Exceptions) © Orientation in Objects GmbH JVM Functional Language Battle 59 Links • 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 – https://projectlombok.org/ • Functional Java – http://www.functionaljava.org/ • Javaslang – http://www.javaslang.io/ © Orientation in Objects GmbH JVM Functional Language Battle 60 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 – – – – – © Orientation in Objects GmbH Maurice Naftalin Oracle Press Erscheinungsdatum: Oktober 2014 ISBN: 0071829628 Sprache: Englisch JVM Functional Language Battle 61 Literaturhinweise • Learn You a Haskell for Great Good!: A Beginner's Guide – – – – Miran Lipovaca No Starch Press, Erscheinungsdatum: April 2011 ISBN: 978-1593272838 Sprache: Englisch • Real World Haskell – – – – © Orientation in Objects GmbH Bryan O'Sullivan und John Goerzen O'Reilly, Erscheinungsdatum: 2010 ISBN: 978-0596514983 Sprache: Englisch JVM Functional Language Battle 62 ? ? ? ? ? Fragen ? Orientation in Objects GmbH Weinheimer Str. 68 68309 Mannheim www.oio.de [email protected] 63 Vielen Dank für Ihre Aufmerksamkeit ! Orientation in Objects GmbH Weinheimer Str. 68 68309 Mannheim www.oio.de [email protected]