- So what was it, Thursday, Friday
- When we woke up to hear the world has changed.
- Open the news on internet.
- Seeing Cameron. Not this one, the sad one.
- Resign from office.
- And what was it, Friday or Saturday when there was this train accident in India with over 200 people dead.
- And the Bituach Leumi. Which is the National insurance institute.
- Very similar to the biblical story of Job. God and Satan had a bet.
- I'm deviating, but I got a letter, as I get every year for the past 7 years.
- Every year they tell me I have debt. Based on the fact that they think that I'm a stay home mom.
- I'm willing to do everything. Everything to prove I'm not a mom.
- And I could go on kids jump overy head. And traffic.
- I guess the world we're leaving in, is probably the reason I love computers so much.
- You start your day. Clean console. No surprises. You have full controll.
gizra
// @amitaibu
- Past 7 years I have been a stay home mom, and/ or cto
Elm
A different approach to frontend webapps
- My goal is to get you excited, and understand you can start using it today.
- Build more easily, stable web apps
- all JS frameworks have in common use JS
- Agree or disagree, but JS is problematic
- If JS ninja ok
- JS is like getting root access to the server. You have too be very disiplined
- Why we have in production: Pragmatic approach - Quickest, cheapest, solid, and keep devs moral
- Bash Angular 1. Elm provides better tools to deal
https://github.com/Gizra/elm-hedley
- What helps us decide to transition from Angular, jump over react to Elm.
- Typical webapp, login, github
- Router
- Maps
- User interactions to filter events
https://github.com/Gizra/elm-spa-example
- Nothing fancy, just login to GitHub, and fetch info.
- But you can go ahead, after the presentation, and after reading the great Elm guide
and learn how to build real apps.
Elm & Elm Architecture
- Language: Compiled, Typed, Immutable, has no side effects, no run time errors
- Set of best practices
- Framework with its own language. It's very opininated
- How to structure your application
- How to connect components
- Model -> Update -> View
- Consists of a few prinicpels
Principle 1: Single source of truth
The state of your whole application is stored in a record tree
- Saw first time it resonated with me
- Redux taking inspiration from Elm
- Angular 1 - where is your state? Router. Services.
- Async nature of JS
- Condition of your webapp
- In case of bugs, hard to reproduce
- Maybe counter intiutive (seperation of concerns) - control webapp
Principle 2: State is read-only
The only way to mutate the state is to emit an action describing what happened
- It's 2016. The root of all evil in this worlds. heart worming, positive, non-cynical,
world - 2 way data binding
- Angular 1 site - Save me so many jQuery lines
- What made us love it, is what we now hate
- If view changes model, chain of actions. Can't control state
- Next something that really got me existed. Ready? Ready?
module Counter exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick)
-- MODEL
type alias Model =
Int
initialModel : Model
initialModel =
0
init : ( Model, Cmd Msg )
init =
( initialModel
, Cmd.none
)
-- UPDATE
type Msg
= Decrement
| Increment
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Decrement ->
( model - 1
, Cmd.none
)
Increment ->
( model + 1
, Cmd.none
)
-- VIEW
view : Model -> Html Msg
view model =
div []
[ button [ onClick Decrement ] [ text "-" ]
, div [] [ text (toString model) ]
, button [ onClick Increment ] [ text "+" ]
]
- Eventhough syntax my look daunting
- Boiler code, Show the essence
- Msg: Angular1 - what actions can you do on your model?
- When I click the button nothing will happen
- Update is the brain of webapp, here we have logic
Model the problem
- With elm, we can really start thinknig from the data structure level
- Elm gives us powerfull tools to model our app
--
type alias User =
{ avatarUrl : String
, name : String
}
viewAvatar : String -> Html a
viewAvatar url =
img [ src url ] []
--
--
type alias User =
{ avatarUrl : String
, name : String
}
viewAvatar : String -> Html a
viewAvatar url =
img [ src url ] []
main = viewAvatar "But this isn't a URL!"
Compile Error Vs Runtime Mistakes
- No Runtime errors in Elm
- Shift as much runtime mistakes to compile time error
type UserType = Anonymous | Pending Integer | Authenticated String
- User type can be either one.
- Pending and Authenticated are wrapping a value.
--
type alias User =
{ avatarUrl : String
, name : String
}
viewAvatar : String -> Html a
viewAvatar url =
img [ src url ] []
--
type Url = Url String
type alias User =
{ avatarUrl : Url
, name : String
}
viewAvatar : Url -> Html a
viewAvatar url =
let
(Url val) = url
in
img [ src val ] []
type Url = Url String
type alias User =
{ avatarUrl : Url
, name : String
}
viewAvatar : Url -> Html a
viewAvatar (Url val) =
img [ src val ] []
--
type alias User =
{ avatarUrl : Url
, name : String
}
emptyUser =
{ avatarUrl = Url ""
, name = ""
}
type alias Model =
{ activePage : Page
, user : User
}
emptyModel =
{ activePage = Login
, user = emptyUser
}
- Example without Maybe. But this is wrong.
type alias Model =
{ activePage : Page
, user : Maybe User
}
emptyModel =
{ activePage = Login
, user = Nothing
}
--
- We know there is no User.
type alias Model =
{ activePage : Page
, user : Maybe User
}
emptyModel =
{ activePage = Login
, user = Just { name = "Amitai"
, avatarUrl = "https://example.com/avatar"
}
}
{-|
* `NotAsked` - We haven't asked for the data yet.
* `Loading` - We've asked, but haven't got an answer yet.
* `Failure` - We asked, but something went wrong. Here's the error.
* `Success` - Everything worked, and here's the data.
-}
type RemoteData e a
= NotAsked
| Loading
| Failure e
| Success a
type alias WebData a =
RemoteData Http.Error a
type alias Model =
{ activePage : Page
, user : WebData User
}
emptyModel =
{ activePage = Login
, user = NotAsked
}
- Using webdata, starting with NotAsked
Learn how to re-think with types
type Language
= English
| Spanish
type TranslationId
= Login
| WelcomeBack { name : String }
type alias TranslationSet =
{ english : String
, spanish : String
}
translations : TranslationId -> TranslationSet
translations id =
case id of
Login ->
{ english = "Please login"
, spanish = "Por favor haga login"
}
WelcomeBack val ->
{ english = "Welcome back " ++ val.name
, spanish = "Bienvenido " ++ val.name
}
translate : Language -> TranslationId -> String
translate lang id =
case lang of
English ->
.english <| translations id
Spanish ->
.spanish <| translations id
- Using webdata, starting with NotAsked
Not everything is in Types
update : Msg -> Model -> Model
update msg model =
case msg of
Decrement ->
model - 1
Increment ->
model + 1
update : Msg -> Model -> Model
update msg model =
case msg of
Decrement ->
let
newModel =
if model < 1 then 0 else model - 1
in
newModel
Increment ->
model + 1
Buisness Logic requires Testing
- Who writes unit tests in JS?
- Who enjoys it?
- For the viewers at home, very few raised there hands, can't blame them
- Probably the same amount of joy and happiness those guys in the back of
Kim Jung Un must be feeling.
- Probably the same amount of joy and happiness those guys in the back of
Kim Jung Un must be feeling.
Unit tests
- What makes unit tests easy Elm
- Time to talk about "Pure functions and side effects"
Pure Functions & Side Effects
- Elm is a black box with no connection to outside world
-- MODEL
type alias Model = Int
-- UPDATE
type Msg
= Fetch
| FetchSucceed Int
| FetchFail Http.Error
- Simple counter example, data from server
- Action - nothing happens by itself
- Code not compiled, for simplicity and brevity
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Fetch ->
( model
, Task.perform FetchFail FetchSucceed (Http.get "https://api.example.com")
)
FetchSucceed count ->
( count, Cmd.none)
FetchFail _ ->
( model, Cmd.none )
- No HTTP happens.
- Encourages us to be better developers
Yeoman Generator
https://github.com/Gizra/generator-elmlang
- Gulp
- browserSync
- Auto-compile
- Sass
- Bundle and Deploy to gh-pages
- Structured app
- Travis integration
- So, I read somewhere that a good presentation should end with a motif that was used in the beginning.
- One of her quotes, and quite incredibly, I feel that it really encapsulats well this session.
- I would kiss a frog even if there were no promise of a Prince Charming popping out of it. I love frogs. I'd lick him.
So what was it, Thursday, Friday
When we woke up to hear the world has changed.
Open the news on internet.