Slide 1

Slide 1 text

@Jack_Franklin, bit.ly/elm-polyconf 1

Slide 2

Slide 2 text

! @Jack_Franklin, bit.ly/elm-polyconf 2

Slide 3

Slide 3 text

@Jack_Franklin, bit.ly/elm-polyconf 3

Slide 4

Slide 4 text

@Jack_Franklin @Jack_Franklin, bit.ly/elm-polyconf 4

Slide 5

Slide 5 text

@Jack_Franklin, bit.ly/elm-polyconf 5

Slide 6

Slide 6 text

@Jack_Franklin, bit.ly/elm-polyconf 6

Slide 7

Slide 7 text

@Jack_Franklin, bit.ly/elm-polyconf 7

Slide 8

Slide 8 text

The great tooling problem @Jack_Franklin, bit.ly/elm-polyconf 8

Slide 9

Slide 9 text

We must accept that complex applications are hard to build @Jack_Franklin, bit.ly/elm-polyconf 9

Slide 10

Slide 10 text

Trends in Complex JavaScript Applications @Jack_Franklin, bit.ly/elm-polyconf 10

Slide 11

Slide 11 text

Two Way Data Binding @Jack_Franklin, bit.ly/elm-polyconf 11

Slide 12

Slide 12 text

Object.observe @Jack_Franklin, bit.ly/elm-polyconf 12

Slide 13

Slide 13 text

MVC / MVVC / MCVCVMMCVCCC @Jack_Franklin, bit.ly/elm-polyconf 13

Slide 14

Slide 14 text

"Let's replicate Rails" @Jack_Franklin, bit.ly/elm-polyconf 14

Slide 15

Slide 15 text

We can do better @Jack_Franklin, bit.ly/elm-polyconf 15

Slide 16

Slide 16 text

Explicit, component based approach @Jack_Franklin, bit.ly/elm-polyconf 16

Slide 17

Slide 17 text

@Jack_Franklin, bit.ly/elm-polyconf 17

Slide 18

Slide 18 text

Components in some form • Angular 2 • Ember • Vue.js • Cycle.js • React @Jack_Franklin, bit.ly/elm-polyconf 18

Slide 19

Slide 19 text

Who actually likes JavaScript these days?! @Jack_Franklin, bit.ly/elm-polyconf 19

Slide 20

Slide 20 text

Explicit about state @Jack_Franklin, bit.ly/elm-polyconf 20

Slide 21

Slide 21 text

Single source of truth @Jack_Franklin, bit.ly/elm-polyconf 21

Slide 22

Slide 22 text

Views represent state view(state) => HTML @Jack_Franklin, bit.ly/elm-polyconf 22

Slide 23

Slide 23 text

View functions are pure view(state1) => HTML1 view(state1) => HTML1 view(state2) => HTML2 @Jack_Franklin, bit.ly/elm-polyconf 23

Slide 24

Slide 24 text

Explicitly define all actions that can modify state function addTodo() { return { type: 'USER_ADD_TODO', text: 'Buy Milk' } } @Jack_Franklin, bit.ly/elm-polyconf 24

Slide 25

Slide 25 text

Have update functions that can handle actions update(action, state) => newState @Jack_Franklin, bit.ly/elm-polyconf 25

Slide 26

Slide 26 text

update encapsulates most business logic @Jack_Franklin, bit.ly/elm-polyconf 26

Slide 27

Slide 27 text

Unidirectional Data Flow user clicks -> action -> update(action, state) -> view(newState) @Jack_Franklin, bit.ly/elm-polyconf 27

Slide 28

Slide 28 text

Recommended Reading ➡ Unidirectional User Interface Architectures by André Staltz @Jack_Franklin, bit.ly/elm-polyconf 28

Slide 29

Slide 29 text

@Jack_Franklin, bit.ly/elm-polyconf 29

Slide 30

Slide 30 text

Explicit vs Magic @Jack_Franklin, bit.ly/elm-polyconf 30

Slide 31

Slide 31 text

Magic! function setNewUser(name) { $scope.user = { name : 'jack' }; } @Jack_Franklin, bit.ly/elm-polyconf 31

Slide 32

Slide 32 text

Explicit! function update(action, state) { switch (action.type) { case 'NEW_USER': return Object.assign({}, state, { user: { name: action.name } }); } } @Jack_Franklin, bit.ly/elm-polyconf 32

Slide 33

Slide 33 text

Even more explicit! type Msg = NewUser String | LogOut @Jack_Franklin, bit.ly/elm-polyconf 33

