Functional Programming: What’s it good for? · These are all you need to get started; there are...

36
David Leppik | Principal Software Engineer Vocal Laboratories Inc. www.vocalabs.com Functional Programming: What’s it good for? How Kotlin makes OO FP David Leppik Creator of EgTest, an annotation-based testing tool https://github.com/dleppik/EgTest

Transcript of Functional Programming: What’s it good for? · These are all you need to get started; there are...

Page 1: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

David Leppik | Principal Software Engineer

Vocal Laboratories Inc.www.vocalabs.com

Functional Programming: What’s it good for?

How Kotlin makes OO ♡ FP

David Leppik

Creator of EgTest, an annotation-based testing tool https://github.com/dleppik/EgTest

Page 2: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

Who are you?

‣New to Kotlin, or written a lot of it?

‣ Coming from

‣ JVM

‣ Java, Scala, Groovy, Clojure?

‣ JavaScript

‣ TypeScript, Angular, React?

‣ Other?

2

Fist-to-five

Page 3: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

How Kotlin makes OO ♥ FP

‣ Goals for this talk

‣ Know how to mix FP with OO

‣ OO lets FP handle algorithms, FP lets OO handle

code management

‣ FP Best Practices

‣ Know a few great FP patterns

‣ See how Kotlin facilitates those patterns

3

Page 4: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

How Kotlin makes OO ♥ FP

‣Non-goals

‣ Become proficient at functional programming

‣ Know the coolest advanced FP techniques*

‣ Higher-order functions for writing domain-specific

languages

‣ Parallel/distributed programming

‣ Futures & coroutines

4

*If you hear me say “monad,” shout BINGO!

FP takes practice.

Page 5: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

My code base at Vocalabs

‣ Java since 2002

‣ Scala + Java since 2012

‣ Kotlin was the right language, but wasn’t ready

‣ Tonight’s techniques are nearly identical in Scala

or Kotlin

5

Page 6: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

Vocalabs business rules

‣ Problem:

‣ Arbitrary (client-supplied) key/value pairs

‣ Transform customer data (in XML) using

complex business rules (which will change)

‣ e.g. calculate missing fields from two merged

sources with inconsistent data

‣ Oh, and apply this retroactively to records in

the SQL database.

6

This is where I felt I had “leveled up.”

A year before, I would have written the same algorithm twice. My solution is OO, but I wouldn’t have seen it without a FP perspective.

Result is under 200 lines in Scala, including one interface and three implementations (XML, SQL, and unit test)

Solution is at the end of the talk.

Page 7: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

Practical philosophy

‣ Source code is machine-readable technical

documentation

‣ Humans are the toughest audience

‣ Especially when fixing emergency bugs

‣ Great code maximizes the shared

understanding between machines & humans

‣ Code is no more detailed than requirements

7

For more on this topic, I will be presenting about EgTest at the JUG on June 13

We need to discuss what is “practical,” what makes something “good” OO or “good” FP. It’s not purity.

Machine “understanding” = mathematical model is congruent with human interpretation. Implies no surprises.

JUG: Search “Java User Group - Hosted by TEKsystems” on Meetup.com.

Page 8: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

Functional Programming

‣ Computation as a transformation of data

‣ output = f(input)

‣ x = cos(angle)

‣ computer state = f(input, old state)

‣ Just like in algebra, variables are immutable

‣ Complex functions (e.g. programs) are chains of functions

8

FP is a model of computation which treats computation as a data transformation.

FP programs consist of data and algorithms (functions), so thinking functionally is thinking about the program in terms of data flow.

Page 9: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

Pure Functions

‣ Definition

‣ No state: the same input always yields the same

output

‣ No side effects: all it does is produce output

‣ No throwing exceptions!

‣Makes code and data easy to reason about for

developers, IDEs, and compiler optimizers

9

Ideally in FP we use pure functions: functions which only transform data and do so predictably. We can use FP techniques without pure functions, especially if you know the trade-offs.

We usually ignore logging, and exceptions are OK for single-threading.

Page 10: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

10

“Functional programming combines the flexibility and power of abstract mathematics with the intuitive clarity of abstract mathematics.”

xkcd.com/1270/

FP has been around since the 1950s, and has had a cult following among mathematicians & AI researchers, but nobody could explain what it’s good for.

Page 11: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

FP + OO = ♥

11

To know whatfunctional programming

is good for, let’s look at what Object-Oriented programming

