This commit is contained in:
Mike Thompson 2016-10-27 07:05:05 +11:00
parent 46380182fb
commit 189709f65f
4 changed files with 54 additions and 55 deletions

View File

@ -7,12 +7,12 @@ patterns of thought that produced that government are left intact,
then those patterns will repeat themselves. <br>
> -- Robert Pirsig, Zen and the Art of Motorcycle Maintenance
The re-frame docs initially focus on the **domino cascade
The re-frame docs initially focus on the **domino cascade
narrative**. The goal was to efficiently explain the mechanics,
and get you reading and writing code ASAP.
**But** there's other interesting perspectives on re-frame
which will considerably deepen your understanding of its design,
**But** there's other interesting perspectives on re-frame
which will considerably deepen your understanding of its design,
and how to get the best from it.
This tutorial is a tour
@ -29,7 +29,7 @@ choose [Reagent], then we had a problem. It was mid to late 2014.
For all its considerable brilliance, Reagent (+ React)
delivers only the 'V' part of a traditional MVC framework.
But apps involve much more than V. We tend to build quite complicated
But apps involve much more than V. We tend to build quite complicated
apps. Where does the control logic go? How is state stored & manipulated? etc.
We read up on [Pedestal App], [Flux],
@ -38,7 +38,7 @@ emerged. Since then, we've tried to kept an eye on further developments like th
Elm Architecture, Om.Next, BEST, Cycle.js, Redux, etc. They have taught us much
although we have often made different choices.
re-frame does have M, V, and C parts but they aren't objects.
re-frame does have M, V, and C parts but they aren't objects.
It is sufficiently different in nature
from (traditional, Smalltalk) MVC that calling it MVC would be confusing. I'd
love an alternative.
@ -90,36 +90,36 @@ 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 sod - make a proper Computer Science-y diagram". But, no.
Joe Armstrong says "don't break the laws of physics" - I'm sure
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 which encourages
this diagram, apart from being a plausible analogy which encourages
you to look differently at re-frame, is **practically proof** it does physics.
## It does Event Sourcing
How did that exception happen, you puzzle, shaking your head?
What did the user do immediately prior to the exception? What
state was the app in that this event was so disastrous?
How did that error happen, you puzzle, shaking your head ruefully?
What did the user do immediately prior? What
state was the app in that this event was so problematic?
To debug, you need to know this information:
1. the state of the app immediately before the exception
2. What final `event` then caused your app to fall in a screaming mess
2. What final `event` then caused your app to error
Well, with re-frame you need to record (have available):
1. A recent checkpoint of the application state in `app-db` (perhaps the initial state)
2. all the events `dispatch`ed since the last checkpoint, up to the point where the exception occurred
2. all the events `dispatch`ed since the last checkpoint, up to the point where the error occurred
Note: that's all just data. **Pure, lovely loggable data.**
If you have that data, then you can reproduce the exception.
If you have that data, then you can reproduce the error.
re-frame allows you to time travel, even in a production setting.
Install the "checkpoint" state into `app-db`
and then "play forward" through the collection dispatched events.
The only way the app "moves forwards" is via events. "Replaying events" moves you
step by step towards the exception causing problem.
step by step towards the error causing problem.
This is perfect for debugging assuming, of course, you are in a position to capture
an app state checkpoint, and the events since then.
@ -132,7 +132,7 @@ Here's an interesting way of thinking about the re-frame
data flow ...
**First**, imagine that all the events ever dispatched in a
certain running app were stored in a collection.
certain running app were stored in a collection (yes, event sourcing again).
So, if when the app started, the user clicked on button X
the first item in this collection would be the event
generated by that button, and then, if next the user moved
@ -142,16 +142,14 @@ collection of event vectors.
**Second**, remind yourself that the `combining function`
of a `reduce` takes two parameters:
1. the current state of the reduction and
2. the next collection member to fold in.
Then notice that `reg-event-db` event handlers take two parameters too:
Then notice that `reg-event-db` event handlers take two parameters also:
1. `db` - the current state of `app-db`
2. `v` - the next event to fold in
1. `db` - the current state of `app-db`
2. `v` - the next event to fold in
Which is the same as a `combining function` in a `reduce`!!
Interesting. That's the same as a `combining function` in a `reduce`!!
So now we can introduce the new mental model: at any point in time,
the value in `app-db` is the result of performing a `reduce` over
@ -173,16 +171,32 @@ and interesting mental model. We first saw it in Elm's early use
of `foldp` (fold from the past), which was later enshrined in the
Elm Architecture.
And for the love of all that is good, please watch this terrific
[StrangeLoop presentation ](https://www.youtube.com/watch?v=fU9hR3kiOK0) (40 mins).
See what happens when you re-imagine a database as a stream!! Look at
all the problems that are solved.
Think about that: shared mutable state (the root of all evil),
re-imagined as a stream!! Blew my socks off.
If, by chance, you do watched that video, you might twig to
the idea that `app-db` is really a derived value .. the video tals
a lot about derived values. So, yes, app-db is a derived value of the `perpetual reduce`.
And yet, it acts as the authoritative source of state in the app. And yet,
it isn't, it is simply a piece of derived state. And yet, it is the source.
This is an infinite loop of sorts. An infinite loop of derived data.
## It does FSM
> Any sufficiently complicated GUI contains an ad hoc,
> informally-specified, bug-ridden, slow implementation
> of a hierarchical Finite State Machine <br>
> -- [my eleventh rule](https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule)
> -- [my 11th rule](https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule)
`event handlers` collectively
implement the "control" part of an application. Their logic
interprets arriving events in the context of existing state,
`event handlers` collectively
implement the "control" part of an application. Their logic
interprets arriving events in the context of existing state,
and they "step" the application state "forward" via modification of that state.
`events` act, then, a bit like the `triggers` in a finite state machine, and
@ -221,25 +235,14 @@ Events are data - `[:delete-item 42]`
That's almost like a function call `(delete-item 42)`. Kinda. So why prefer data?
Using data gives us:
- easier hot reloading ??
- late binding
- logability and event sourcing
- a more flexible version of "partial" (curring)
## Derived Data
There's a video I'd like you to watch from
[StrangeLoop](https://www.youtube.com/watch?v=fU9hR3kiOK0) (40 mins, sorry).
XXX
If you have then, given the explanation above, you might twig to the idea that `app-db` is
really a derived value (of the `perpetual reduce`).
And yet, it acts as the authoritative source of state in the app. And yet, it isn't, it is simply
a piece of derived state. And
yet, it is the source.
Hmm. This is an infinite loop of sorts. **Derived data is flowing around the
**Derived data is flowing around the
loop, reactively, through pure functions.** There is a pause in the loop whenever we wait
for a new event, but the moment we get it, it's another iteration of the "derived data" FRP loop.

View File

@ -29,14 +29,13 @@ Perhaps:
**completely change everything**? And, if so, what would that look like in a language
that embraces those paradigms?
3. You're taking a [Functional Design and Programming course at San Diego State University](http://www.eli.sdsu.edu/courses/fall15/cs696/index.html)
and you have to learn re-frame to do an assignment. You've left it a bit late, right?
Good news, there is a quick start guide coming up shortly.
4. You like social proof!!
re-frame is impressively buzzword compliant: it has reactivity,
unidirectional data flow, pristinely pure functions,
and you have an assignment due. You've left the reading a bit late, right? I remember those days.
4. Cromulent neologisms embiggen social proof!! We all know that. Luckily,
re-frame is impressively buzzword compliant: it has reactivity,
unidirectional data flow, pristinely pure functions,
interceptors, coeffects, conveyor belts, statechart-friendliness (FSM)
and claims an immaculate hammock conception. It also has a charming
xkcd reference (soon) and a hilarious, insiders-joke T-shirt,
and claims an immaculate hammock conception. It also has a charming
xkcd reference (soon) and a hilarious, insiders-joke T-shirt,
ideal for conferences (in design). What could possibly go wrong?
## re-frame
@ -157,7 +156,7 @@ similar 5 domino cascade will happen again.
**Each of the dominoes you supply are simple, pure functions** which
can be be described, understood and
tested independently (other than domino 3). They take data, transform it and return new data.
tested independently. They take data, transform it and return new data. (Other than domino 3)
The loop itself is utterly predictable and very mechanical in operation.
So, there's a regularity, simplicity and
@ -194,17 +193,19 @@ Data - that's the way we roll.
### It is both mature and successful in the large
re-frame was released early 2015, and has since been successfully
re-frame was released early 2015, and has since [been](https://www.fullcontact.com)
successfully
[used](https://www.nubank.com.br)
[by](https://www.fullcontact.com)
by
[quite](http://open.mediaexpress.reuters.com/)
[a few](https://rokt.com/) companies and
a
[few](https://rokt.com/) companies and
individuals to build complex apps, many running to 50K lines of
ClojureScript code, and beyond.
<img align="right" src="/images/scale-changes-everything.jpg?raw=true">
Scale changes everything. Frameworks
**Scale changes everything.** Frameworks
are just pesky overhead at small scale - measure them instead by how they help
you tame the complexity of bigger apps, and in this regard re-frame has
worked out well. Some have even praised it effusively.

View File

@ -70,11 +70,6 @@ going further (certainly read the first two):
- [presentation (video)](http://www.infoq.com/presentations/ClojureScript-Javelin) by Alan Dipert (co-author of Hoplon)
- [serious pants Elm thesis](https://www.seas.harvard.edu/sites/default/files/files/archived/Czaplicki.pdf)
And for the love of all that is good, please watch this terrific
[StrangeLoop presentation ](https://www.youtube.com/watch?v=fU9hR3kiOK0) (40 mins). Watch what happens
when you re-imagine a database as a stream!! Look at all the problems that are solved.
Think about that: shared mutable state (the root of all evil),
re-imagined as a stream!! Blew my socks off.
### How Flow Happens In Reagent

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 13 KiB