Skip to content

Origins

Colin Kahn edited this page Sep 17, 2018 · 1 revision

The ideas that led to the step library began roughly 9 months prior to its development. At that time two articles had caught my interest. The first was by Cognitect employee Jeb Biech1. It was a pair of articles about using state machines in your Re-frame applications and using the state names to drive conditional logic in your UI components. The second article was by a trio of writers, one of them, Jean-Jacques Dubray2, the creator the SAM pattern. Using concepts in TLA+, it showed that using state machines led to approximations and it was not possible to generalize them to every use case.

I had been exploring several different approaches for state management in UIs, such as Redux with various middleware, and reactive patterns using RxJS. Not fully satisfied with either I began to develop my own solution combining the ideas of the aforementioned articles. This eventually led to the Re-state library.

Re-state used a modified version of a state machine map where one or more potential states could be reached from an action. To determine which state was reached each state had associated predicates. With a Re-frame handler modifying the db, the Re-state interceptor would test the predicates of potential next states. The predicate that succeeded would become the new state and be assoc'd into the db. UI components could then use it for their conditional logic.

Around the same time I was starting on a non-ClojureScript project using React. I decided to create a Redux version (middleware and higher-order reducer) that did the same thing as Re-state.

The application was non-trival, with many branching flows in the applications login and other areas. This was relatively easy to model with the declarative transition mappings.

Some time later I started doing research into the structural programming paradigm, how it came about as a response to the use of goto. As I thought more about this in the context of Re-state I felt that I had fractured the mental model that structural programming set out to achieve. The large map of data, with its implementations defined elsewhere, appeared to me as analogous to the goto jumps that structural programming attempted to avoid.

In response I refactored out the Redux middleware from the application, determining (if necessary) what next state should be assoc'd directly in the Redux reducers. The code was more straight-forward while achieving the same results.

About 5 months later I revisited the ideas in Re-state and something became obvious. The benefit of Re-state had been in the up-front declarative mappings of the transitions. By specifying these transitions without affecting their implementation I could achieve the best of both worlds. The small leap to implementing this using Clojure's spec library then came naturally, and the step library was created.


  1. http://blog.cognitect.com/blog/2017/8/14/restate-your-ui-creating-a-user-interface-with-re-frame-and-state-machines
  2. https://dzone.com/articles/the-three-approximations-you-should-never-use-when

Clone this wiki locally