is good for

Page 12: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

David Leppik | Principal Software Engineer

Vocal Laboratories Inc.www.vocalabs.com

https://medium.com/@cscalfani/goodbye-object-oriented-programming-a59cda4c0e53

I’ve heard too much “I’m giving up on OO, FP is the future!”

If that’s your attitude, you’re in for a world of hurt.

Page 13: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

SOLID

13

All I have is this hammer

Inheritance

Lots of OO developers see OO as a one-hammer toolbox, and that hammer is named…

Page 14: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

SOLID: OO Best PracticesSingle Responsibility Principle

A class should have only one reason to change.

Open/Closed PrincipleAdd methods instead of changing them

Liskov Substitution PrincipleDon’t give me a squeaky hammer, I’m pounding nails!

Interface Segregation PrincipleMake fine-grained, client specific interfaces

Dependency Inversion PrincipleDepend on abstractions, not heavyweight classes

14

I can’t describe OO best practices without having a slide defining SOLID, but we need to get back to Functional Programming.

A URL for more info is at the end.

Page 15: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

SOLID Summary

‣ Single-purpose classes and interfaces

‣ Don’t abuse inheritance

‣ Lightweight, client-friendly relationships between

components (“interfaces”)

15

Page 16: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

What is good OO?

16

Java is pure OO! That makes it the best!

Page 17: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

Is Java good OO?

‣ Java makes inheritance easier than interfaces

‣ Getting better

‣ One file per class encourages huge multi-

purpose classes

‣ (On the other hand, you always know the

filename for a class)

17

Ironically, good OO is supported by interfaces & packages, which aren’t even technically OO!

Page 18: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

FP lets OO do its thing

‣Object Orientation organizes code

‣ Which class is responsible for this pixel?

‣ Which line in which file can I blame?

‣ How do classes interface with each other?

‣ BUT:

‣ You need algorithms? Have some design patterns!

18

Not a nail

Page 19: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

OO lets FP do its thing

‣ Functional Programming makes it easy to

transform complex data structures

‣ BUT

‣ No guidance on where to code should live or

how to name it

19

All your functions live in one big junk drawer.Emphasis on type systems, not named types. (Haskell, I’m looking at you.)

Page 20: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

FP lets OO do its thing

‣ Here is good OO, but painful to do in Java

‣ Holds related data, doesn’t evaluate, store, or

pretty-print

20

sealed class Exprdata class Const(val number: Double) : Expr()data class Sum(val e1: Expr, val e2: Expr) : Expr()object NotANumber : Expr()

http://kotlinlang.org/docs/reference/sealed-classes.html

Example of Single Responsibility PrincipleIncludes getters, equals, hashCode, toString, copy; this would be at least 40 lines in Java—and wouldn’t be as capable!

The classes describe an expression grammar. The DO NOT evaluate that grammar; that’s something else’s (or several thing else’s) responsibility.

A sealed class has all of its subclasses in the same file.

Page 21: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

OO lets FP do its thing

‣ Basic FP data transformation

21

sealed class Exprdata class Const(val number: Double) : Expr()data class Sum(val e1: Expr, val e2: Expr) : Expr()object NotANumber : Expr()

fun eval(expr: Expr): Double = when (expr) { is Const -> expr.number is Sum -> eval(expr.e1) + eval(expr.e2) NotANumber -> Double.NaN}

http://kotlinlang.org/docs/reference/sealed-classes.html

Since Expr defines the grammar, we have a function to evaluate it. The “when” expression will not compile if you miss any cases.

Construction and deconstruction of complex data structures is central to FP.

In pure OO, deconstructing a superclass is a “code smell” (warning of bad code), since it can be a sign that the method belongs in the class. However, fear of deconstruction leads to violation of Single Responsibility Principle—you need to be clear about what the responsibilities of a class are and not burden it with extra jobs!

In this case, Expr is built to be deconstructed. (So are lists, maps, JSON, XML, POJOs, and all other structured data.) Just about anything you want to do with an Expr follows this “when” pattern. Imagine if this were an HTML formatter. A “format” method clearly wouldn’t belong in Expr, since it is based on your particular web design. Also, formatting could depend on interactions between a Sum and its sub-expressions, where the responsibility wouldn’t belong to any particular Expr type.

Page 22: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

What’s FP good for?

22

So what is the FP equivalent to SOLID?

Page 23: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

Principle of Least Power

