Think like an Elm developer Piper Niehaus Denver, CO, USA - - PowerPoint PPT Presentation

think like an elm developer piper niehaus
SMART_READER_LITE
LIVE PREVIEW

Think like an Elm developer Piper Niehaus Denver, CO, USA - - PowerPoint PPT Presentation

Think like an Elm developer Piper Niehaus Denver, CO, USA Backpacker / skier Nonprofit board chair @piperniehaus Software Engineer at Pivotal Pivotal Tracker team Elm in Production since 2016 Internal Products and


slide-1
SLIDE 1

Think like an Elm developer

slide-2
SLIDE 2

@piperniehaus

Piper Niehaus

  • Denver, CO, USA
  • Backpacker / skier
  • Nonprofit board chair
slide-3
SLIDE 3

@piperniehaus

Software Engineer at Pivotal

  • Pivotal Tracker team

Elm in Production since 2016

  • Internal Products and Services team

○ Kotlin

slide-4
SLIDE 4

@piperniehaus

We all get excited about new languages

slide-5
SLIDE 5

@piperniehaus

Production changes everything

  • Bugs matter
  • Testing matters
  • Maintainability matters
slide-6
SLIDE 6

@piperniehaus

Goals

  • The promise (level set)
  • The production hump
  • What’s next?
slide-7
SLIDE 7

@piperniehaus

Agenda

  • About me
  • The promise of Elm

○ Background ○ Language ○ Architecture

  • The Pivotal Tracker experience
  • Is Elm right for you?
slide-8
SLIDE 8

@piperniehaus

Elm: A DSL for web apps

  • Language
  • Framework
  • Ecosystem
slide-9
SLIDE 9

@piperniehaus

Elm in production

slide-10
SLIDE 10

@piperniehaus

Elm background

  • Evan Czaplicki’s Harvard thesis
  • Now at noredink
  • Elm’s Benevolent Dictator For Life
slide-11
SLIDE 11

@piperniehaus

Benevolent dictator for life

  • Design
  • Direction
  • Priorities
  • Pace
slide-12
SLIDE 12

@piperniehaus

Agenda

  • About me
  • The promise of Elm

○ Background ○ Language ○ Architecture

  • The Pivotal Tracker experience
  • Is Elm right for you?
slide-13
SLIDE 13

@piperniehaus

Elm is a programming language that compiles to JavaScript

  • Pure functional
  • Strong static type system with a friendly compiler

Elm language

slide-14
SLIDE 14

@piperniehaus

Agenda

  • About me
  • The promise of Elm

○ Background ○ Language ■ Pure functional ■ Strong static type system with a friendly compiler ○ Architecture

  • The Pivotal Tracker experience
  • Is Elm right for you?
slide-15
SLIDE 15

@piperniehaus

What is a pure function?

A function that takes some input and returns output without affecting or being affected by external state

slide-16
SLIDE 16

@piperniehaus

Pure function

Function (arguments) { Computations } External state

Impure function

Return value Return value Function (arguments) { Computations }

slide-17
SLIDE 17

@piperniehaus

slide-18
SLIDE 18

@piperniehaus

Pure vs impure functional programming languages

Pure functional languages:

  • Languages that support only functional paradigms (Haskell, Elm)

Impure functional languages:

  • Languages that support both functional and imperative style

programming (Kotlin, Python)

slide-19
SLIDE 19

@piperniehaus

Benefits of pure functional programming

  • Consistency
  • Code is easy to follow and understand
  • A function given the same values always has the same result
  • Lack of race conditions
  • Time travel debugger
slide-20
SLIDE 20

@piperniehaus

Elm time travel debugger

  • Because every function in Elm is pure
  • See the system at any state
  • Roll back, roll forward
slide-21
SLIDE 21

@piperniehaus

Time travel debugging

slide-22
SLIDE 22

@piperniehaus

Agenda

  • About me
  • The promise of Elm

○ Background ○ Language ■ Pure functional ■ Strong static type system with a friendly compiler ○ Architecture

  • The Pivotal Tracker experience
  • Is Elm right for you?