Slide 34

Slide 34 text

Even more explicit because the compiler says so update msg model = case msg of NewUser name -> { model | user = name } This `case` does not have branches for all possibilities. 22|> case msg of You need to account for the following values: LogOut Add a branch to cover this pattern! @Jack_Franklin, bit.ly/elm-polyconf 34

Slide 35

Slide 35 text

@Jack_Franklin, bit.ly/elm-polyconf 35

Slide 36

Slide 36 text

Elm: a language to solve these problems. @Jack_Franklin, bit.ly/elm-polyconf 36

Slide 37

Slide 37 text

Elm, my Dear Watson -- Sherlock Holmes @Jack_Franklin, bit.ly/elm-polyconf 37

Slide 38

Slide 38 text

Not the finished article @Jack_Franklin, bit.ly/elm-polyconf 38

Slide 39

Slide 39 text

Not the perfect language (yet?!) @Jack_Franklin, bit.ly/elm-polyconf 39

Slide 40

Slide 40 text

Not the perfect solution to all our problems @Jack_Franklin, bit.ly/elm-polyconf 40

Slide 41

Slide 41 text

No runtime errors! @Jack_Franklin, bit.ly/elm-polyconf 41

Slide 42

Slide 42 text

• Functional • Typed • Compiled @Jack_Franklin, bit.ly/elm-polyconf 42

Slide 43

Slide 43 text

• Expressive, clear code • Self documenting • Robust @Jack_Franklin, bit.ly/elm-polyconf 43

Slide 44

Slide 44 text

Learning curve ahead! @Jack_Franklin, bit.ly/elm-polyconf 44

Slide 45

Slide 45 text

Expressive, clear code @Jack_Franklin, bit.ly/elm-polyconf 45

Slide 46

Slide 46 text

Functional Programming add(1, 2) (add 1 2) List.map (\x -> x + 2) [1, 2, 3, 4] List.map ((+) 2) [1, 2, 3, 4] @Jack_Franklin, bit.ly/elm-polyconf 46

Slide 47

Slide 47 text

Pipes incrementWeight (incrementHeight (incrementAge (makePerson "jack"))) makePerson "jack" |> incrementAge |> incrementHeight |> incrementWeight @Jack_Franklin, bit.ly/elm-polyconf 47

Slide 48

Slide 48 text

Clean syntax incrementAge person = { person | age = person.age + 1 } add x y = x + y addTwo = add 2 @Jack_Franklin, bit.ly/elm-polyconf 48

Slide 49

Slide 49 text

Self documenting @Jack_Franklin, bit.ly/elm-polyconf 49

Slide 50

Slide 50 text

Types add : Int -> Int -> Int isEven : Int -> Bool @Jack_Franklin, bit.ly/elm-polyconf 50

Slide 51

Slide 51 text

Union Types type Filter = ShowAll | ShowCompleted | ShowActive showTodos : Filter -> List Todo -> List Todo showTodos filter todos = case filter of ShowAll -> todos ShowCompleted -> List.filter (\t -> t.complete) todos ShowActive -> List.filter (\t -> not t.complete) todos @Jack_Franklin, bit.ly/elm-polyconf 51

Slide 52

Slide 52 text

Union Types ! They can be checked by the compiler (typos are spotted) ! Compiler ensures all are dealt with in case ... of ! Easy to change / add a new one: add it and fix each compiler error! @Jack_Franklin, bit.ly/elm-polyconf 52

Slide 53

Slide 53 text

Type aliases type alias Person = { name : String , age : Int } incrementAge : Person -> Person incrementAge person = { person | person.age = person.age + 1 } @Jack_Franklin, bit.ly/elm-polyconf 53

Slide 54

Slide 54 text

! Clearer code, typed in your domain specific objects. ! Compiler can guarantee you're meeting the type requirements. ! No more 'undefined is not a function' ! @Jack_Franklin, bit.ly/elm-polyconf 54

Slide 55

Slide 55 text

type alias Person = { name : String , age : Int } @Jack_Franklin, bit.ly/elm-polyconf 55

Slide 56

Slide 56 text

Robust @Jack_Franklin, bit.ly/elm-polyconf 56

Slide 57

Slide 57 text

Immutability brings guarantees var person = { name: 'Jack', age: 24 }; incrementAge(person); // has this mutated? // does it return a new person? // #javascript @Jack_Franklin, bit.ly/elm-polyconf 57

Slide 58

Slide 58 text

