combinator als funktionales entwurfsmuster · 2017-06-26 · about me gregor trefs 31 years old...

47
Combinator als funktionales Entwurfsmuster In Java 8

Upload: others

Post on 24-Jul-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Combinator als funktionales Entwurfsmuster

In Java 8

Page 2: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Combinator PatternIn Java 8

Page 3: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

About Me

Gregor Trefs

31 years old

Organizer of @majug

Achievement 2017: Acting lessons

twitter/github: gtrefs

Page 4: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Who knows what

a function is?

a lambda expression is?

a combinator is?

the combinator pattern is?

About You

Page 5: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

The TalkRecap: Functions

Primitives and Combinators

Return value reasoning

Benefits and Disadvantages

When to use it

Page 6: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Recap: Functions

add :: Num a => a -> a -> aadd = \x -> \y -> x + y

Page 7: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Recap: Functions

int addOne(int i){ return i+1; }

Page 8: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Recap: Functions

Function<Integer, Integer> addOne;addOne = i -> i + 1;

Deduction Context

Lambda expression

Page 9: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Recap: Functions

int compute(int i, Function<Int, Int> f)

Higher order

First order

Page 10: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Recap: Functions

Function<Int, Int> makeAdder(int i){ return x -> x + i;}

Function<Int, Int> addOne = makeAdder(1)

Return value Factory

Page 11: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Recap: Functions

Function<Int, Function<Int, Int>> f;

f = x -> (y -> x + y);

Function<Integer, Integer> addOne = f.apply(1);

Parameter of

first function

Returns function

Parameter of

returned function

Returns int

Page 12: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Recap: Functions

addOne = f.apply(1); addTwo = f.apply(2);

Function<Int, Int> addThree = x -> addTwo.apply(addOne.apply(x));

addFive = addThree.compose(addTwo);

Typesafe composition

Page 13: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

The TalkRecap: Functions

Primitives and Combinators

Return value reasoning

Benefits and Disadvantages

When to use it

Page 14: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Primitives and Combinators

Combine primitives into more complex structures

Functions Functions Functions

Page 15: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Primitives and Combinators

Primitives are the simplest elements within a domain

Functions

Page 16: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Primitives and Combinators

Combinators compose primitives and/or domain structures into more complex domain

structures

Page 17: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Primitives and Combinators

Use Case: User Validation

Function<User, Boolean>

Page 18: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Primitives and Combinators

@Testpublic void yield_valid_for_user_with_email_and_non_empty_name(){ User gregor = new User("Gregor Trefs", 31, "[email protected]");

UserValidation validation = todo();

assertThat(validation.apply(gregor), is(true));}

interface UserValidation extends Function<User, Boolean> {}

Page 19: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Primitives and Combinators

@Testpublic void yield_valid_for_user_with_email_and_non_empty_name(){ User gregor = new User("Gregor Trefs", 31, "[email protected]"); UserValidation nameIsNotEmpty = user -> !user.name.trim().isEmpty(); UserValidation mailContainsAtSign = user -> user.email.contains("@"); UserValidation validation; validation = user -> nameIsNotEmpty.apply(user) && mailContainsAtSign.apply(user);

assertThat(validation.apply(gregor), is(true));}

interface UserValidation extends Function<User, Boolean> {}

Page 20: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Primitives and Combinators

@Testpublic void yield_valid_for_user_with_email_and_non_empty_name(){ final User gregor = new User("Gregor Trefs", 31, "[email protected]"); final UserValidation validation = nameIsNotEmpty.and(mailContainsAtSign);

assertThat(validation.apply(gregor), is(true));}

public interface UserValidation extends Function<User, Boolean> { UserValidation nameIsNotEmpty = user -> !user.name.trim().isEmpty(); UserValidation mailContainsAtSign = user -> user.email.contains("@"); default UserValidation and(UserValidation other){ return user -> this.apply(user) && other.apply(user); }

default UserValidation or(UserValidation other){ return user -> this.apply(user) || other.apply(user); }}

