My study project for the month is the Pedestal web app library by Cognitect. I’ve mentioned it before, but it’s worth repeating: the best page to understand what Pedestal is for is What I’ve Learned About Making ClojureScript Applications With Pedestal by Tero Parviainen. This provides the big picture whats and whys that the tutorial doesn’t (or doesn’t begin with). EVERYONE thinking of going through the tutorial should read this first.
Another great resource for understanding Pedestal, including seeing it in action, is Brenton Ashworth‘s talk from Strangeloop 2013: Web Apps in Clojure+ClojureScript with Pedestal. It’s a 39 minute video with slides and demos, which is still a lot less to bite of than the 8-12 hours to work through the whole Pedestal tutorial. I’ve posted my notes on the talk below, hopefully someone else will find them useful.
Thanks Brenton and Cognitect for all the great Clojure work and outreach!
- What type of app
- Designed for interactive, 2 way transfer of info
- Receive inputs from multiple source (not just the user UI)
- Coordinate events on the client
- Large, long-running applications
- Other libs/frameworks depend on mutation, OO concepts, not functional
- Example app – sales funnel, real-time shopper progression + reaction, process 1000 events/sec, update browser 2x/sec
- How do we control it? – Pedestal
- Separation of concerns – rendering/information model+logic/services, communicate by messages + queues
- rendering, information model & logic, services
- Information model – standard way to organize and store data
- data stored in a tree of nested maps, so a list of symbols is a tree traversal to a piece of data
- basis and derived information
- some information so support the UI
- State transition model – an orderly succession of states from one input to a new output
- associate cause (incoming message) to effect (new state)
- prefer to store state in one atom that you can watch, monitor, etc
- Pedestal provides fine-grained change reporting to make lots of data in one atom manageable
- Dataflow – disconnect functions from how they are executed
- declarative inputs and outputs
- automatic minimal propagation
- no explicit pub/sub or conditionals
- great way to encode data dependencies
- promotes adding code instead of updating code – small focused functions that you can recombine instead of tweaking conditionals
- 21:10 – walkthrough of a dataflow event
- 22:50 – walkthrough of a roundtrip through event, message, info model, rendering
- Separation of concerns – rendering/information model+logic/services, communicate by messages + queues
- Demo app – everything runs in web workers, except only UI which runs on the main thread
- 25:15 core.async
- Good advice: “If Rich Hickey announces he’s working on something related to what you’re doing, just wait for him to be ready.”
- allows you to program in the browsers as if you had real blocking threads
- current message processing – change message, map message to function, call function, queue return message
- new message processing – inform channel – map message to function, call function, return transform messages
- inform message: “Here’s how I changed”
- transform message: “Here’s how I’d like you to change”
- 28:25 Future Pedestal structure
- view → event → inform mesage → fn → transform message → deterministically update information model → UI change messages → UI change fns
- allows you to encapsulate changes in widgets, as long as they can handle inform/transform messages
- widgets aren’t limited to UI – it can also encapsulate communication with external services
- Q&A
- shouldn’t be a problem to have a Javascript API that you can plug into
- core.async doesn’t make it harder to test the declared dataflow functions
- functions don’t need to be aware of the channels sending the messages
- You can also write functions that return a channel if the API you’re calling is fast
- messages can be stored & replayed to replicate rendering scenarios
- Clojure provides code and structure to get code into webworkers, it’s configurable
- you can setup channels to correspond to UI/webworker boundaries
- The declared inputs/outputs let you test beforehand that you don’t have infinite loops
- It feels quite natural if you are familiar with Clojure principles
Leave a Reply
You must be logged in to post a comment.