re-frame/docs/WIP/Mental-Models.md

3.4 KiB

It Does Physics

Remember this diagram from school? The water cycle. Two stages, involving water in different phases, being acted upon by different forces: gravity working one way, evaporation/convection the other.

logo

To understand re-frame, imagine data flowing instead of water. re-frame provides the "conveyance" of the data - the gravity, evaporation and convection. You design what's flowing and then you hang functions off the loop at various points to look after the data's phase changes.

Sure, right now, you're thinking "lazy sods - make a proper Computer Science-y diagram". But, no. Joe Armstrong says "don't break the laws of physics" - I'm sure you've seen the videos - and if he says to do something, you do it (unless Rich Hickey disagrees, and says to do something else). So, this diagram, apart from being a plausible analogy, and bordering on useful, is practically PROOF that re-frame is doing physics.

Finite State Machines

This perspective can be useful ...

Any sufficiently complicated GUI contains an ad hoc, informally-specified, bug-ridden, slow implementation of a hierarchical FSM
-- my eleventh rule (see Greenspun's tenth rule)

Previously, I commented that event handlers (domino 2) collectively represent the "control layer" of the application. They contain logic which interprets arriving events in the context of existing state, and they "step" the application state "forward".

In this way, events act like the triggers in a finite state machine, and the event handlers act like the rules which govern how a the state machine moves from one logical state to the next.

Not every app has lots of logical states, but some do, and if you are implementing one of them, then formally recognising it and using a technique like State Charts will help greatly in getting a clean design and a nice data model.

So, in this section, I'm suggesting that this perspective is useful sometimes:

Events - that's the way we roll.

Dumb Views - Part 1

A lot of events are dispatched by the DOM in response to user actions.

For example, a button view might be like this:

(defn yes-button
  []
  [:div  {:class "button-class"
          :on-click  #(dispatch [:yes-button-clicked])}
          "Yes"])

Notice that on-click DOM handler:

  #(dispatch [:yes-button-clicked])

With re-frame, we want the DOM as passive as possible. We do not want our views containing any imperative control logic. All of that should be computed by event handlers.

We want that "on-click" as simple as we can make it.

Rule: views are as passive and minimal as possible when it comes to handling events. They dispatch pure data and nothing more.

Dumb Views - Part 2

Neither do we want views computing the data they render.
That's the job of a subscription:

So this is bad:

(defn show-items
  []
  (let [sorted-items (sort @(subscribe [:items]))]  ;; <--
    (into [:div] (for [i sorted-items] [item-view i]))))

The view is not simply taking the data supplied by the