slide-23
SLIDE 23

@piperniehaus

What is a type?

  • An object’s type describes

○ The kind of data in the object ○ What it can do

  • Examples:

○ String ○ Int

  • All languages must check types

○ Can’t do 1 + “two“

slide-24
SLIDE 24

@piperniehaus

What is static typing?

  • All languages must check types but statically typed languages check at

compile time, while dynamically typed languages check at runtime.

  • Example: Can’t do 1 + “two“

○ In ruby: we find this out when we try to load a page and see an error ○ In Elm: we can’t even compile our code to run the app at all

slide-25
SLIDE 25

@piperniehaus

Dynamic typing

Types are checked at runtime

Static typing

Types are checked at compile time

Strong static* typing

Static typing with the goal of minimizing the gap between code that compiles and code that runs error-free

* While static is a definite CS term, strong is colloquial. This is our definition going forward.

slide-26
SLIDE 26

@piperniehaus Code compiles

Static typing Strong static typing

Code compiles Code runs without errors Code compiles Code runs without errors

Dynamic typing

Code runs without errors

slide-27
SLIDE 27

@piperniehaus

Strong static typing tools in Elm

Extra checks to prevent runtime errors. EG:

  • Custom types
  • Null checks
  • Exhaustiveness checks

○ type Pet = Cat | Dog | Fish ○ Fido is a pet. ○ Everywhere we use fido, we must account for the possibility that fido could be a cat, a dog

  • r a fish
slide-28
SLIDE 28

@piperniehaus

Benefits of strong static typing...

  • Catches errors early and preempts null pointer exceptions
  • Provides parameter + return type matching
  • Makes impossible states impossible (no need to test them)
  • Encode business logic into type system
slide-29
SLIDE 29

@piperniehaus

For the developer, strong static typing means...

  • Enables developers to focus on business logic
  • Provides fast feedback
  • Makes code easy to read
  • Refactoring is easy
slide-30
SLIDE 30

@piperniehaus

Elm’s friendly compiler

  • Elm’s compiler messages are easy to read
  • Makes it easy to rely on the compiler
slide-31
SLIDE 31

@piperniehaus

Example, a misspelled function name

Function addInts is defined Oops! We tried to call it but misspelled Compiler error is helpful and friendly

slide-32
SLIDE 32

@piperniehaus

Agenda

  • About me
  • The promise of Elm

○ Background ○ Language ○ Architecture

  • The Pivotal Tracker experience
  • Is Elm right for you?
slide-33
SLIDE 33

@piperniehaus

What is the Elm architecture?

A way of building web apps that separates an application into:

  • Model: the application’s current state
  • Update: the only way that the state is updated
  • View: the application’s current state in html format

The elm architecture feels natural in Elm, but it also works in other languages

  • Inspiration for Redux
slide-34
SLIDE 34

@piperniehaus

Elm architecture example

View Model Update

User makes a change in the UI (onClick) Message is sent to update function Update function returns a new model based on the old model and function arguments New model is passed to view function and rendered in the browser

slide-35
SLIDE 35

@piperniehaus

An example

slide-36
SLIDE 36

@piperniehaus

slide-37
SLIDE 37

@piperniehaus

Benefits of the Elm architecture

  • Single source of truth
  • Easy to understand
  • Removes race conditions
  • Model and view stay in sync
slide-38
SLIDE 38

@piperniehaus

Why use Elm?

Static typing Pure functions Architecture

+ = Few runtime errors +

Language Architecture

slide-39
SLIDE 39

@piperniehaus

Agenda

  • About me
  • The promise of Elm
  • The Pivotal Tracker experience

○ Background ○ Types & FP in practice ○ Scaling ○ Testing ○ JavaScript interop

  • Is Elm right for you?
slide-40
SLIDE 40

@piperniehaus

Elm and functional programming at Pivotal Tracker

RoR / React / Backbone Dashboard in Elm Project Memberships Page in Elm 2016 2017 2018 Kotlin, TypeScript experiments New user experience in Elm Much discussion

slide-41
SLIDE 41

@piperniehaus

Elm here!

