Think like an Elm developer
Piper Niehaus Denver, CO, USA Backpacker / skier Nonprofit board chair
Software Engineer at Pivotal Pivotal Tracker team Elm in Production since 2016 Internal Products and Services team Kotlin
We all get excited about new languages
Production changes everything Bugs matter Testing matters Maintainability matters
Goals The promise (level set) The production hump What s next?
Agenda About me The promise of Elm Background Language Architecture The Pivotal Tracker experience Is Elm right for you?
Elm: A DSL for web apps Language Framework Ecosystem
Elm in production
Elm background Evan Czaplicki s Harvard thesis Now at noredink Elm s Benevolent Dictator For Life
Benevolent dictator for life Design Direction Priorities Pace
Agenda About me The promise of Elm Background Language Architecture The Pivotal Tracker experience Is Elm right for you?
Elm language Elm is a programming language that compiles to JavaScript Pure functional Strong static type system with a friendly compiler
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?
What is a pure function? A function that takes some input and returns output without affecting or being affected by external state
Pure function Impure function Function (arguments) { Computations } Function (arguments) { External state Computations } Return value Return value
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)
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
Elm time travel debugger Because every function in Elm is pure See the system at any state Roll back, roll forward
Time travel debugging
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?
What is a type? An object s type describes Examples: The kind of data in the object What it can do String Int All languages must check types Can t do 1 + two
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
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.
Dynamic typing Code compiles Static typing Code compiles Code compiles Code runs without errors Code runs without errors Strong static typing Code runs without errors
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 or a fish
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
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
Elm s friendly compiler Elm s compiler messages are easy to read Makes it easy to rely on the compiler
Example, a misspelled function name Function addints is defined Oops! We tried to call it but misspelled Compiler error is helpful and friendly
Agenda About me The promise of Elm Background Language Architecture The Pivotal Tracker experience Is Elm right for you?
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
Elm architecture example User makes a change in the UI (onclick) Message is sent to update function View Update New model is passed to view function and rendered in the browser Model Update function returns a new model based on the old model and function arguments
An example
Benefits of the Elm architecture Single source of truth Easy to understand Removes race conditions Model and view stay in sync
Why use Elm? Language Static typing + Architecture Pure functions + Architecture = Few runtime errors
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?
Elm and functional programming at Pivotal Tracker 2017 2016 RoR / React / Backbone Much discussion Dashboard in Elm 2018 New user Project experience Memberships in Elm Page in Elm Kotlin, TypeScript experiments
Elm here!
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
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
Continuing to use Elm mentalities Where else can we apply functional programming and strong types? More Elm? TypeScript? Kotlin?
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?
Elm lives up to its promise Runtime errors Race conditions Easy refactors Mindset change
Encoding business logic into types Example: Managing memberships Project member First name Last name Email Invitee Email
People
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?
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? \_(ツ)_/
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?
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
Hello World The first modules More modules Main.elm Main.elm Main.elm Model & Types Update loop View Model & Types Update loop View.elm Takes: Model Returns: Html Model & Types Update loop View.elm Takes: Model Returns: Html (Etc).elm
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?
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
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
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
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?
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.
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
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?
Testing phase 1 Tests here Not here The first modules Main.elm Model & Types Update loop View.elm Takes: Model Returns: Html
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
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
The first modules Selector pattern Tests here Main.elm Update function Model & Types Selector.elm Tests here Takes: Model Returns: Selector View.elm Takes: Selector Returns: Html
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
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
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
JavaScript interop Elm sends messages to and from JavaScript Ports Native code (EEK!) Multi-language code base
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
Background on JS interop Ports Recommended Hooks into the update loop Native code Not recommended Less safe
What s a port? Elm app JavaScript Outgoing Incoming: Update loop sends a Cmd to contact JS via a port Subscribe to the port, get the message, do the thing Incoming: Outgoing Subscribe to the port, Msg enters the update loop Send to a port in Elm
Good: Anything JS can do, Elm can do More libraries Meh: Communication via JSON In and out of type safety Multiple languages in your codebase
Native code Very discouraged, hacky way of wrapping native (JS) code in Elm to create Elm libraries Won t work in Elm 0.19
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
Elm devs support multiple languages long-term Elm is growing but lacks libraries Transition to Elm is gradual Need to maintain Ports long term During the transition, you ll need Elm and JS to still work Transition may not be the goal
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
Agenda About me The promise of Elm The Pivotal Tracker experience Is Elm right for you? It depends Think like an elm developer
As a developer... :) Coding feels good Learning Excitement High productivity after ramp up Easy refactors :( Need to know multiple languages Port / JS complexity Longer ramp-up
As a product owner or tester... :) Time travel debugger No runtime exceptions :( Potential higher cost for features that require libraries
As a user... :) No runtime exceptions :( Excitement is the spice of life?
Agenda About me The promise of Elm The Pivotal Tracker experience Is Elm right for you? It depends Think like an elm developer
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
Think like an Elm developer Code compiles Code compiles Language + culture Code runs without errors Code runs without errors
Language + Culture Elm Language Kotlin Language Typescript Language Culture Culture Culture
Cultural shifts Kotlin Typescript
Strong static typing / FP in Kotlin Pay attention to warnings compilekotlin { kotlinoptions.allwarningsaserrors = true } Be functionally minded (avoid side-effects) Avoid!!
Compiles with a warning Bird is missing
Strong static typing / FP in Typescript Be functionally minded Always turn on --strictnullchecks Avoid Any Exception: 3rd party libraries, sometimes Avoid type casting Avoid returns after case statements
Don t override TypeScript exhaustiveness checking Adding a return after the case statement ends disables exhaustiveness checking
You should Use Elm Think like an Elm developer
Happy (FUNctional) coding! pniehaus@pivotal.io