Peter Christensen

  • Presentations
  • Contact Me

#sfcljs August Meetup – Om vs Reagent vs Quiescent, Converting to Om

August 25, 2014 by Peter Leave a Comment

[UPDATE: Added links to slides for some of the talks]

ClojureScript is my new toy, so I was glad to see the San Francisco ClojureScript Meetup plan a new event, and all of the talks were about Om, which made it even better. It was a great event at Etsy’s SF office. Thanks to Melissa and Sean Grove for organizing it!

Here are my notes:

  • http://www.meetup.com/SF-Clojurescript-Meetup/events/201007552/
  • Official Meetup Hashtag: #sfcljs – https://twitter.com/search?q=%23sfcljs
  • Etsy (host) is hiring: https://www.etsy.com/careers/
  • Diogo
    • Slides: http://htmlpreview.github.io/?https://github.com/diogo149/om-no/blob/master/notes.html
    • Project: Social network with data mining, in stealth
      • switched from Om to Reagent
      • hit a wall after 5k+ LOC, months
    • What was good about Om
      • Global undo – really easy, but didn’t apply to the app
      • One atom to contain global app state
    • The Bad
      • reify and build/build-all was error prone – you have to keep straight which fns return reified functions and which are normal
      • API is verbose
        • he built syntactic sugar for it, but that shows weakness with API
      • Too slow – much slower than Angular JS
      • No anonymous fns as components
        • didn’t throw error messages, just re-mounted and caused site to flicker
      • Can’t compose components, because components track their parent
      • Cursors – pointers into app state
        • async transact! can change the value or order of the app state, making the cursor point to the wrong data
      • Local state mixed with global state
        • you can’t wholesale replace new app state, b/c you don’t know where it’s mixed with local state that you would lose
      • cursors behave like maps
        • you can pass maps like cursors, except for when you want to transact!
      • Need to Know principle
        • In React, components work best when they know as little as possible, so they don’t re-render for unnecessary changes
        • In Om, app state is a tree, so you need knowledge of lowest common ancestor
        • same data in multiple places
      • hard to be both consistent and performant
    • Reagent
      • principle of least surprise
      • more Clojure-y – lazy components, normal functions,
      • data model works better with React.js
      • easier to work with data as a direct acyclic graph
      • We were able to teach a new employee the codebase without knowledge of app or Reagent – testament of a good API
      • Simpler for small apps, more scaleable for large apps
    • Reagent – https://github.com/holmsand/reagent
  • Anton – http://textik.com/
    • Slides: http://www.slideshare.net/AntonAstashov/textik
    • ASCII diagram generator
    • Pet project, so he needed something he could build in an hour a day
    • Normal design of front-end web apps
      • observe changes in view models by any other observer models, sometimes cascading
      • Works well, but hard to figure out what happened in exception
      • Many inputs, many code paths
    • Prefer one-way flow of events → data → rendering → events
      • One global code path
      • Full state of the app when exceptions happen
    • Like React for fast view layer, use Quiescent for cljs
      • lightweight, ~200 LOC
      • Simple
      • Opinionless
    • Cons
      • slowly developing – few recent commits, pending pull requests
      • you have to maintain your own fork for e.g. animations
      • Has bugs that are fixed in Om
    • Lifecycle
      • Init – call Render
      • View – render, register event handlers that send payload to core.async channel
        • core.async used b/c you can’t have circular dependencies on namespaces, since view would require dispatch and vice versa
      • Dispatch – listen to channel, call mutators, call render
      • Mutators – change data (only layer where data is changed)
      • Data → return to Dispatch
    • Code – https://github.com/astashov/tixi
    • Minimal app using Quiescent, this architecture – https://github.com/astashov/mintik
    • Quiescent – https://github.com/levand/quiescent
  • Danny from CircleCI – Om From a Designer’s Point of View
    • Does not like writing Om, but likes how everything is in one language, so it’s easier to reason about (vs HAML, CoffeeScript, CSS, etc)
    • Can be harder to find where the data is coming from
    • Only sort of gets the lifecycle, design of components
      • Learning is coming faster than expected
    • Workflow + tools are the same except for a ~10sec delay when making changes
      • Using production data, and has to use the whitespace compiler to produce a single Javascript file
      • Sublime, Chrome Dev tools, etc
    • This is not a natural tool for a designer – most would need someone to help with the more programmery/Clojure-y stuff
    • Syntax for Hiccup etc isn’t a big change from HTML/CSS
    • Could use a more applicable cheat sheet for designers
    • Uses CSS or SVG animations
    • Surprised by React making assumptions/transformations on markup – e.g. moving an anchor to be a sibling of inline tag, from inside of it
    • Design process would be easier if he ran a local dev environment, but that’s a big new dependency that requires maintenance
  • Daniel from CircleCI – Converting a Site from Knockout to Om
    • Can now use CircleCI for open source projects – free container, public build pages
    • Open sourced front-end code: https://github.com/circleci/frontend
      • You connect to your own CircleCI backend data, so you can push changes/fixes to be merged into the main, public repo, while protecting your data
      • Still working out details of the open source workflow
    • (this was more showing code than presentation)
    • Old site used Knockout.js, 2-way data binding
      • data binding in JS, HAML-coffee templates in CoffeeScript, etc, so there were language mismatches, string interpolation
    • Converter from HAML-coffee to Hiccup – not perfect, but close enough
      • Difference between whitespace automatically included vs required
    • Event handlers put messages into core.async channels
    • Took about 2.5 months full time development to convert
    • How it works
      • All state is serializable in a single Atom
      • Build messages – something we know about the build that we want to tell you (~100 messages)
        • Gave a representative sample of serialized state to designer
      • In theory you can store and replay messages to rebuild state
      • core.async – e.g. Stripe checkout – complete/cancel puts message into channel, and the page blocks on that
    • Problems with Om
      • haven’t figured out testing, still just using webdriver tests
      • Rendering too much to the virtual DOM – parents have to know about child data, even if they don’t need it
        • hasn’t been too big a problem yet
      • Slow enough that you can drop characters on input, because of how much rendering goes on when everything is in global app state
        • More of a problem in tests
        • Needed to pull input data out of app state and into local component state

Filed Under: Clojure, Programming

Leave a Reply

You must be logged in to post a comment.

Categories

  • Blog
  • Book Review
  • Business
  • Clojure
  • Education
  • Emacs
  • Fun
  • iOS
  • Lisp
  • Personal Sprints
  • Pictures
  • Polyphasic
  • Presentations
  • Programming
  • Rails
  • Startups
  • Uncategorized

Copyright © 2025 · Minimum Pro Theme on Genesis Framework · WordPress · Log in