Elm
Funktionale Frontend-Entwicklung
Webmontag Bremen - 21. November 2016
Dennis Reimann - @dennisreimann
Intro
UIEngineering
Frontend -> Elm
Bevor es los geht …
Status Quo
Unterdessen in JavaScript-Land …
Was ist aktuell der heiße Shit?
Warum ist das so?
Komponenten: Reduktion der Komplexität
Deklaratives UI: Zustandslose Funktionen
Lösung für State Management: Flux Pattern
Trend in Richtung Funktionale Programmierung
Pure Functions
Immutability
Statische Typisierung
Pure Functions: Arbeiten nur auf dem Input, keine Effekte!
Effekte: Operationen mit äußeren Zuständen
Testing und Refactoring
Immutability: Keine Variablen!
n ew
p ackages
m onthly
Purity (native)
Functional Style Rambda
Immutability Immutable.js
Deklaratives UI React
State Management Redux
Statische Typisierung Flow / TypeScript
Historie und Legacy, Syntax: ES 2015
Nicht ursprünglich für diesen Zweck gedacht
In JS erfordert der funktionale Stil Disziplin
Es kann trotzdem was schief gehen
Kein Zwang oder Kontrolle
Elm ist …
eine funktionale Programmiersprache
für dynamische Web-Interfaces
statisch typisiert
JavaScript-basiert
fokussiert auf Praktikabilität
Entwickler-freundlich
Pure Functions / Immutability
interoperabel mit JavaScript
Praktischer Einstieg in FP: für JS, nicht für Haskell
Keine esotherischen Konzepte – dennoch Lernkurve!
Wesentliche Punkte:
Compiler
Elm Architektur
Tooling
Compiler
Das Herzstück von Elm
Statische Typisierung
Keine inkonsistente Variablentypen
Keine unsichere Referenzzugriffe
Keine Laufzeitfehler
Zuverlässlichkeit & Wartbarkeit
Unterstützt Entwickler
"undefined is not a function"
Einfachere Refactorings gegenüber JS
Weniger Testing nötig
Entwicklung == Konversation mit dem Kompiler
"Wenn es kompiliert, funktioniert es auch"
Editor vs. Browser: Schnelleres und besseres Feedback
Fehlermeldungen
Die Applikation besteht aus …
Model: Beinhaltet den Zustand
View: Funktion, deren Input das Model ist
Update: Transformiert das Model
Im Wesentlichen drei Teile – plus Runtime/Wiring.
Update: Die einzige Stelle, an der das Model bearbeitet wird
Es gibt nur diesen einen Weg
Model
type alias Model =
{ title : String
, talks : List Talk
}
type alias Talk =
{ title : String
, speaker : String
, description : Maybe String
, showDetails : Bool
}
Typdefinitionen
Maybe: Alles in Elm hat einen Typ (auch `null`)
initialModel : Model
initialModel =
{ title = "Webmontag IV/2016"
, talks = todaysTalks
}
todaysTalks : List Talk
todaysTalks =
[ { title = "Was, wie und warum - Die Gambio Shopsoftware"
, speaker = "Lennard Kläfker und Daniel Wu"
, description = (Just "Die Geschichte unserer Software …" )
, showDetails = False
}
, { title = "Elm – Funktionale Frontend-Entwicklung"
, speaker = "Dennis Reimann"
, description = Nothing
, showDetails = False
}
]
View
view : Model -> Html Msg
view model =
div [ class "wrapper" ]
[ h1 [ class "title" ] [ text model.title ]
, ul [ class "talks" ] (List .map viewTalk model.talks)
]
viewTalk : Talk -> Html Msg
viewTalk talk =
li
[ onClick (ToggleDetails talk) ]
[ text talk.title
, div
[ hidden (not talk.showDetails) ]
[ text (talk.speaker ++ ": " )
, text (Maybe .withDefault "keine Beschreibung" talk.description)
]
]
Update
type Msg
= ToggleDetails Talk
update : Msg -> Model -> Model
update msg model =
case msg of
ToggleDetails talk ->
let
updateTalk t =
if t == talk then
{ t | showDetails = (not talk.showDetails) }
else
t
in
{ model | talks = List .map updateTalk model.talks }
Iterierung, Map vs. Zugriff auf Array
Boilerplate
module Main exposing (..)
import Html exposing (..)
import Html.Events exposing (onClick)
import Html.Attributes exposing (class, hidden)
main : Program Never Model Msg
main =
Html .beginnerProgram
{ model = initialModel
, view = view
, update = update
}
Behandelt Effekte
Effekte als Daten: Bspw. AjAX
Effect Managers: Bspw. Websockets oder GraphQL
Runtime: JavaScript Interoperability
Only one way to do it
Skalierung und Modularität
elm-package
Erzwingt Semantic Versioning
Breaking Changes erfordern Major Version Bump
Diffs von Versionen anzeigen
NPM Äquivalent
elm-package erlaubt sonst kein publish
elm-package diff NoRedInk/elm-rails 2.0.0 3.0.0
elm-format
Formatiert Code entsprechend Community Standard
Keine Code Style-Debatten: Überall konsistent
Developer Experience:
Man findet sich direkt zurecht
Übernimmt Fleißarbeit beim Upgrade
Zusammenspiel mit TEA
Vergleich Rails: Convention over Configuration
elm-css
Funktionen die zu CSS kompilieren
Typsicher und vom Compiler gecheckt
Variablen und Mixins
Nur verfügbare Properties
Debugger
Export und Import für State und Event-Abläufe
Wiederholung, um Bugs zu reproduzieren
Zustand an jeder Stelle einsehbar
Demo
Gotchas
Lernkurve:
Funktionale Programmierung, neue Paradigmen
Syntax und statische Typisierung
Compiler erschwert Prototyping
Recht junges Ökosystem
(Noch) kein Server-Side Rendering
Keine Private Packages
Standard-Library sehr klein: Kaum Lernaufwand
Was mag ich an Elm?
Es geht nicht um das was die Sprache bietet, sondern um das, was sie weglässt
Elm Architektur: Einfache und solide Basis
Developer Experience: Best Practices eingebacken
Community und Ansatz, siehe Code is the easy part
Developer Experience
One way to do it – extrem gut unterstützt
Testing einfach
Community und Approach
Moving fast
Focus: simplicity
Warum Elm?
Selbst wenn man Elm nicht praktisch nutzt, gibt es eine Menge daraus zu lernen!
"It can't be unseen"
Elm macht dich zu einem besseren JavaScripter
Praktischer Einsteg in Funktionale Programmierung
FP zunehmend wichtig
State Management ist eins der größten Probleme
Keine schnelleren CPUs, aber mehr Kerne: Immutability wichtig
Danke!
dennisreimann.de/talks/elm.html
@dennisreimann
React: 135K (minified) / 43K (gzipped)
Elm: 80K / 25K
Vue: 63K / 23K
UI engineering Podcast