JVM Functional Language Battle

Werbung
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
Architektur
Agile Softwareentwicklung
Codequalität
Co-Organisator
Feedback gern an: @sippsack, [email protected]
© Orientation in Objects GmbH
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
JavaScript
Haskell
Frege
Funktional
JVM Functional Language Battle
6
3
Imperativ
Funktional
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
JVM Functional Language Battle
14
Java klassisch – Variante 1
© Orientation in Objects GmbH
7
Java klassisch – Variante 2
Variablen
Schleifen
Verzweigungen
Tiefe der
Verschachtelung
Zustandsänderungen
Reihenfolge
nicht beliebig
ExceptionHandling?
© Orientation in Objects GmbH
JVM Functional Language Battle
15
OOP?
SRP?
DRY?
SoC?
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)
•
Exceptions = Goto-Statements
•
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 typisiert (statisch auch möglich)
•
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
JavaScript
•
objektorientierte Skriptsprache
•
aber klassenlos (Prototyp-basiert)
•
dynamisch typisiert
•
Funktionen sind First Class Citizens
•
geeignet für Client (Browser) und Server (Node.js, Nashorn)
© Orientation in Objects GmbH
JVM Functional Language Battle
25
JVM Functional Language Battle
26
Beispiel JavaScript
© Orientation in Objects GmbH
13
Kotlin
•
statisch typisiert
•
objektorientiert
•
Übersetzung in Java Bytecode oder JavaScript Quellcode
•
interoperabel mit Java
•
entwickelt bei Jetbrains (IntelliJ IDEA)
© Orientation in Objects GmbH
JVM Functional Language Battle
27
JVM Functional Language Battle
28
Beispiel Kotlin
© Orientation in Objects GmbH
14
Kurz, kürzer, lesbarer?
http://codegolf.eu-west-1.elasticbeanstalk.com/results
© Orientation in Objects GmbH
JVM Functional Language Battle
29
Viele Beispiele in vielen
imperativen Sprachen
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
30
15
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
JVM Functional Language Battle
© Orientation in Objects GmbH
31
Beispiel
4716347184862961
1
4
7
2
1
6
3
1
12
4
1
1 2
5
1
3
6
6
2
9 in 6Ziffern
1
Aufsplitten
3
6
1
7
Ziffern umdrehen4
9
4
6 16 4 16 1 14 4 jede
6 2.
6 verdoppeln
2
7
8
9
4
6 1 6 4 1 6 1 1 4 4 Ziffern
6
6 aufspalten
2
7
8
9
4
6
7
4
7
1
5
4 Teilsummen
6
6
2
7
8
1 + 3 + 9 + 4 + 6 + 7 + 4 + 7 + 1 + 5 + 4 + 6 +Aufsummieren
6+2+7+8
1
6
3
4
7
1
8
4
8
9
2
6
8
4
8
1
7
4
80
80 % 10 == 0
gültig
7
© Orientation in Objects GmbH
Teilbar durch 10?
JVM Functional Language Battle
32
16
Algorithmus in Frege
isValid n =
Validierungsfunktion
divisibleBy10(
Teilbar durch 10?
sumDigits(
Aufsummieren
double2nd(
jede 2. verdoppeln
reverse(
Ziffern umdrehen
toDigits(n)
Aufsplitten in Ziffern
)
)
)
)
JVM Functional Language Battle
© Orientation in Objects GmbH
33
toDigits
reverse
double2nd
sumDigits
true
false
divisible10
Funktionskaskade
n
isValid n =
divisibleBy10(sumDigits(double2nd(reverse(toDigits(n)))))
© Orientation in Objects GmbH
JVM Functional Language Battle
34
17
•
•
•
•
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
35
Funktionale Elemente
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])
sumDigits xs = sum (concat (map toDigits xs))
divisibleBy10 n = n `mod` 10 == 0
isValid = divisibleBy10 . sumDigits . double2nd .
reverse . toDigits
© Orientation in Objects GmbH
JVM Functional Language Battle
36
18
Funktionale Elemente
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])
sumDigits xs = sum (concat
toDigits xs))
Infix- statt(map
Postfix-Notation
divisibleBy10 n = n `mod` 10 == 0
isValid = divisibleBy10 . sumDigits . double2nd .
reverse . toDigits
© Orientation in Objects GmbH
JVM Functional Language Battle
37
Funktionale Elemente
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])
sumDigits xs = sum (concat (map toDigits xs))
Composition:
divisibleBy10 nFunction
= n `mod`
10 == 0
f . g (x) == f(g(x))
isValid = divisibleBy10 . sumDigits . double2nd .
reverse . toDigits
© Orientation in Objects GmbH
JVM Functional Language Battle
38
19
Funktionale Elemente
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])
Partial Function
sumDigits
xs = sumHigher
(concat
toDigits xs))
Order(map
Function
Persistente
Application
Datenstrukturen
divisibleBy10 n = n `mod` 10 == 0
isValid = divisibleBy10 . sumDigits . double2nd .
reverse . toDigits
© Orientation in Objects GmbH
JVM Functional Language Battle
39
Funktionale Elemente
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
sumDigits xs = sum (concat (map toDigits xs))
divisibleBy10 n = n `mod` 10 == 0
isValid = divisibleBy10 . sumDigits . double2nd .
reverse . toDigits
© Orientation in Objects GmbH
JVM Functional Language Battle
40
20
Funktionale Elemente
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])
sumDigits xs = sum (concat (map toDigits xs))
divisibleBy10 n = n `mod` 10 == 0
isValid = divisibleBy10 . sumDigits . double2nd .
reverse . toDigits
JVM Functional Language Battle
© Orientation in Objects GmbH
Vorteile
•
leicht verständlich, einfach zu
schlussfolgern
•
seiteneffektfrei
•
einfach test-/debugbar
•
leicht parallelisierbar
•
modularisierbar und einfach
wieder zusammenführbar
•
hohe Code-Qualität
41
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
42
21
OO vs. Funktional
https://twitter.com/mariofusco/status/63573247425384448
https://twitter.com/mfeathers/status/29581296216
© Orientation in Objects GmbH
JVM Functional Language Battle
43
Scala
•
funktional und objektorientiert
•
statisch typisiert (Typinferenz)
•
Funktionen als First-Class-Citizens
•
Pattern Matching
•
Java-Integration möglich
© Orientation in Objects GmbH
JVM Functional Language Battle
44
22
Beispiel Scala
© Orientation in Objects GmbH
JVM Functional Language Battle
45
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
46
23
Luhn-Algorithmus in Java 8 – Variante 1
© Orientation in Objects GmbH
JVM Functional Language Battle
47
Luhn-Algorithmus in Java 8 – Variante 2
nach Idee von Thomas Much
© Orientation in Objects GmbH
JVM Functional Language Battle
48
24
Luhn-Algorithmus in Java 8
Variante 1 (vs. Variante 1.1) vs. Variante 2
// 1 if length even, 2 otherwise
int[] i = { number.length() % 2 == 0 ? 1 : 2 };
…
.map(n -> n * (i[0] = i[0] == 1 ? 2 : 1))
Verkappte Zustandsänderung
// oder Ref<Boolean> alternate = new Ref(false);
// .map(n -> n * (alternate.swap() ? 2 : 1))
PrimitiveIterator.OfInt faktor = IntStream.iterate(1, i
-> 3 - i).iterator();
System.out.println(faktor.nextInt()); // 1
System.out.println(faktor.nextInt()); // 2
Lazy Evaluation
System.out.println(faktor.nextInt()); // 1
Generator
System.out.println(faktor.nextInt()); // 2
© Orientation in Objects GmbH
JVM Functional Language Battle
49
Was heißt "Funktional Programmieren" in Java 8?
•
Lambdas: Funktionsliterale als First-Class-Citizens
•
Higher-Order Functions (map, forEach)
•
Currying und Funktionskomposition
•
Unendliche Datenstrukturen mit Streams
•
(Rekursion)
© Orientation in Objects GmbH
JVM Functional Language Battle
50
25
Java 8: Wiederverwendung von Funktionen
Funktionskomposition
Verketten/Komposition von Teil-Funktionen: (f . g)(x) == f(g(x))
© Orientation in Objects GmbH
JVM Functional Language Battle
51
Java 8: Wiederverwendung von Funktionen
Currying und partielle Funktionsaufrufe
Currying: Konvertierung einer Funktion mit n Argumenten
in n Funktionen mit jeweils einem Argument.
Partielle Aufrufe: Spezialisierung von allgemeinen Funktionen
© Orientation in Objects GmbH
JVM Functional Language Battle
52
26
Was fehlt Java 8 zur besseren funktionalen
Unterstützung?
•
Erzwingen von Immutability
•
persistente/unveränderbare Datenstrukturen
•
Vermeidung von Seiteneffekten (erzwingen)
•
Lazy Evualation
•
kein echtes Currying
•
funktionale Bibliotheksfunktionen
•
Value-Types (Tuple, Either, Try, Validation, Lazy …)
© Orientation in Objects GmbH
JVM Functional Language Battle
53
Luhn-Algorithmus in Java 8 – Variante 3
Frege/Haskell Style
© Orientation in Objects GmbH
JVM Functional Language Battle
54
27
Funktionale Erweiterungen für Java
Project Lombok
© Orientation in Objects GmbH
JVM Functional Language Battle
55
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
56
28
private, final,
keine Setter,
Argument-Konstruktor
equals/hashcode
Lazy-Evaluierung
© Orientation in Objects GmbH
JVM Functional Language Battle
57
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
58
29
Luhn-Algorithmus in Java 8 mit Functional Java
© Orientation in Objects GmbH
JVM Functional Language Battle
59
Vavr
•
"Vavr core is a functional library for Java 8+."
•
Persistent Data Structures
– LinkedList, Queue, Sorted Set, Stream
•
Tuple, Values (Option, Try, Lazy, Either, …)
•
Pattern Matching
•
Functions, CheckedFunctions, Lifting (Exceptions fangen)
– Currying, Partial Application, Composition
•
Monaden, Zipping, …
© Orientation in Objects GmbH
JVM Functional Language Battle
60
30
http://www.vavr.io/vavr-docs/
© Orientation in Objects GmbH
JVM Functional Language Battle
61
JVM Functional Language Battle
62
Vavr: Tuple (bis Tuple8)
© Orientation in Objects GmbH
31
Vavr: Wiederverwendung von Funktionen
Currying
© Orientation in Objects GmbH
JVM Functional Language Battle
63
Vavr: Wiederverwendung von Funktionen
Partielle Funktionsaufrufe und Komposition
© Orientation in Objects GmbH
JVM Functional Language Battle
64
32
Vavr: Function Lift (Fangen von Exceptions)
© Orientation in Objects GmbH
JVM Functional Language Battle
65
Luhn-Algorithmus in Java 8 mit Vavr
© Orientation in Objects GmbH
JVM Functional Language Battle
66
33
Luhn-Algorithmus in Java 8 mit Vavr (Variante 2)
© Orientation in Objects GmbH
JVM Functional Language Battle
67
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
68
34
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
69
Foto von Hans Braxmeier, CC0 Public Domain Lizenz, https://pixabay.com/de/teller-suppenteller-essteller-1365805/
© Orientation in Objects GmbH
JVM Functional Language Battle
70
35
+
Project Lombok
© Orientation in Objects GmbH
JVM Functional Language Battle
71
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
•
Onlinekurs TU Delft (FP 101):
– https://courses.edx.org/courses/DelftX/FP101x/3T2014/info
© Orientation in Objects GmbH
JVM Functional Language Battle
72
36
Links
•
Vavr
– http://www.vavr.io/
•
Immutables
– http://immutables.github.io/
•
Project Lombok
– https://projectlombok.org/
•
Functional Java
– http://www.functionaljava.org/
JVM Functional Language Battle
© Orientation in Objects GmbH
73
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
74
37
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
–
–
–
–
Bryan O'Sullivan und John Goerzen
O'Reilly, Erscheinungsdatum: 2010
ISBN: 978-0596514983
Sprache: Englisch
JVM Functional Language Battle
© Orientation in Objects GmbH
75
? ?
?
?
?
? ?
?
Fragen ?
Orientation in Objects GmbH
Weinheimer Str. 68
68309 Mannheim
www.oio.de
[email protected]
76
38
Vielen Dank für Ihre
Aufmerksamkeit !
Orientation in Objects GmbH
Weinheimer Str. 68
68309 Mannheim
www.oio.de
[email protected]
39
Herunterladen