Sweet, sweet Elm let person = { name = "Jack", age = 24 } in incrementAge person ! person is untouched ! incrementAge has to return a new person ! goodbye mutation bugs @Jack_Franklin, bit.ly/elm-polyconf 58

Slide 59

Slide 59 text

Modules ! Everything is scoped ! Modules explicitly declare what they expose ! Modules explicitly declare what they import @Jack_Franklin, bit.ly/elm-polyconf 59

Slide 60

Slide 60 text

Dealing with nothing No more null. @Jack_Franklin, bit.ly/elm-polyconf 60

Slide 61

Slide 61 text

Maybe type Maybe a = Just a | Nothing It's either Just some value, or Nothing. @Jack_Franklin, bit.ly/elm-polyconf 61

Slide 62

Slide 62 text

Maybe type alias Model = { user : Maybe User } view : Model -> Html Msg view model = case model.user of Nothing -> div [] [ text "No user!" ] Just user -> div [] [ text ("Logged in as " ++ user.name) ] @Jack_Franklin, bit.ly/elm-polyconf 62

Slide 63

Slide 63 text

You must handle all cases of missing / pending data @Jack_Franklin, bit.ly/elm-polyconf 63

Slide 64

Slide 64 text

Task A module for async actions that might fail (HTTP). Task errType successType Task String User - if it fails, fail with a String - if it succeeds, succeed with a User @Jack_Franklin, bit.ly/elm-polyconf 64

Slide 65

Slide 65 text

You have to deal with errors. Task doesn't let you not. (We'll come back to this later). @Jack_Franklin, bit.ly/elm-polyconf 65

Slide 66

Slide 66 text

