SlideShare a Scribd company logo
1 of 54
Download to read offline
Pragmatic Functional 
Refactoring with Java 8 
Raoul-Gabriel Urma 
Richard Warburton
First-class Functions 
Currying 
Immutability 
Optional Data Types 
Conclusions
Step 1: filtering invoices from Oracle 
public List<Invoice> filterInvoicesFromOracle(List<Invoice> invoices){ 
List<Invoice> result = new ArrayList<>(); 
for(Invoice invoice: invoices){ 
if( invoice.getCustomer() == Customer.ORACLE){ 
result.add(invoice); 
} 
} 
return result; 
}
Step 2a: abstracting the customer 
public List<Invoice> filterInvoicesFromCustomer(List<Invoice> invoices, 
Customer customer){ 
List<Invoice> result = new ArrayList<>(); 
for(Invoice invoice: invoices){ 
if( invoice.getCustomer() == customer){ 
result.add(invoice); 
} 
} 
return result; 
}
Step 2b: abstracting the name 
public List<Invoice> filterInvoicesEndingWith(List<Invoice> invoices, 
String suffix){ 
List<Invoice> result = new ArrayList<>(); 
for(Invoice invoice: invoices){ 
if( invoice.getName().endsWith(suffix)){ 
result.add(invoice); 
} 
} 
return result; 
}
Step 3: messy code-reuse! 
private List<Invoice> filterInvoicesBad(List<Invoice> invoices, 
Customer customer, 
String suffix, 
boolean flag){ 
List<Invoice> result = new ArrayList<>(); 
for(Invoice invoice: invoices){ 
if(( flag && invoice.getCustomer() == customer) 
|| (!flag && invoice.getName().endsWith(suffix))){ 
result.add(invoice); 
} 
} 
return result; 
}
Step 4a: modeling the filtering criterion 
public Predicate<T> { 
boolean test(T t); 
} 
Invoice boolean 
Predicate<Invoice>
Step 4b: using different criterion with objects 
private List<Invoice> filterInvoices(List<Invoice> invoices, 
Predicate<Invoice> p){ 
List<Invoice> result = new ArrayList<>(); 
for(Invoice invoice: invoices){ 
if( p.test(invoice)){ 
result.add(invoice); 
} 
} 
return result; 
}
Step 4b: using different criterion with objects 
List<Invoice> specificInvoices = 
filterInvoices(invoices, new FacebookTraining()); 
private class FacebookTraining implements Predicate<Invoice> { 
@Override 
public boolean test(Invoice invoice) { 
return invoice.getCustomer() == Customer.FACEBOOK 
&& invoice.getName().endsWith("Training"); 
} 
}
Step 5: method references 
public boolean isOracleInvoice(Invoice invoice){ 
return invoice.getCustomer() == Customer.ORACLE; 
} 
public boolean isTrainingInvoice(Invoice invoice){ 
return invoice.getName().endsWith("Training"); 
} 
List<Invoice> oracleInvoices = 
filterInvoices(invoices, this::isOracleInvoice); 
List<Invoice> trainingInvoices = 
filterInvoices(invoices, this::isTrainingInvoice); 
method references
Step 6: lambdas 
List<Invoice> oracleInvoices = 
filterInvoices(invoices, 
(Invoice invoice) -> invoice.getCustomer() == Customer.ORACLE); 
List<Invoice> trainingInvoices = 
filterInvoices(invoices, 
(Invoice invoice) -> invoice.getName().endsWith(("Training")));
First-class functions 
● Scary functional-programming terminology for a common object-oriented 
pattern (strategy, function object…) 
● All it means is the ability to use a function (method reference, lambda, 
object representing a function) just like a regular value 
○ Pass it as argument to a method 
○ Store it in a variable 
● Lets you cope with requirement changes by representing and passing 
the new requirement as a function
Composing functions 
Functions Composing functions
Composing functions: example 
import java.util.function.Predicate; 
Predicate<Invoice> isFacebookInvoice = this::isFacebookInvoice; 
List<Invoice> facebookAndTraining = 
invoices.stream() 
.filter( isFacebookInvoice.and(this::isTrainingInvoice)) 
.collect(toList()); 
List<Invoice> facebookOrGoogle = 
invoices.stream() 
creating more complex 
functions from building blocks 
.filter( isFacebookInvoice.or(this::isGoogleInvoice)) 
.collect(toList());
Composing functions: why does it work? 
public interface Predicate<T> { 
boolean test(T t); 
default Predicate<T> and(Predicate<? super T> other) { 
Objects.requireNonNull(other); 
return (t) -> test(t) && other.test(t); 
} 
default Predicate<T> or(Predicate<? super T> other) { 
Objects.requireNonNull(other); 
return (t) -> test(t) || other.test(t); 
} 
} 
returns a new 
function that is 
the result of 
composing two 
functions
Creating function pipelines (1) 
public class Letter { 
private final String message; 
public Letter(String message) { 
this.message = message; 
} 
public Letter addDefaultHeader(){ 
return new Letter("From her majesty:n" + message); 
} 
public Letter checkSpelling(){ 
return new Letter(message.replaceAll("FTW", "for the win")); 
} 
public Letter addDefaultFooter(){ 
return new Letter(message + "nKind regards"); 
} 
}
Creating function pipelines (2) 
import java.util.function.Function; 
Function<Letter, Letter> addHeader = Letter::addDefaultHeader; 
Function<Letter, Letter> processingPipeline = 
addHeader.andThen(Letter::checkSpelling) 
.andThen(Letter::addDefaultFooter); 
andThen andThen 
composing 
functions 
addHeader checkSpelling addFooter 
Letter 
{message="Java 
8 FTW!"} 
Letter{message='From 
her majesty: 
Java 8 for the win! 
Kind regards'}
Creating function pipelines (3) 
import java.util.function.Function; 
Function<Letter, Letter> addHeader = Letter::addDefaultHeader; 
Function<Letter, Letter> processingPipeline = 
addHeader.andThen(Letter::addDefaultFooter); 
andThen 
composing 
functions 
addHeader addFooter 
Letter 
{message="Java 
8 FTW!"} 
Letter{message='From 
her majesty: 
Java 8 FTW! 
Kind regards'}
First-class Functions 
Currying 
Immutability 
Optional Data Types 
Conclusions
A conversion function 
// (double, double, double) -> double 
double convert(double amount, double factor, double base) 
{ 
return amount * factor + base; 
} 
// Usage 
double result = convert(10, 1.8, 32); 
assertEquals(result, 50, 0.0);
Currying the conversion function 
// (double, double) -> (double -> double) 
DoubleUnaryOperator convert(double factor, double base) { 
return amount -> amount * factor + base; 
} 
// Partial Application 
DoubleUnaryOperator convertCtoF = convert(1.8, 32); 
// Usage 
double result = convertCtoF.applyAsDouble(10); 
assertEquals(result, 50, 0.0);
More partial application 
// Temperatures 
DoubleUnaryOperator convertCtoF = convert(1.8, 32); 
// Currencies 
DoubleUnaryOperator convert$to£ = convert(0.6, 0); 
// Distance 
DoubleUnaryOperator convertKmToMi = convert(0.62137, 0);
A curry function 
// int -> (int -> int) 
IntFunction<IntUnaryOperator> 
curry(IntBinaryOperator biFunction) { 
return f -> s -> biFunction.applyAsInt(f, s); 
} 
// Usage: 
IntFunction<IntUnaryOperator> add = curry((f, s) -> f + 
s); 
int result = add.apply(1) 
.applyAsInt(2); 
assertEquals(3, result);
Generalised curry function 
// F -> (S -> R) 
<F, S, R> Function<F, Function<S, R>> 
curry(BiFunction<F, S, R> biFunction) { 
return f -> s -> biFunction.apply(f, s); 
}
Summary 
● Currying is about splitting up the arguments of a function. 
● Partial Application is a function “eating” some of its arguments and 
returning a new function 
● You can write your functions in curried form from the beginning or use 
a function to curry them.
First-class Functions 
Currying 
Immutability 
Optional Data Types 
Conclusions
Mutable objects 
public class TrainJourney { 
private int price; 
private TrainJourney onward; 
public TrainJourney(int p, TrainJourney t) { 
price = p; 
onward = t; 
} 
public int getPrice() { 
return price; 
} 
public TrainJourney getOnward() { 
return onward; 
} 
public void setPrice(int price) { 
this.price = price; 
} 
public void setOnward(TrainJourney onward) { 
this.onward = onward; 
} 
}
Immutable objects 
public class TrainJourneyImmutable { 
private final int price; 
private final TrainJourneyImmutable onward; 
public TrainJourneyImmutable(int p, TrainJourneyImmutable t) { 
price = p; 
onward = t; 
} 
public int getPrice() { 
return price; 
} 
public TrainJourneyImmutable getOnward() { 
return onward; 
} 
public TrainJourneyImmutable setPrice(int price) { 
return new TrainJourneyImmutable(price, getOnward()); 
} 
public TrainJourneyImmutable setOnward(TrainJourneyImmutable onward) 
{ 
return new TrainJourneyImmutable(getPrice(), onward); 
} 
}
Mutable approach 
public TrainJourney link(TrainJourney tj1, TrainJourney tj2) { 
if (tj1 == null) { 
return tj2; 
} 
TrainJourney t = tj1; 
while (t.getOnward() != null) { 
t = t.getOnward(); 
} 
t.setOnward(tj2); 
return tj1; 
}
Mutable approach: problem 
TrainJourney linked1 = link(tj1, tj2); 
TrainJourney linked2 = link(tj1, tj2); 
visit(linked2, tj -> { System.out.print(tj.price + " - "); 
}); 
static void visit(TrainJourney journey, Consumer<TrainJourney> c) 
{ 
if (journey != null) { 
c.accept(journey); 
visit(journey.onward, c); 
} 
}
java.lang.StackOverflowError
Immutable approach 
public TrainJourneyImmutable append(TrainJourneyImmutable tj1, 
TrainJourneyImmutable tj2) { 
return tj1 == null ? tj2 
: new TrainJourneyImmutable(tj1.getPrice(), 
append(tj1.getOnward(), tj2) 
); 
}
Related topics 
● Domain Driven Design 
○ Value Classes are Immutable 
● Core Java Improvements 
○ New date & time library in Java 8 has many Immutable Objects 
○ Current Value Types proposal is immutable 
● Tooling 
○ final keyword only bans reassignment 
○ JSR 308 - improved annotation opportunities 
○ Mutability Detector 
○ Findbugs
Immutable objects reduce the scope for bugs.
First-class Functions 
Currying 
Immutability 
Optional Data Types 
Conclusions
Don’t we all love it? 
Exception in thread "main" java.lang.NullPointerException
public String getCarInsuranceName(Person person) { 
return person.getCar().getInsurance().getName(); 
} 
Where’s the NPE?
Defensive checking 
public String getCarInsuranceName(Person person) { 
if (person != null) { 
Car car = person.getCar(); 
if (car != null) { 
Insurance insurance = car.getInsurance(); 
if (insurance != null) { 
return insurance.getName(); 
} 
} 
} 
return "No Insurance"; 
}
Optional 
● Java 8 introduces a new class java.util.Optional<T> 
○ a single-value container 
● Explicit modelling 
○ Immediately clear that its an optional value 
○ better maintainability 
● You need to actively unwrap an Optional 
○ force users to think about the absence case 
○ fewer errors
Updating model 
public class Person { 
private Optional<Car> car; 
public Optional<Car> getCar() { return car; } 
} 
public class Car { 
private Optional<Insurance> insurance; 
public Optional<Insurance> getInsurance() { return insurance; } 
} 
public class Insurance { 
private String name; 
public String getName() { return name; } 
}
Refactoring our example 
public String getCarInsuranceName(Person person) { 
return Optional.ofNullable(person) 
.flatMap(Person::getCar) 
.flatMap(Car::getInsurance) 
.map(Insurance::getName) 
.orElse("No Insurance"); 
}
Consistent use of Optional replaces the use of null
First-class Functions 
Currying 
Immutability 
Optional Data Types 
Conclusions
Summary of benefits 
● First-class functions let you cope for requirement changes 
● Currying lets you re-use code logic 
● Immutability reduces the scope for bugs 
● Optional data types lets you reduce null checking boilerplate and 
prevent bugs
Training Website: http://java8training.com 
http://manning.com/urma http://tinyurl.com/java8lambdas
Any Questions? 
Richard Warburton 
@richardwarburto 
Raoul-Gabriel Urma 
@raoulUK
Example currying use cases 
● Large factory methods 
○ Partially apply some of the arguments and then pass this factory 
object around. 
● Parser Combinators 
○ many(‘a’) - function which parses a, aa, aaa, etc.

More Related Content

What's hot

PHP unserialization vulnerabilities: What are we missing?
PHP unserialization vulnerabilities: What are we missing?PHP unserialization vulnerabilities: What are we missing?
PHP unserialization vulnerabilities: What are we missing?Sam Thomas
 
Haskell vs. F# vs. Scala
Haskell vs. F# vs. ScalaHaskell vs. F# vs. Scala
Haskell vs. F# vs. Scalapt114
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modelingMario Fusco
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Mario Fusco
 
The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)Scott Wlaschin
 
Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Scott Wlaschin
 
Introduction to ParSeq: to make asynchronous java easier
Introduction to ParSeq: to make asynchronous java easierIntroduction to ParSeq: to make asynchronous java easier
Introduction to ParSeq: to make asynchronous java easierJunchuan Wang
 
Introduction to Coroutines @ KotlinConf 2017
Introduction to Coroutines @ KotlinConf 2017Introduction to Coroutines @ KotlinConf 2017
Introduction to Coroutines @ KotlinConf 2017Roman Elizarov
 
Kotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenesKotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenesAnh Vu
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Roman Elizarov
 
Kotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime PerformanceKotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime Performanceintelliyole
 
Let's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java APILet's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java APIMario Fusco
 
Kotlin Native - C / Swift Interop - ACCU Autmn 2019
Kotlin Native - C / Swift Interop - ACCU Autmn 2019Kotlin Native - C / Swift Interop - ACCU Autmn 2019
Kotlin Native - C / Swift Interop - ACCU Autmn 2019Eamonn Boyle
 
Quill vs Slick Smackdown
Quill vs Slick SmackdownQuill vs Slick Smackdown
Quill vs Slick SmackdownAlexander Ioffe
 
Clean code and Code Smells
Clean code and Code SmellsClean code and Code Smells
Clean code and Code SmellsMario Sangiorgio
 
Fantastic Red Team Attacks and How to Find Them
Fantastic Red Team Attacks and How to Find ThemFantastic Red Team Attacks and How to Find Them
Fantastic Red Team Attacks and How to Find ThemRoss Wolf
 
Functional Patterns with Java8 @Bucharest Java User Group
Functional Patterns with Java8 @Bucharest Java User GroupFunctional Patterns with Java8 @Bucharest Java User Group
Functional Patterns with Java8 @Bucharest Java User GroupVictor Rentea
 
Java Input Output and File Handling
Java Input Output and File HandlingJava Input Output and File Handling
Java Input Output and File HandlingSunil OS
 

What's hot (20)

PHP unserialization vulnerabilities: What are we missing?
PHP unserialization vulnerabilities: What are we missing?PHP unserialization vulnerabilities: What are we missing?
PHP unserialization vulnerabilities: What are we missing?
 
Haskell vs. F# vs. Scala
Haskell vs. F# vs. ScalaHaskell vs. F# vs. Scala
Haskell vs. F# vs. Scala
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modeling
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...
 
The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)
 
Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013
 
Spring integration
Spring integrationSpring integration
Spring integration
 
Introduction to ParSeq: to make asynchronous java easier
Introduction to ParSeq: to make asynchronous java easierIntroduction to ParSeq: to make asynchronous java easier
Introduction to ParSeq: to make asynchronous java easier
 
Introduction to Coroutines @ KotlinConf 2017
Introduction to Coroutines @ KotlinConf 2017Introduction to Coroutines @ KotlinConf 2017
Introduction to Coroutines @ KotlinConf 2017
 
Kotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenesKotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenes
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017
 
Kotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime PerformanceKotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime Performance
 
Let's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java APILet's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java API
 
Kotlin Native - C / Swift Interop - ACCU Autmn 2019
Kotlin Native - C / Swift Interop - ACCU Autmn 2019Kotlin Native - C / Swift Interop - ACCU Autmn 2019
Kotlin Native - C / Swift Interop - ACCU Autmn 2019
 
Quill vs Slick Smackdown
Quill vs Slick SmackdownQuill vs Slick Smackdown
Quill vs Slick Smackdown
 
Clean code and Code Smells
Clean code and Code SmellsClean code and Code Smells
Clean code and Code Smells
 
Fantastic Red Team Attacks and How to Find Them
Fantastic Red Team Attacks and How to Find ThemFantastic Red Team Attacks and How to Find Them
Fantastic Red Team Attacks and How to Find Them
 
Logging with log4j v1.2
Logging with log4j v1.2Logging with log4j v1.2
Logging with log4j v1.2
 
Functional Patterns with Java8 @Bucharest Java User Group
Functional Patterns with Java8 @Bucharest Java User GroupFunctional Patterns with Java8 @Bucharest Java User Group
Functional Patterns with Java8 @Bucharest Java User Group
 
Java Input Output and File Handling
Java Input Output and File HandlingJava Input Output and File Handling
Java Input Output and File Handling
 

Viewers also liked

Refactoring to Java 8 (Devoxx BE)
Refactoring to Java 8 (Devoxx BE)Refactoring to Java 8 (Devoxx BE)
Refactoring to Java 8 (Devoxx BE)Trisha Gee
 
Pragmatic functional refactoring with java 8 (1)
Pragmatic functional refactoring with java 8 (1)Pragmatic functional refactoring with java 8 (1)
Pragmatic functional refactoring with java 8 (1)RichardWarburton
 
Migrating to IntelliJ IDEA from Eclipse
Migrating to IntelliJ IDEA from EclipseMigrating to IntelliJ IDEA from Eclipse
Migrating to IntelliJ IDEA from EclipseTrisha Gee
 
Productive Programming in Java 8 - with Lambdas and Streams
Productive Programming in Java 8 - with Lambdas and Streams Productive Programming in Java 8 - with Lambdas and Streams
Productive Programming in Java 8 - with Lambdas and Streams Ganesh Samarthyam
 
Functional programming with Java 8
Functional programming with Java 8Functional programming with Java 8
Functional programming with Java 8LivePerson
 

Viewers also liked (6)

Refactoring to Java 8 (Devoxx BE)
Refactoring to Java 8 (Devoxx BE)Refactoring to Java 8 (Devoxx BE)
Refactoring to Java 8 (Devoxx BE)
 
Java 8 by example!
Java 8 by example!Java 8 by example!
Java 8 by example!
 
Pragmatic functional refactoring with java 8 (1)
Pragmatic functional refactoring with java 8 (1)Pragmatic functional refactoring with java 8 (1)
Pragmatic functional refactoring with java 8 (1)
 
Migrating to IntelliJ IDEA from Eclipse
Migrating to IntelliJ IDEA from EclipseMigrating to IntelliJ IDEA from Eclipse
Migrating to IntelliJ IDEA from Eclipse
 
Productive Programming in Java 8 - with Lambdas and Streams
Productive Programming in Java 8 - with Lambdas and Streams Productive Programming in Java 8 - with Lambdas and Streams
Productive Programming in Java 8 - with Lambdas and Streams
 
Functional programming with Java 8
Functional programming with Java 8Functional programming with Java 8
Functional programming with Java 8
 

Similar to Pragmatic functional refactoring with java 8

Pragmatic Functional Refactoring with Java 8
Pragmatic Functional Refactoring with Java 8Pragmatic Functional Refactoring with Java 8
Pragmatic Functional Refactoring with Java 8Codemotion
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modelingCodemotion
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy codeShriKant Vashishtha
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Codemotion
 
Is java8a truefunctionallanguage
Is java8a truefunctionallanguageIs java8a truefunctionallanguage
Is java8a truefunctionallanguageSamir Chekkal
 
Is java8 a true functional programming language
Is java8 a true functional programming languageIs java8 a true functional programming language
Is java8 a true functional programming languageSQLI
 
Currying and Partial Function Application (PFA)
Currying and Partial Function Application (PFA)Currying and Partial Function Application (PFA)
Currying and Partial Function Application (PFA)Dhaval Dalal
 
SeneJug java_8_prez_122015
SeneJug java_8_prez_122015SeneJug java_8_prez_122015
SeneJug java_8_prez_122015senejug
 
TI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class FunctionsTI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class FunctionsEelco Visser
 
Functional Programming In Java
Functional Programming In JavaFunctional Programming In Java
Functional Programming In JavaAndrei Solntsev
 
Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Calvin Cheng
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestPavan Chitumalla
 
Higher Order Components and Render Props
Higher Order Components and Render PropsHigher Order Components and Render Props
Higher Order Components and Render PropsNitish Phanse
 
Java 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesJava 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesGanesh Samarthyam
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondMario Fusco
 

Similar to Pragmatic functional refactoring with java 8 (20)

Pragmatic Functional Refactoring with Java 8
Pragmatic Functional Refactoring with Java 8Pragmatic Functional Refactoring with Java 8
Pragmatic Functional Refactoring with Java 8
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modeling
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy code
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...
 
Is java8a truefunctionallanguage
Is java8a truefunctionallanguageIs java8a truefunctionallanguage
Is java8a truefunctionallanguage
 
Is java8 a true functional programming language
Is java8 a true functional programming languageIs java8 a true functional programming language
Is java8 a true functional programming language
 
Currying and Partial Function Application (PFA)
Currying and Partial Function Application (PFA)Currying and Partial Function Application (PFA)
Currying and Partial Function Application (PFA)
 
SeneJug java_8_prez_122015
SeneJug java_8_prez_122015SeneJug java_8_prez_122015
SeneJug java_8_prez_122015
 
Functional Programming
Functional ProgrammingFunctional Programming
Functional Programming
 
Array Cont
Array ContArray Cont
Array Cont
 
TI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class FunctionsTI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class Functions
 
Java8
Java8Java8
Java8
 
Functional programming 101
Functional programming 101Functional programming 101
Functional programming 101
 
Functional Programming In Java
Functional Programming In JavaFunctional Programming In Java
Functional Programming In Java
 
Unit 4 (1)
Unit 4 (1)Unit 4 (1)
Unit 4 (1)
 
Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at Pinterest
 
Higher Order Components and Render Props
Higher Order Components and Render PropsHigher Order Components and Render Props
Higher Order Components and Render Props
 
Java 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesJava 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional Interfaces
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
 

More from RichardWarburton

Fantastic performance and where to find it
Fantastic performance and where to find itFantastic performance and where to find it
Fantastic performance and where to find itRichardWarburton
 
Production profiling what, why and how technical audience (3)
Production profiling  what, why and how   technical audience (3)Production profiling  what, why and how   technical audience (3)
Production profiling what, why and how technical audience (3)RichardWarburton
 
Production profiling: What, Why and How
Production profiling: What, Why and HowProduction profiling: What, Why and How
Production profiling: What, Why and HowRichardWarburton
 
Production profiling what, why and how (JBCN Edition)
Production profiling  what, why and how (JBCN Edition)Production profiling  what, why and how (JBCN Edition)
Production profiling what, why and how (JBCN Edition)RichardWarburton
 
Production Profiling: What, Why and How
Production Profiling: What, Why and HowProduction Profiling: What, Why and How
Production Profiling: What, Why and HowRichardWarburton
 
Java collections the force awakens
Java collections  the force awakensJava collections  the force awakens
Java collections the force awakensRichardWarburton
 
Generics Past, Present and Future (Latest)
Generics Past, Present and Future (Latest)Generics Past, Present and Future (Latest)
Generics Past, Present and Future (Latest)RichardWarburton
 
Generics past, present and future
Generics  past, present and futureGenerics  past, present and future
Generics past, present and futureRichardWarburton
 
Jvm profiling under the hood
Jvm profiling under the hoodJvm profiling under the hood
Jvm profiling under the hoodRichardWarburton
 
Generics Past, Present and Future
Generics Past, Present and FutureGenerics Past, Present and Future
Generics Past, Present and FutureRichardWarburton
 
Performance and predictability (1)
Performance and predictability (1)Performance and predictability (1)
Performance and predictability (1)RichardWarburton
 
Performance and predictability
Performance and predictabilityPerformance and predictability
Performance and predictabilityRichardWarburton
 
Twins: Object Oriented Programming and Functional Programming
Twins: Object Oriented Programming and Functional ProgrammingTwins: Object Oriented Programming and Functional Programming
Twins: Object Oriented Programming and Functional ProgrammingRichardWarburton
 
Introduction to lambda behave
Introduction to lambda behaveIntroduction to lambda behave
Introduction to lambda behaveRichardWarburton
 
Introduction to lambda behave
Introduction to lambda behaveIntroduction to lambda behave
Introduction to lambda behaveRichardWarburton
 
Performance and predictability
Performance and predictabilityPerformance and predictability
Performance and predictabilityRichardWarburton
 
Simplifying java with lambdas (short)
Simplifying java with lambdas (short)Simplifying java with lambdas (short)
Simplifying java with lambdas (short)RichardWarburton
 

More from RichardWarburton (20)

Fantastic performance and where to find it
Fantastic performance and where to find itFantastic performance and where to find it
Fantastic performance and where to find it
 
Production profiling what, why and how technical audience (3)
Production profiling  what, why and how   technical audience (3)Production profiling  what, why and how   technical audience (3)
Production profiling what, why and how technical audience (3)
 
Production profiling: What, Why and How
Production profiling: What, Why and HowProduction profiling: What, Why and How
Production profiling: What, Why and How
 
Production profiling what, why and how (JBCN Edition)
Production profiling  what, why and how (JBCN Edition)Production profiling  what, why and how (JBCN Edition)
Production profiling what, why and how (JBCN Edition)
 
Production Profiling: What, Why and How
Production Profiling: What, Why and HowProduction Profiling: What, Why and How
Production Profiling: What, Why and How
 
Java collections the force awakens
Java collections  the force awakensJava collections  the force awakens
Java collections the force awakens
 
Generics Past, Present and Future (Latest)
Generics Past, Present and Future (Latest)Generics Past, Present and Future (Latest)
Generics Past, Present and Future (Latest)
 
Collections forceawakens
Collections forceawakensCollections forceawakens
Collections forceawakens
 
Generics past, present and future
Generics  past, present and futureGenerics  past, present and future
Generics past, present and future
 
Jvm profiling under the hood
Jvm profiling under the hoodJvm profiling under the hood
Jvm profiling under the hood
 
How to run a hackday
How to run a hackdayHow to run a hackday
How to run a hackday
 
Generics Past, Present and Future
Generics Past, Present and FutureGenerics Past, Present and Future
Generics Past, Present and Future
 
Performance and predictability (1)
Performance and predictability (1)Performance and predictability (1)
Performance and predictability (1)
 
Performance and predictability
Performance and predictabilityPerformance and predictability
Performance and predictability
 
Twins: Object Oriented Programming and Functional Programming
Twins: Object Oriented Programming and Functional ProgrammingTwins: Object Oriented Programming and Functional Programming
Twins: Object Oriented Programming and Functional Programming
 
Introduction to lambda behave
Introduction to lambda behaveIntroduction to lambda behave
Introduction to lambda behave
 
Introduction to lambda behave
Introduction to lambda behaveIntroduction to lambda behave
Introduction to lambda behave
 
Performance and predictability
Performance and predictabilityPerformance and predictability
Performance and predictability
 
Simplifying java with lambdas (short)
Simplifying java with lambdas (short)Simplifying java with lambdas (short)
Simplifying java with lambdas (short)
 
Twins: OOP and FP
Twins: OOP and FPTwins: OOP and FP
Twins: OOP and FP
 

Recently uploaded

Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesZilliz
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 

Recently uploaded (20)

Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector Databases
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 

Pragmatic functional refactoring with java 8

  • 1. Pragmatic Functional Refactoring with Java 8 Raoul-Gabriel Urma Richard Warburton
  • 2.
  • 3.
  • 4. First-class Functions Currying Immutability Optional Data Types Conclusions
  • 5. Step 1: filtering invoices from Oracle public List<Invoice> filterInvoicesFromOracle(List<Invoice> invoices){ List<Invoice> result = new ArrayList<>(); for(Invoice invoice: invoices){ if( invoice.getCustomer() == Customer.ORACLE){ result.add(invoice); } } return result; }
  • 6. Step 2a: abstracting the customer public List<Invoice> filterInvoicesFromCustomer(List<Invoice> invoices, Customer customer){ List<Invoice> result = new ArrayList<>(); for(Invoice invoice: invoices){ if( invoice.getCustomer() == customer){ result.add(invoice); } } return result; }
  • 7. Step 2b: abstracting the name public List<Invoice> filterInvoicesEndingWith(List<Invoice> invoices, String suffix){ List<Invoice> result = new ArrayList<>(); for(Invoice invoice: invoices){ if( invoice.getName().endsWith(suffix)){ result.add(invoice); } } return result; }
  • 8. Step 3: messy code-reuse! private List<Invoice> filterInvoicesBad(List<Invoice> invoices, Customer customer, String suffix, boolean flag){ List<Invoice> result = new ArrayList<>(); for(Invoice invoice: invoices){ if(( flag && invoice.getCustomer() == customer) || (!flag && invoice.getName().endsWith(suffix))){ result.add(invoice); } } return result; }
  • 9. Step 4a: modeling the filtering criterion public Predicate<T> { boolean test(T t); } Invoice boolean Predicate<Invoice>
  • 10. Step 4b: using different criterion with objects private List<Invoice> filterInvoices(List<Invoice> invoices, Predicate<Invoice> p){ List<Invoice> result = new ArrayList<>(); for(Invoice invoice: invoices){ if( p.test(invoice)){ result.add(invoice); } } return result; }
  • 11. Step 4b: using different criterion with objects List<Invoice> specificInvoices = filterInvoices(invoices, new FacebookTraining()); private class FacebookTraining implements Predicate<Invoice> { @Override public boolean test(Invoice invoice) { return invoice.getCustomer() == Customer.FACEBOOK && invoice.getName().endsWith("Training"); } }
  • 12. Step 5: method references public boolean isOracleInvoice(Invoice invoice){ return invoice.getCustomer() == Customer.ORACLE; } public boolean isTrainingInvoice(Invoice invoice){ return invoice.getName().endsWith("Training"); } List<Invoice> oracleInvoices = filterInvoices(invoices, this::isOracleInvoice); List<Invoice> trainingInvoices = filterInvoices(invoices, this::isTrainingInvoice); method references
  • 13. Step 6: lambdas List<Invoice> oracleInvoices = filterInvoices(invoices, (Invoice invoice) -> invoice.getCustomer() == Customer.ORACLE); List<Invoice> trainingInvoices = filterInvoices(invoices, (Invoice invoice) -> invoice.getName().endsWith(("Training")));
  • 14. First-class functions ● Scary functional-programming terminology for a common object-oriented pattern (strategy, function object…) ● All it means is the ability to use a function (method reference, lambda, object representing a function) just like a regular value ○ Pass it as argument to a method ○ Store it in a variable ● Lets you cope with requirement changes by representing and passing the new requirement as a function
  • 15. Composing functions Functions Composing functions
  • 16. Composing functions: example import java.util.function.Predicate; Predicate<Invoice> isFacebookInvoice = this::isFacebookInvoice; List<Invoice> facebookAndTraining = invoices.stream() .filter( isFacebookInvoice.and(this::isTrainingInvoice)) .collect(toList()); List<Invoice> facebookOrGoogle = invoices.stream() creating more complex functions from building blocks .filter( isFacebookInvoice.or(this::isGoogleInvoice)) .collect(toList());
  • 17. Composing functions: why does it work? public interface Predicate<T> { boolean test(T t); default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } } returns a new function that is the result of composing two functions
  • 18. Creating function pipelines (1) public class Letter { private final String message; public Letter(String message) { this.message = message; } public Letter addDefaultHeader(){ return new Letter("From her majesty:n" + message); } public Letter checkSpelling(){ return new Letter(message.replaceAll("FTW", "for the win")); } public Letter addDefaultFooter(){ return new Letter(message + "nKind regards"); } }
  • 19. Creating function pipelines (2) import java.util.function.Function; Function<Letter, Letter> addHeader = Letter::addDefaultHeader; Function<Letter, Letter> processingPipeline = addHeader.andThen(Letter::checkSpelling) .andThen(Letter::addDefaultFooter); andThen andThen composing functions addHeader checkSpelling addFooter Letter {message="Java 8 FTW!"} Letter{message='From her majesty: Java 8 for the win! Kind regards'}
  • 20. Creating function pipelines (3) import java.util.function.Function; Function<Letter, Letter> addHeader = Letter::addDefaultHeader; Function<Letter, Letter> processingPipeline = addHeader.andThen(Letter::addDefaultFooter); andThen composing functions addHeader addFooter Letter {message="Java 8 FTW!"} Letter{message='From her majesty: Java 8 FTW! Kind regards'}
  • 21. First-class Functions Currying Immutability Optional Data Types Conclusions
  • 22.
  • 23.
  • 24. A conversion function // (double, double, double) -> double double convert(double amount, double factor, double base) { return amount * factor + base; } // Usage double result = convert(10, 1.8, 32); assertEquals(result, 50, 0.0);
  • 25. Currying the conversion function // (double, double) -> (double -> double) DoubleUnaryOperator convert(double factor, double base) { return amount -> amount * factor + base; } // Partial Application DoubleUnaryOperator convertCtoF = convert(1.8, 32); // Usage double result = convertCtoF.applyAsDouble(10); assertEquals(result, 50, 0.0);
  • 26. More partial application // Temperatures DoubleUnaryOperator convertCtoF = convert(1.8, 32); // Currencies DoubleUnaryOperator convert$to£ = convert(0.6, 0); // Distance DoubleUnaryOperator convertKmToMi = convert(0.62137, 0);
  • 27. A curry function // int -> (int -> int) IntFunction<IntUnaryOperator> curry(IntBinaryOperator biFunction) { return f -> s -> biFunction.applyAsInt(f, s); } // Usage: IntFunction<IntUnaryOperator> add = curry((f, s) -> f + s); int result = add.apply(1) .applyAsInt(2); assertEquals(3, result);
  • 28. Generalised curry function // F -> (S -> R) <F, S, R> Function<F, Function<S, R>> curry(BiFunction<F, S, R> biFunction) { return f -> s -> biFunction.apply(f, s); }
  • 29. Summary ● Currying is about splitting up the arguments of a function. ● Partial Application is a function “eating” some of its arguments and returning a new function ● You can write your functions in curried form from the beginning or use a function to curry them.
  • 30. First-class Functions Currying Immutability Optional Data Types Conclusions
  • 31. Mutable objects public class TrainJourney { private int price; private TrainJourney onward; public TrainJourney(int p, TrainJourney t) { price = p; onward = t; } public int getPrice() { return price; } public TrainJourney getOnward() { return onward; } public void setPrice(int price) { this.price = price; } public void setOnward(TrainJourney onward) { this.onward = onward; } }
  • 32. Immutable objects public class TrainJourneyImmutable { private final int price; private final TrainJourneyImmutable onward; public TrainJourneyImmutable(int p, TrainJourneyImmutable t) { price = p; onward = t; } public int getPrice() { return price; } public TrainJourneyImmutable getOnward() { return onward; } public TrainJourneyImmutable setPrice(int price) { return new TrainJourneyImmutable(price, getOnward()); } public TrainJourneyImmutable setOnward(TrainJourneyImmutable onward) { return new TrainJourneyImmutable(getPrice(), onward); } }
  • 33. Mutable approach public TrainJourney link(TrainJourney tj1, TrainJourney tj2) { if (tj1 == null) { return tj2; } TrainJourney t = tj1; while (t.getOnward() != null) { t = t.getOnward(); } t.setOnward(tj2); return tj1; }
  • 34.
  • 35. Mutable approach: problem TrainJourney linked1 = link(tj1, tj2); TrainJourney linked2 = link(tj1, tj2); visit(linked2, tj -> { System.out.print(tj.price + " - "); }); static void visit(TrainJourney journey, Consumer<TrainJourney> c) { if (journey != null) { c.accept(journey); visit(journey.onward, c); } }
  • 37. Immutable approach public TrainJourneyImmutable append(TrainJourneyImmutable tj1, TrainJourneyImmutable tj2) { return tj1 == null ? tj2 : new TrainJourneyImmutable(tj1.getPrice(), append(tj1.getOnward(), tj2) ); }
  • 38.
  • 39. Related topics ● Domain Driven Design ○ Value Classes are Immutable ● Core Java Improvements ○ New date & time library in Java 8 has many Immutable Objects ○ Current Value Types proposal is immutable ● Tooling ○ final keyword only bans reassignment ○ JSR 308 - improved annotation opportunities ○ Mutability Detector ○ Findbugs
  • 40. Immutable objects reduce the scope for bugs.
  • 41. First-class Functions Currying Immutability Optional Data Types Conclusions
  • 42. Don’t we all love it? Exception in thread "main" java.lang.NullPointerException
  • 43. public String getCarInsuranceName(Person person) { return person.getCar().getInsurance().getName(); } Where’s the NPE?
  • 44. Defensive checking public String getCarInsuranceName(Person person) { if (person != null) { Car car = person.getCar(); if (car != null) { Insurance insurance = car.getInsurance(); if (insurance != null) { return insurance.getName(); } } } return "No Insurance"; }
  • 45. Optional ● Java 8 introduces a new class java.util.Optional<T> ○ a single-value container ● Explicit modelling ○ Immediately clear that its an optional value ○ better maintainability ● You need to actively unwrap an Optional ○ force users to think about the absence case ○ fewer errors
  • 46. Updating model public class Person { private Optional<Car> car; public Optional<Car> getCar() { return car; } } public class Car { private Optional<Insurance> insurance; public Optional<Insurance> getInsurance() { return insurance; } } public class Insurance { private String name; public String getName() { return name; } }
  • 47. Refactoring our example public String getCarInsuranceName(Person person) { return Optional.ofNullable(person) .flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) .orElse("No Insurance"); }
  • 48. Consistent use of Optional replaces the use of null
  • 49. First-class Functions Currying Immutability Optional Data Types Conclusions
  • 50. Summary of benefits ● First-class functions let you cope for requirement changes ● Currying lets you re-use code logic ● Immutability reduces the scope for bugs ● Optional data types lets you reduce null checking boilerplate and prevent bugs
  • 51.
  • 52. Training Website: http://java8training.com http://manning.com/urma http://tinyurl.com/java8lambdas
  • 53. Any Questions? Richard Warburton @richardwarburto Raoul-Gabriel Urma @raoulUK
  • 54. Example currying use cases ● Large factory methods ○ Partially apply some of the arguments and then pass this factory object around. ● Parser Combinators ○ many(‘a’) - function which parses a, aa, aaa, etc.