Page 21: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Return value reasoning

Embedded domain specific language: Primitives and combinators from the

validation domain

Page 22: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Return value reasoning

Separation of validation description and execution

Page 23: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Return value reasoning

Validation has no shared mutable state

Page 24: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

The TalkRecap: Functions

Primitives and Combinators

Return value reasoning

Benefits and Disadvantages

When to use it

Page 25: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Return value reasoning

Boolean is bad for representing validation results

Page 26: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Return value reasoning

Hard to determine which rules invalidated the result

Page 27: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Return value reasoning

Semantic is implicit and context specific

Page 28: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Return value reasoning

Type for representing the validation result is needed

Page 29: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Return value reasoning

@Testpublic void yield_invalid_for_user_without_email(){ User gregor = new User("Gregor Trefs", 31, ""); ValidationResult result = nameIsNotEmpty.and(eMailContainsAtSign).apply(gregor); assertThat(result.getReason().get(), is("E-Mail is not valid."));}

public interface UserValidation extends Function<User, ValidationResult> { UserValidation nameIsNotEmpty = todo(); UserValidation eMailContainsAtSign = todo(); default UserValidation and(UserValidation other){ return todo(); }}

Page 30: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Return value reasoning

@Testpublic void yield_invalid_for_user_without_email(){ User gregor = new User("Gregor Trefs", 31, ""); ValidationResult result = nameIsNotEmpty.and(eMailContainsAtSign).apply(gregor); assertThat(result.getReason().get(), is("E-Mail is not valid."));}public interface UserValidation extends Function<User, ValidationResult> { UserValidation nameIsNotEmpty = user -> !user.name.trim().isEmpty()?valid():invalid("User name is empty"); UserValidation eMailContainsAtSign = user -> user.email.contains("@")?valid():invalid("E-Mail is not valid."); default UserValidation and(UserValidation other){ return user -> { ValidationResult result = this.apply(user); return result.isValid() ? other.apply(user) : result; }; }}

Page 31: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

The TalkRecap: Functions

Primitives and Combinators

Return value reasoning

Benefits and Disadvantages

When to use it

Page 32: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Benefits and Disadvantages

Domain specific approach

Page 33: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Benefits and Disadvantages

Implicit information is modelled explicit

Page 34: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Benefits and Disadvantages

Separation of concerns in primitives and composability with combinators

Page 35: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Benefits and Disadvantages

Extensibility by using the context

UserValidation ext; ext = nameIsNotEmpty.and(u -> …)

Page 36: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Benefits and Disadvantages

Reusability: Once described, a function can be applied manyfold

Page 37: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Benefits and Disadvantages

Does my team understand the concepts of functional programming?

Page 38: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Benefits and Disadvantages

How do I determine primitives and combinators in my domain?

Page 39: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

The TalkRecap: Functions

Primitives and Combinators

Return value reasoning

Benefits and Disadvantages

When to use it

Page 40: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

When to use it

Design your API in a composable way

Comparator

Page 41: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

When to use it

Strategy pattern: Combine your strategies

Page 42: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

When to use it

Command pattern: Combine your commands

Page 43: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

When to use it

Similar to the composite pattern, but:Composes behaviour instead of structure

Page 44: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

When to use it

Whenever a function is the basic concept

Page 45: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

When to use it

FizzBuzz: Number -> Word

Validation: User -> ValidationResult

Parsing: String -> AST

Projection: EventStream -> Aggregate

Serialization: Object -> JSON

Page 46: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

Hire me for

development

courses on functional Java

Contact

[email protected]

linkedin.com/in/gregor-trefs

The EndQuestions?

Page 47: Combinator als funktionales Entwurfsmuster · 2017-06-26 · About Me Gregor Trefs 31 years old Organizer of @majug Achievement 2017: Acting lessons twitter/github: gtrefs

● My blog post about the topic

http://bitly.com/2lryGxJ

● Functional Programming in

Scala (The red one)

Java (The blue one)

● Background picture by

John Salzarulo

Literatureand links