41
Functional Vaadin Henri Muurimaa, SVP of Services [email protected] +358 400 474778 @henrimuurimaa 7

Functional Vaadin talk at OSCON 2014

  • Upload
    hezamu

  • View
    532

  • Download
    2

Embed Size (px)

DESCRIPTION

An introduction on how to utilize functional programming techniques in Java 8 and Scala with Vaadin code.

Citation preview

Page 1: Functional Vaadin talk at OSCON 2014

Functional Vaadin

Henri Muurimaa, SVP of [email protected] +358 400 474778 @henrimuurimaa

7

Page 2: Functional Vaadin talk at OSCON 2014
Page 3: Functional Vaadin talk at OSCON 2014

MissionMissionWhy do we exist

Make building amazing web applications easy

Page 4: Functional Vaadin talk at OSCON 2014

Building blocks

Page 5: Functional Vaadin talk at OSCON 2014

Developer

Productivity

Rich

UX

Page 6: Functional Vaadin talk at OSCON 2014

Web application layers

JavaScriptWeb serverBackend Communication

JS required required required requiredVaadin

required optionalrequired optional

Page 7: Functional Vaadin talk at OSCON 2014

Web application layers

JavaScriptWeb serverBackend Communication

JS required required required required

Vaadin

required optionalrequired optional

1 layer vs

3 layers

Less code Less bugs Faster time-to-market

Page 8: Functional Vaadin talk at OSCON 2014

Wrong, but the community is very active there

> 100.000 developers from > 10.000 cities > 450 add-ons in the marketplace

Other 4 %Asia

20 %

Americas 22 %

Europe 54 %

Open Source community

Apache-licensed

Page 9: Functional Vaadin talk at OSCON 2014

Demo time

Page 10: Functional Vaadin talk at OSCON 2014

github.com/hezamu/WorkoutTracker

Page 11: Functional Vaadin talk at OSCON 2014

What is Functional Programming?

Page 12: Functional Vaadin talk at OSCON 2014

A style of programming that expresses computation as the evaluation of mathematical functions

Page 13: Functional Vaadin talk at OSCON 2014

Recursion

Lazy evaluation

Lambda expressionsType theory

MonadsReferential transparency

Currying

Entscheidungsproblem

Pattern matching

Tuples

Page 14: Functional Vaadin talk at OSCON 2014

Something practical?

Side effects?

State?

Denied

Denied

Page 15: Functional Vaadin talk at OSCON 2014

Okay…

Page 16: Functional Vaadin talk at OSCON 2014

What’s in it for me?

A new way of thinking

A new way of programming

Write tight, robust and scalable code

Page 17: Functional Vaadin talk at OSCON 2014

What’s hot in Java 8

Page 18: Functional Vaadin talk at OSCON 2014

Improved Date API

Page 19: Functional Vaadin talk at OSCON 2014

New Java 8 Date API in action

public int monthAge() { return (new Date().getYear() - date.getYear()) * 12 + (new Date().getMonth() - date.getMonth()); }

// Java 8 version with the new Date API public int monthAge() { return (int) Period.between(date, LocalDate.now()).toTotalMonths(); }

Page 20: Functional Vaadin talk at OSCON 2014

Lambda expressions

Page 21: Functional Vaadin talk at OSCON 2014

Anonymous functions