Commands and Subcriptions • Cmd : an async thing that Elm should run for you • Sub : a subscription to some data you care about that might change (We'll come back to these). @Jack_Franklin, bit.ly/elm-polyconf 66

Slide 67

Slide 67 text

Adjustment time This does take time to get used to • Syntax • Types • Immutablility • Compiling! • Maybe and explicit error handling @Jack_Franklin, bit.ly/elm-polyconf 67

Slide 68

Slide 68 text

When you apply a pattern everywhere it ends up becoming a guarantee: that 100% of your code will follow that pattern. Once you have that guarantee you can build powerful developer tools or cross module features. -- Everywhereness as a Foundation, André Staltz @Jack_Franklin, bit.ly/elm-polyconf 68

Slide 69

Slide 69 text

The Elm compiler make sure that 100% of your code is thoroughly checked against corner cases and error cases. This everywhereness becomes a guarantee. And it is only because of this guarantee that Elm programs have virtually no runtime errors. -- Everywhereness as a Foundation, André Staltz @Jack_Franklin, bit.ly/elm-polyconf 69

Slide 70

Slide 70 text

The Elm Architecture @Jack_Franklin, bit.ly/elm-polyconf 70

Slide 71

Slide 71 text

The three parts: model : Model view : Model -> Html Msg update : Msg -> Model -> Model @Jack_Franklin, bit.ly/elm-polyconf 71

Slide 72

Slide 72 text

@Jack_Franklin, bit.ly/elm-polyconf 72

Slide 73

Slide 73 text

Counter @Jack_Franklin, bit.ly/elm-polyconf 73

Slide 74

Slide 74 text

First, define your Model type alias Model = Int initialModel : Model initialModel = 0 @Jack_Franklin, bit.ly/elm-polyconf 74

Slide 75

Slide 75 text

Secondly, define your Msgs type Msg = Increment | Decrement @Jack_Franklin, bit.ly/elm-polyconf 75

Slide 76

Slide 76 text

Thirdly, define your update: update : Msg -> Model -> Model update msg model = case msg of Increment -> model + 1 Decrement -> model - 1 @Jack_Franklin, bit.ly/elm-polyconf 76

Slide 77

Slide 77 text

Fourthly, define your view: view : Model -> Html Msg view model = div [] [ button [ onClick Decrement ] [ text "-" ] , div [] [ text (toString model) ] , button [ onClick Increment ] [ text "+" ] ] @Jack_Franklin, bit.ly/elm-polyconf 77

Slide 78

Slide 78 text

Finally, hook it all up! main = Html.App.beginnerProgram { model = initialModel , view = view , update = update } @Jack_Franklin, bit.ly/elm-polyconf 78

Slide 79

Slide 79 text

@Jack_Franklin, bit.ly/elm-polyconf 79

Slide 80

Slide 80 text

! We left the view until last. ! Explained all our logic before the UI. ! Notice how easy update would be to test. @Jack_Franklin, bit.ly/elm-polyconf 80

Slide 81

Slide 81 text

Side Effects @Jack_Franklin, bit.ly/elm-polyconf 81

Slide 82

Slide 82 text

Explicitly model side effects. Hand off to Elm, it will hand back later. @Jack_Franklin, bit.ly/elm-polyconf 82

Slide 83

Slide 83 text

Commands @Jack_Franklin, bit.ly/elm-polyconf 83

Slide 84

Slide 84 text

Whenever you need to perform some background work, you have to give Elm a command. Elm will go off, perform the command, and call your update function once it's done. @Jack_Franklin, bit.ly/elm-polyconf 84

Slide 85

Slide 85 text

model : Model view : Model -> Html Msg update : Msg -> Model -> (Model, Cmd Msg) @Jack_Franklin, bit.ly/elm-polyconf 85

Slide 86

Slide 86 text

@Jack_Franklin, bit.ly/elm-polyconf 86

Slide 87

Slide 87 text

Fetching someone's GitHub data. @Jack_Franklin, bit.ly/elm-polyconf 87

Slide 88

Slide 88 text

Firstly, define the model: type alias GithubPerson = { name : String , company : String } type alias Model = { username : String , githubPerson : Maybe GithubPerson } @Jack_Franklin, bit.ly/elm-polyconf 88

Slide 89

Slide 89 text

Secondly, define your Msgs type Msg = NewGithubData GithubPerson | FetchGithubData | FetchError Http.Error @Jack_Franklin, bit.ly/elm-polyconf 89

Slide 90

Slide 90 text

Thirdly, define your update (and note the new type) update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case msg of FetchError error -> -- deal with error here in reality NewGithubData person -> ( { model | githubPerson = Just person }, Cmd.none ) FetchGithubData -> ( model, fetchGithubData model.username ) @Jack_Franklin, bit.ly/elm-polyconf 90

Slide 91

Slide 91 text

NewGithubData person -> ( { model | githubPerson = Just person }, Cmd.none ) -- Cmd.none === do nothing FetchGithubData -> ( model, fetchGithubData model.username ) --- fetchGithubData returns a command --- which Elm will run for us @Jack_Franklin, bit.ly/elm-polyconf 91

Slide 92

Slide 92 text

@Jack_Franklin, bit.ly/elm-polyconf 92

Slide 93

Slide 93 text

Fourthly, define your view: view : Model -> Html Msg view model = case model.githubPerson of Just person -> div [] [ text (person.name ++ ", " ++ person.company) ] Nothing -> div [] [ button [ onClick FetchGithubData ] [ text "Load!" ] ] @Jack_Franklin, bit.ly/elm-polyconf 93

Slide 94

Slide 94 text

Fifthly (new step), define your init: initialModel : Model initialModel = { username = "jackfranklin" , githubPerson = Nothing } init : ( Model, Cmd Msg ) init = ( initialModel, Cmd.none ) @Jack_Franklin, bit.ly/elm-polyconf 94

Slide 95

Slide 95 text

Finally, hook it all together! main = Html.App.program { init = init , view = view , update = update , subscriptions = \_ -> Sub.none } @Jack_Franklin, bit.ly/elm-polyconf 95

Slide 96

Slide 96 text

@Jack_Franklin, bit.ly/elm-polyconf 96

Slide 97

Slide 97 text

@Jack_Franklin, bit.ly/elm-polyconf 97

Slide 98

Slide 98 text

@Jack_Franklin, bit.ly/elm-polyconf 98

Slide 99

Slide 99 text

@Jack_Franklin, bit.ly/elm-polyconf 99

Slide 100

Slide 100 text

@Jack_Franklin, bit.ly/elm-polyconf 100

Slide 101

Slide 101 text

@Jack_Franklin, bit.ly/elm-polyconf 101

Slide 102

Slide 102 text

@Jack_Franklin, bit.ly/elm-polyconf 102

Slide 103

Slide 103 text

That feels like a lot of code / effort! -- All of you. @Jack_Franklin, bit.ly/elm-polyconf 103

Slide 104

Slide 104 text

Boilerplate vs Explicitness @Jack_Franklin, bit.ly/elm-polyconf 104

Slide 105

Slide 105 text

Benefits increase as application grows @Jack_Franklin, bit.ly/elm-polyconf 105

Slide 106

Slide 106 text

Fetching Data • Decoding JSON from an API into an Elm record. • Use Elm's HTTP library to make the request. • Code in the GitHub repo! • Come and grab me if you'd like to see it in person. @Jack_Franklin, bit.ly/elm-polyconf 106

Slide 107

Slide 107 text

http://bit.ly/elm-polyconf @Jack_Franklin, bit.ly/elm-polyconf 107

Slide 108

Slide 108 text

Scaling your application @Jack_Franklin, bit.ly/elm-polyconf 108

Slide 109

Slide 109 text

@Jack_Franklin, bit.ly/elm-polyconf 109

Slide 110

Slide 110 text

The Elm Ecosystem @Jack_Franklin, bit.ly/elm-polyconf 110

Slide 111

Slide 111 text

elm reactor Easily run a project in the browser with no tooling required. @Jack_Franklin, bit.ly/elm-polyconf 111

Slide 112

Slide 112 text

@Jack_Franklin, bit.ly/elm-polyconf 112

Slide 113

Slide 113 text

elm package @Jack_Franklin, bit.ly/elm-polyconf 113

Slide 114

Slide 114 text

@Jack_Franklin, bit.ly/elm-polyconf 114

Slide 115

Slide 115 text

Semantic versioning ensured. ~/git/elm-statey > elm package diff Comparing jackfranklin/elm-statey 2.0.0 to local changes... This is a MAJOR change. ------ Changes to module Statey - MAJOR ------ Changed: - makeState : String -> Statey.State + makeState : Statey.State @Jack_Franklin, bit.ly/elm-polyconf 115

Slide 116

Slide 116 text

elm format @Jack_Franklin, bit.ly/elm-polyconf 116

Slide 117

Slide 117 text

There's so much more I haven't covered. @Jack_Franklin, bit.ly/elm-polyconf 117

Slide 118

Slide 118 text

So, why / when should you use Elm? @Jack_Franklin, bit.ly/elm-polyconf 118

Slide 119

Slide 119 text

You're fed up of undefined function errors that take up loads of time @Jack_Franklin, bit.ly/elm-polyconf 119

Slide 120

Slide 120 text

You're fed up of packages on npm breaking semantic versioning @Jack_Franklin, bit.ly/elm-polyconf 120

Slide 121

Slide 121 text

You want to develop with the confidence of Types and a clever compiler to back you up @Jack_Franklin, bit.ly/elm-polyconf 121

Slide 122

Slide 122 text

You're happy to "ride the wave" and deal with a language still growing and settling down @Jack_Franklin, bit.ly/elm-polyconf 122

Slide 123

Slide 123 text

You're happy to build more packages than depend on existing solutions which may not exist in Elm @Jack_Franklin, bit.ly/elm-polyconf 123

Slide 124

Slide 124 text

But what if this talk has put me off Elm? @Jack_Franklin, bit.ly/elm-polyconf 124

Slide 125

Slide 125 text

Elm does take time to learn, so please don't give up after 30 minutes of slides! guide.elm-lang.org @Jack_Franklin, bit.ly/elm-polyconf 125

Slide 126

Slide 126 text

Elm the language brings many concepts that are language agnostic @Jack_Franklin, bit.ly/elm-polyconf 126

Slide 127

Slide 127 text

The Elm Architecture @Jack_Franklin, bit.ly/elm-polyconf 127

Slide 128

Slide 128 text

Explicitness across your application @Jack_Franklin, bit.ly/elm-polyconf 128

Slide 129

Slide 129 text

Types @Jack_Franklin, bit.ly/elm-polyconf 129

Slide 130

Slide 130 text

Immutability / Functional Programming @Jack_Franklin, bit.ly/elm-polyconf 130

Slide 131

Slide 131 text

Defining your application step by step 1. Define your model. 2. Define your actions. 3. Define your update function. 4. Define your view. 5. Repeat. @Jack_Franklin, bit.ly/elm-polyconf 131

Slide 132

Slide 132 text

Will everyone be writing Elm in 1/2/5 years? @Jack_Franklin, bit.ly/elm-polyconf 132

Slide 133

Slide 133 text

@Jack_Franklin, bit.ly/elm-polyconf 133

Slide 134

Slide 134 text

• guide.elm-lang.org • elm-lang.org/docs • elm-lang.org/community • bit.ly/elm-polyconf • speakerdeck.com/jackfranklin @Jack_Franklin, bit.ly/elm-polyconf 134

Slide 135

Slide 135 text

@Jack_Franklin javascriptplayground.com @Jack_Franklin, bit.ly/elm-polyconf 135

Slide 136

Slide 136 text

@Jack_Franklin, bit.ly/elm-polyconf 136