slide-42
SLIDE 42

@piperniehaus

The decision to use Elm

  • Developers using Elm in personal projects
  • Multiple meetings, much thought

○ Would Elm stick around? ○ Interop between multiple languages? ○ Developers using multiple languages?

  • Started in an isolated piece of the app

○ Not interconnected with other stuff ○ Easy to pull out if it didn’t work

slide-43
SLIDE 43

@piperniehaus

Projects

  • The Dashboard page

○ Learning curve ○ (Most) developers like it ○ Challenge of scaling an Elm app ○ Testing philosophies in Elm vs on our team

  • Expanded usage

○ Testing hitting a stride ○ Challenge of interop with Javascript external libraries

slide-44
SLIDE 44

@piperniehaus

Continuing to use Elm mentalities

  • Where else can we apply functional programming and strong types?

○ More Elm? ○ TypeScript? ○ Kotlin?

slide-45
SLIDE 45

@piperniehaus

Agenda

  • About me
  • The promise of Elm
  • The Pivotal Tracker experience

○ Background ○ Types & FP in practice ○ Scaling ○ Testing ○ JavaScript interop

  • Is Elm right for you?
slide-46
SLIDE 46

@piperniehaus

Elm lives up to its promise

  • Runtime errors
  • Race conditions
  • Easy refactors
  • Mindset change
slide-47
SLIDE 47

@piperniehaus

Encoding business logic into types

Example: Managing memberships

  • Project member

○ First name ○ Last name ○ Email

  • Invitee

○ Email

slide-48
SLIDE 48

@piperniehaus

People

slide-49
SLIDE 49

@piperniehaus

slide-50
SLIDE 50

@piperniehaus

Agenda

  • About me
  • The promise of Elm
  • The Pivotal Tracker experience

○ Background ○ Types & FP in practice ○ Scaling ○ Testing ○ JavaScript interop

  • Is Elm right for you?
slide-51
SLIDE 51

@piperniehaus

How to structure a large Elm app?

  • It depends™
  • One of the biggest hurdles and biggest FAQs
  • Big files? Small files?
  • Big update loops? Multiple update loops?

¯\_(ツ)_/¯

slide-52
SLIDE 52

@piperniehaus

Agenda

  • About me
  • The promise of Elm
  • The Pivotal Tracker experience

○ Background ○ Types & FP in practice ○ Scaling ■ Puzzle ■ Mindset ○ Testing

  • Is Elm right for you?
slide-53
SLIDE 53

@piperniehaus

File structure puzzle

  • Pure function = less obvious structure
  • Elm apps are broken up into Modules
  • Each file is a module
  • Modules have public (exposed) functions and private functions
slide-54
SLIDE 54

@piperniehaus

Hello World Main.elm

  • Model & Types
  • Update loop
  • View

The first modules Main.elm

  • Model & Types
  • Update loop

View.elm

  • Takes: Model
  • Returns: Html

More modules Main.elm

  • Model & Types
  • Update loop

View.elm

  • Takes: Model
  • Returns: Html

(Etc).elm

slide-55
SLIDE 55

@piperniehaus

Agenda

  • About me
  • The promise of Elm
  • The Pivotal Tracker experience

○ Background ○ Types & FP in practice ○ Scaling ■ Puzzle ■ Mindset ○ Testing

  • Is Elm right for you?
slide-56
SLIDE 56

@piperniehaus

Elm structure mindset

  • Each Tracker Elm app has a different structure
  • We debated

○ Conventions? ○ Top-down structures in advance? ○ Big files?

  • Conclusions

○ Refactor often (for now) ○ Follow guidelines

slide-57
SLIDE 57

@piperniehaus

Ease of refactoring Elm

  • Ease of refactoring Elm allows delay of architectural decisions
  • Compiler makes large files easier to manage
  • We have restructured all Elm projects multiple times
slide-58
SLIDE 58

@piperniehaus

Landing point: Conventional Wisdom +

  • Conventional wisdom:

○ Keep everything together until it starts to clump naturally ○ Break clumps into modules ○ Modules generally structure around a type

  • Tracker addendum:

○ Use tests and module exposures to drive structure

slide-59
SLIDE 59

@piperniehaus

Agenda

  • About me
  • The promise of Elm
  • The Pivotal Tracker experience

○ Background ○ Types & FP in practice ○ Scaling ○ Testing ■ Elm language ■ Elm application ○ JavaScript interop

  • Is Elm right for you?
slide-60
SLIDE 60

@piperniehaus

Testing in Elm

The myth:

  • If it compiles, it works

The reality:

  • The elm compiler catches many errors
  • Testing business logic is still important

The compiler prevents using a String where we need an Int, but it can’t prevent using the wrong Int all together.

slide-61
SLIDE 61

@piperniehaus

Test/Type Driven Development (TDD)

  • Use compiler failures AND tests to drive code
  • Compiler ensures that code will always run
  • Tests ensure that code will fulfill business logic
slide-62
SLIDE 62

@piperniehaus

slide-63
SLIDE 63

@piperniehaus

slide-64
SLIDE 64

@piperniehaus

slide-65
SLIDE 65

@piperniehaus

Agenda

  • About me
  • The promise of Elm
  • The Pivotal Tracker experience

○ Background ○ Scaling ○ Testing ■ Elm language ■ Elm application ○ JavaScript interop

  • Is Elm right for you?
slide-66
SLIDE 66

@piperniehaus

Testing phase 1

The first modules Main.elm

  • Model & Types
  • Update loop

View.elm

  • Takes: Model
  • Returns: Html

Tests here Not here

slide-67
SLIDE 67

@piperniehaus

Testing the update loop

  • Update loop is the main logic of the app
  • Pure functional makes testing easier
  • Elm architecture makes testing resultant updates hard
slide-68
SLIDE 68

@piperniehaus

Testing HTML

  • We test HTML output via Happy Path integration tests

○ Testing HTML is brittle

  • We don’t test the view

○ Much debate ○ Testing view output in Elm is cumbersome

slide-69
SLIDE 69

@piperniehaus

Selector pattern

The first modules Main.elm

  • Update function
  • Model & Types

Selector.elm

  • Takes: Model
  • Returns: Selector

View.elm

  • Takes: Selector
  • Returns: Html

Tests here Tests here

slide-70
SLIDE 70

@piperniehaus

Selectors

  • Middle layer between model and view
  • Computed, not stored
  • “View state”

Model

  • Stored

application state Selector

  • Calculated state

View

  • HTML based on

selector calculations

slide-71
SLIDE 71

@piperniehaus

Elm tests driving structure

  • If no external modules use a function, don’t expose it
  • If a module exposes a function, test it
  • If an unexposed function feels like it needs testing, make a new module

and expose it

slide-72
SLIDE 72

@piperniehaus

Agenda

  • About me
  • The promise of Elm
  • The Pivotal Tracker experience

○ Background ○ Scaling ○ Testing ○ JavaScript interop

  • Is Elm right for you?

○ It depends™ ○ Think like an elm developer

slide-73
SLIDE 73

@piperniehaus

JavaScript interop

  • Elm sends messages to and from JavaScript

○ Ports ○ Native code (EEK!)

  • Multi-language code base
slide-74
SLIDE 74

@piperniehaus

Agenda

  • About me
  • The promise of Elm
  • The Pivotal Tracker experience

○ Background ○ Scaling ○ Testing ○ JavaScript interop ■ Background ■ Multi-language code base

  • Is Elm right for you?

○ It depends™ ○ Think like an elm developer

slide-75
SLIDE 75

@piperniehaus

Background on JS interop

  • Ports

○ Recommended ○ Hooks into the update loop

  • “Native code”

○ Not recommended ○ Less safe

slide-76
SLIDE 76

@piperniehaus

What’s a port?

Elm app Outgoing Update loop sends a Cmd to contact JS via a port Incoming: Subscribe to the port, Msg enters the update loop JavaScript Incoming: Subscribe to the port, get the message, do the thing Outgoing Send to a port in Elm

slide-77
SLIDE 77

@piperniehaus