Runnable r = () -> System.out.println("hello lambda!”);

Comparator<Integer> cmp1 = (x, y) -> (x < y) ? -1 : ((x > y) ? 1 : 0);

// Anonymous onsite functions button.addClickListener(event -> System.out.println("Button clicked!"));

Comparator<Integer> cmp2 = (x, y) -> { return (x < y) ? -1 : ((x > y) ? 1 : 0); // Need return if not one liner };

Page 22: Functional Vaadin talk at OSCON 2014

Workout Tracker example

editor.clear.addClickListener(new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { editor.clearValues(); updateRating(); } });

// Java 8 version with a lambda editor.clear.addClickListener(event -> { editor.clearValues(); updateRating(); });

Page 23: Functional Vaadin talk at OSCON 2014

Method references with the :: notation

! private void eventHandler(Button.ClickEvent event) { // do something about the button click }

button.addClickListener(this::eventHandler);

// If the handler method is static button.addClickListener(MyClass::eventHandler);

Page 24: Functional Vaadin talk at OSCON 2014

Workout Tracker example

!editor.activity.addValueChangeListener(new Property.ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { updateRating(); } });

// Java 8 version with a method reference editor.date.addValueChangeListener(this::updateRating);

Page 25: Functional Vaadin talk at OSCON 2014

Streams

Page 26: Functional Vaadin talk at OSCON 2014

Composable with higher order functions

Streams != collections

As lazy as possible

Can be infinite

Page 27: Functional Vaadin talk at OSCON 2014

Input validation

private boolean areInputsValid() { Component component = null; for (Iterator<Component> iter = editor.iterator(); iter.hasNext(); iter.next()) { if (fieldNotValidating(component)) return false; } return true; }

// Java 8 version with anyMatch and a method reference private boolean areInputsValid() { return !StreamSupport.stream(editor.spliterator(), true) .anyMatch(this::fieldNotValidating); }

Page 28: Functional Vaadin talk at OSCON 2014

Higher order functions

Page 29: Functional Vaadin talk at OSCON 2014

A function that takes one or more functions as input

Page 30: Functional Vaadin talk at OSCON 2014

Returns a new stream by applying the given function to all elements of this stream. !

MapReturns a new stream consisting of the elements of this stream that match the given predicate.

Filter

SQL analogue: SELECT SQL analogue: WHERE

Page 31: Functional Vaadin talk at OSCON 2014

Workout Tracker Example

!

!

!

// Java 8 version with stream operations private Stream<Workout> findByAge(int maxMonths) { return workouts.stream() .filter(w -> w.monthAge() < maxMonths) .sorted(Comparator.comparing(Workout::monthAge).reversed()); }

private List<Workout> findByAge(int maxMonths) { List<Workout> result = new ArrayList<>(); for (Workout w : workouts) { if (w.monthAge() < maxMonths) { result.add(w); } } Collections.sort(result, new Comparator<Workout>() { @Override public int compare(Workout o1, Workout o2) { return o2.monthAge() - o1.monthAge(); } }); ! return result; }

Page 32: Functional Vaadin talk at OSCON 2014
Page 33: Functional Vaadin talk at OSCON 2014

Scratching the surface of Scala syntax

class Cat(name: String) { initLitterBox() def meow(volume: Int = 5) = { println(s"$name meows " + (if (volume <= 5) "quietly" else "loudly")) volume <= 5 } }

Class body is the constructor

identifier: type notation

Functions with def keyword

Arguments can have default values

Return keyword optional

No semicolons needed

Page 34: Functional Vaadin talk at OSCON 2014

Burn the boilerplate - Workout.java

!

!

!

public void setDuration(int duration) { this.duration = duration; } ! public double getAvgHR() { return avgHR; } ! public void setAvgHR(double avgHR) { this.avgHR = avgHR; } ! public double getMaxHR() { return maxHR; } ! public void setMaxHR(double maxHR) { this.maxHR = maxHR; } ! public int getCalories() { return calories; } ! public void setCalories(int calories) { this.calories = calories; } ! public String getComment() { return comment; } ! public void setComment(String comment) { this.comment = comment; } }

public class Workout { private String activity; private Date date; private int duration, calories; private double avgHR, maxHR; private String comment; ! public Workout(String activity, Date date, int time, double avgHR, double maxHR, int kcal, String comment) { this.activity = activity; this.date = date; this.duration = time; this.avgHR = avgHR; this.maxHR = maxHR; this.calories = kcal; this.comment = comment; } ! public int monthAge() { return (int) Period.between(date, LocalDate.now()).toTotalMonths(); } ! public String getActivity() { return activity; } ! public void setActivity(String activity) { this.activity = activity; } ! public Date getDate() { return date; } ! public void setDate(Date date) { this.date = date; } ! public int getDuration() { return duration; }

Page 35: Functional Vaadin talk at OSCON 2014

Equivalent Workout.scala

!

!

!

case class Workout(activity: String, date: LocalDate, duration: Int, avgHR: Double, maxHR: Double, calories: Int, comment: String) { def monthAge = Period.between(date, LocalDate.now).toTotalMonths }

Page 36: Functional Vaadin talk at OSCON 2014

github.com/henrikerola/scaladin

Page 37: Functional Vaadin talk at OSCON 2014

An example

// Scaladin val layout = new VerticalLayout { margin = true ! add(Label("Hello, OSCON!"), alignment = Alignment.TopCenter) add(Button("Click me”, handleButtonClick)) }

// Java 7 VerticalLayout layout = new VerticalLayout(); layout.setMargin(true); Label label = new Label(“Hello, OSCON!”); layout.addComponent(title); layout.setComponentAlignment(label, Alignment.TOP_CENTER); !Button button = new Button(“Click me", new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { handleButtonClick(); } }); layout.addComponent(button);

Page 38: Functional Vaadin talk at OSCON 2014

Input validation, Java 8 & Scala

// Scaladin version of the editor gives us the components as a Scala Set // which supports functional operations. private def areInputsValid = !editor.components.exists(fieldNotValidating)

// Java 8 version with anyMatch and a method reference private boolean areInputsValid() { return !StreamSupport.stream(editor.spliterator(), true) .anyMatch(this::fieldNotValidating); }

Page 39: Functional Vaadin talk at OSCON 2014

Summary

Page 40: Functional Vaadin talk at OSCON 2014

SLOC comparison

Java 7 Java 8 Scala

UI 267 264 175

Presenter 168 128 84

POJO 82 82 8All versions: zero lines of HTML, JavaScript, RPC code or browser specific tweaks

Page 41: Functional Vaadin talk at OSCON 2014

Je zult maar letter wezen. Goed, ik ben niet ontevredet. Maar het valt niet mee in deze zeventiger jaren tot het vaderlandse alfabet te behoren. Foto-zetterijen wringen je steeds in steeds ingevikkelder. Je zult maar letter wezen. Goed, ik ben

Henri Muurimaa, SVP of [email protected] +358 400 474778 @henrimuurimaa