23

Can’t we all agree to use this?

Strategic Scala Style: Principle of Least Powerby Li Haoyi

http://tinyurl.com/jos6kue

Martin Odersky, Scala (not Kotlin) creator, at a ScalaDays keynote a year or two ago.

Page 24: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

Principle of Least Power

24

Adapted fromStrategic Scala Style: Principle of Least Power

by Li Haoyi http://tinyurl.com/jos6kue

‣ Principle of Least Power

‣ Given a choice of solutions, pick the least powerful

solution capable of solving your problem

This is the FP equivalent of the Single Responsibility Principle

Page 25: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

Principle of Least Power

25

Scala style guide: http://tinyurl.com/jos6kue

‣ Principle of Least Power

‣ For data, prefer…

‣ Built-in types & collections if possible

‣ Functions if you need a single callback or factory

‣ Data classes to bind multiple things together

‣ Sealed classes for multiple types

Page 26: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

Principle of Least Power

26

Instead of this:

Do this:

Scala style guide: http://tinyurl.com/jos6kue

Instead of calling a getter, pass in the simple type.If you use only one method in a function, pass in the method as a function.This makes code easy to test and easy to reuse.In this case, we’ve removed the dependency on Servlets: we can test without mocks and can reuse this code in a different framework.

Page 27: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

FP: dataflow & functions

27

To think functionally, assume construction and

deconstruction

are cheap & easy

Page 28: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

FP: dataflow & functions

‣ when, your all-purpose deconstruction tool

‣ Data classes

‣ copy makes immutability painless

‣ Collection methods (map, filter, & friends)

28

Page 29: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

Collection/Iterable Functions

‣ filter for the items you want to include

‣map is for one-to-one transformations

‣ flatMap is for many-to-many transformations

‣ Including optional returns

‣ It’s the same as Collection.map(…).flatten()

‣ reduce is for many-to-one transformations

‣ Usually taken care of by sum & joinToString.

29

Best

Esoteric!

These are all you need to get started; there are dozens, but you can do everything with these (except sort.)

Everyone gets confused by the Map interface and the map function. The map interface is a collection type which stores data as if it were the map function.

Page 30: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

Debugging tips

30

One line per action

Split into vals, have IntelliJ explicitly specify the type

Be careful of {} vs ()

Simplify once it works

Page 31: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

The FP Design Pattern

‣ Transform input into simple or algorithm-

specific types

‣ Your core algorithm

‣ Transform into other simple or algorithm-

specific types

‣ Transform output into desired types

31

There’s no real name for this pattern, but it really is fundamental.

Start with your core algorithm and build data around it.

It’s almost as easy as unstructured programming, but far more flexible and maintainable.

Page 32: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

The FP Design Pattern

‣ E.g.: Configuration data class to hold

command-line options, rather than parsing as

you go

‣ E.g.: Result data class rather than array/pair of

function output (startDate, endDate)

‣ E.g. Map of map of data objects instead of

JSON, HTML or XML

32

Page 33: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

Vocalabs business rules

‣ Problem:

‣ Arbitrary (client-supplied) key/value pairs

‣ Transform customer data (in XML) using

complex business rules (which will change)

‣ e.g. calculate missing fields from two merged

sources with inconsistent data

‣ Oh, and apply this retroactively to records in

the SQL database.

33

Start with your core algorithm and build data structures around it. In this case we don’t have one core algorithm, but a long history of example algorithms.

So we need a simple domain-specific language. Don’t be intimidated by the word “language.”

In this case, it’s what Apple calls “protocol-oriented design.”

Page 34: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

Vocalabs business rules

34

A few more convenience methods aren’t shown. This abstracts the algorithm from the implementation.

The business rules are allowed to throw an exception. Alternatively, we could have an errors set.

For each implementation, construct a Builder, apply the rules, commit.

Page 35: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

Conclusion

‣OO lets FP handle algorithms, FP lets OO

handle code management

‣ Computation = data transformation

‣ Principle of least power

‣ Given a choice of solutions, pick the least powerful

solution capable of solving your problem

35

Page 36: Functional Programming: What’s it good for? · These are all you need to get started; there are dozens, but you can do everything with these (except sort.) Everyone gets confused

Questions & Resources

‣ Any questions?

‣ SOLID

‣ http://tinyurl.com/rebellabsSOLID

‣ Principle of Least Power

‣ http://tinyurl.com/jos6kue

36