Good:

  • Anything JS can do, Elm can do
  • More libraries
  • Communication via JSON
  • In and out of type safety
  • Multiple languages in your

codebase

Meh:

slide-78
SLIDE 78

@piperniehaus

“Native” code

  • Very discouraged, hacky way of wrapping native (JS) code in Elm to create

Elm libraries

  • Won’t work in Elm 0.19
slide-79
SLIDE 79

@piperniehaus

Agenda

  • About me
  • The promise of Elm
  • The Pivotal Tracker experience

○ Background ○ Scaling ○ Testing ○ JavaScript interop ■ Background ■ Multi-language code base

  • Is Elm right for you?

○ It depends™ ○ Think like an elm developer

slide-80
SLIDE 80

@piperniehaus

Elm devs support multiple languages long-term

  • Elm is growing but lacks libraries

○ Need to maintain Ports long term

  • Transition to Elm is gradual

○ During the transition, you’ll need Elm and JS to still work

  • Transition may not be the goal
slide-81
SLIDE 81

@piperniehaus

Issues with supporting multiple languages

  • Developers need proficiency in multiple languages
  • Same code in multiple languages?
  • Dependent on libraries and webpack knowledge

○ React-elm-components doesn’t work with React 16

  • “Native” libraries will disappear in next Elm version
slide-82
SLIDE 82

@piperniehaus

Agenda

  • About me
  • The promise of Elm
  • The Pivotal Tracker experience
  • Is Elm right for you?

○ It depends™ ○ Think like an elm developer

slide-83
SLIDE 83

@piperniehaus

:)

  • Coding feels good
  • Learning
  • Excitement
  • High productivity after

ramp up

  • Easy refactors

As a developer... :(

  • Need to know multiple

languages

  • Port / JS complexity
  • Longer ramp-up
slide-84
SLIDE 84

@piperniehaus

:)

  • Time travel debugger
  • No runtime exceptions

As a product owner or tester... :(

  • Potential higher cost for

features that require libraries

slide-85
SLIDE 85

@piperniehaus

:)

  • No runtime exceptions

As a user... :(

  • Excitement is the spice
  • f life?
slide-86
SLIDE 86

@piperniehaus

Agenda

  • About me
  • The promise of Elm
  • The Pivotal Tracker experience
  • Is Elm right for you?

○ It depends™ ○ Think like an elm developer

slide-87
SLIDE 87

@piperniehaus

What if Elm isn’t right for you?

Elm learnings can still be important

  • Encode business logic in the type system
  • Make impossible states impossible
  • Minimize side effects to minimize confusion

Culture can compensate for language

  • Similar to TDD
slide-88
SLIDE 88

@piperniehaus

Think like an Elm developer

Language + culture

Code compiles Code runs without errors Code runs without errors Code compiles

slide-89
SLIDE 89

@piperniehaus

Language + Culture

Culture Language Elm Culture Language Kotlin Culture Language Typescript

slide-90
SLIDE 90

@piperniehaus

Cultural shifts

  • Kotlin
  • Typescript
slide-91
SLIDE 91

@piperniehaus

  • Pay attention to warnings

compileKotlin { kotlinOptions.allWarningsAsErrors = true }

  • Be functionally minded (avoid side-effects)
  • Avoid !!

Strong static typing / FP in Kotlin

slide-92
SLIDE 92

@piperniehaus

Compiles with a warning

Bird is missing

slide-93
SLIDE 93

@piperniehaus

  • Be functionally minded
  • Always turn on --strictNullChecks
  • Avoid Any

○ Exception: 3rd party libraries, sometimes

  • Avoid type casting
  • Avoid returns after case statements

Strong static typing / FP in Typescript

slide-94
SLIDE 94

@piperniehaus

Don’t override TypeScript exhaustiveness checking

Adding a return after the case statement ends disables exhaustiveness checking

slide-95
SLIDE 95

@piperniehaus

You should

  • Use Elm
  • Think like an Elm developer
slide-96
SLIDE 96

@piperniehaus

Happy (FUNctional) coding!

pniehaus@pivotal.io