Docs WIP - I think this is finally good enough for publish (git checkin 1001 for the repo, I think)

This commit is contained in:
Mike Thompson 2016-12-06 12:23:55 +11:00
parent d8cad51db6
commit fe87721c0e
5 changed files with 102 additions and 87 deletions

View File

@ -42,7 +42,7 @@ Perhaps:
re-frame is a pattern for writing [SPAs] in ClojureScript, using [Reagent].
McCoy might report "It's MVC, Jim, but not as we know it". And you would respond
"McCoy, you damn trouble maker, why even mention an OO pattern?
"McCoy, you trouble maker, why even mention an OO pattern?
re-frame is a **functional framework**."
Being a functional framework, it is about data, and the pure functions
@ -55,7 +55,7 @@ Architecturally, re-frame implements "a perpetual loop".
To build an app, you hang pure functions on certain parts of this loop,
and re-frame looks after the `conveyance of data`
around the loop, into and out of the transforming functions you
provide - which is why the tag line is "Derived Values, Flowing".
provide - hence a tag line of "Derived Values, Flowing".
### It does Physics
@ -66,7 +66,7 @@ Remember this diagram from school? The water cycle, right?
Two distinct stages, involving water in different phases, being acted upon
by different forces: gravity working one way, evaporation/convection the other.
To understand re-frame, **imagine data flowing around that loop instead of water**.
To understand re-frame, **imagine data flowing around that loop instead of water**.
re-frame
provides the conveyance of the data around the loop - the equivalent of gravity, evaporation and convection.
@ -87,13 +87,13 @@ you to understand re-frame, is **practically proof** it does physics.
Computationally, each iteration of the loop involves a
six domino cascade.
One domino triggers the next, which triggers the next, et cetera,
until all the dominoes are knocked over. Then re-frame stands the dominoes up
so the loop can repeat again. Each iteration is the same cascade, like a really boring OK Go video.
One domino triggers the next, which triggers the next, et cetera, until we are
back at the beginning of the loop, whereupoon the dominoes all spring to attention
again, ready for the next iteration of the same cascade.
Here are the six dominoes ...
### 1st Domino - Event Initiation
### 1st Domino - Event Dispatch
An `event` is sent when something happens - the user
clicks a button, or a websocket receives a new message.
@ -112,7 +112,7 @@ Event handler functions compute side effects (known in re-frame simply as `effec
a **description of `effects`**. This description is a data structure
which says, declaratively, how the world should change (because of the event).
Much of the time, only the "app state" of the SPA itself need
Much of the time, only the "application state" of the SPA itself need
change, but sometimes the outside world must also be effected
(localstore, cookies, databases, emails, logs, etc).
@ -128,20 +128,19 @@ marvelous because they move the app forward. Without them, an app stays stuck in
never achieving anything.
So re-frame embraces the protagonist nature of `effects` - the entire, unruly zoo of them - but
it does so in a controlled, debuggable, auditable, mockable, pluggable way.
it does so in a largely hidden way, and in a manner which is debuggable, auditable, mockable and pluggable.
### A Pivot Point
The world has just changed and, very often,
one particular part of the world, namely the **app's state**.
The world just changed and, very often, one particular part of it: the **application state**.
re-frame's `app state` is held in one place - think of it like you
would an in-memory, central database for the app (Much more details later).
would an in-memory, central database for the app (more details later).
When domino 3 changes this `app state`, it triggers the next part of the cascade
involving dominoes 4-5-6.
### The view formula
### There's a formula for it
The 4-5-6 domino cascade implements the formula made famous by Facebook's ground-breaking React library:
`v = f(s)`
@ -164,7 +163,7 @@ and only part of `s` may change at any one time, so only part of the
`v` (DOM) need be re-computed and updated. And some parts of `v` might not
be showing right now.
### Domino 4 - Query
### Domino 4 - Query
Domino 4 is about extracting data from "app state", and providing it
in the right format for view functions (which are Domino 5).
@ -296,7 +295,7 @@ database.
Because a new version of "app state" has been computed and installed,
a query (function) over this app state is called automatically (reactively),
itself computing the list of items.
itself computing the list of items.
Because the items
are stored in app state, there's not a lot to compute in this case. This
@ -307,7 +306,7 @@ subscription acts more like an accessor.
(:items db)) ;; not much of a materialised view
```
On program startup, such a query-fn must be associated with a key,
On program startup, such a query-fn must be associated with an id,
(for reasons obvious in the next domino) like this:
```clj
(re-frame.core/reg-sub :query-items query-fn)
@ -329,8 +328,9 @@ for the deleted item, obviously, but otherwise the same DOM as last time).
[:div (map item-render @items])) ;; assume item-render already written
```
Notice how `items` is "sourced" from "app state" via `subscribe`. It is called with a query key
to identify what data it needs, which should make a prior registration.
Notice how `items` is "sourced" from "app state" via `subscribe`. It is called with a query id
to identify what data it needs - in Domino 4 we associated the query id `:query-items` with
the function for that computation).
### Code For Domino 6
@ -348,9 +348,7 @@ The key point to understand about our 3-4-5-6 example is:
- which triggers view functions to rerun
- which causes new DOM
Boom, boom, boom go the dominoes.
It is a reactive data flow.
Boom, boom, boom go the dominoes. It is a reactive data flow.
### Aaaaand we're done
@ -368,6 +366,56 @@ When building a re-frame app, you will:
- write and register query functions which implement nodes in a signal graph (query layer) (domino 4)
- write Reagent view functions (view layer) (domino 5)
## Interconnections
Ask a Systems Theorist, and they'll tell you that a system has **parts** and **interconnections**.
Human brains tend to focus first on the **parts**, and then, later, maybe
**interconnections**. But we know better, right? We
know interconnections are often critical to a system.
"Focus on the lines between the boxes" we lecture anyone kind enough to listen (in my case, glassy-eyed family members).
In the case of re-frame, dominoes are the **parts**, so, tick, yes, we have
looked at them first. Our brains are happy. But what about the **interconnections**?
If the **parts** are functions, what does it even mean to talk about **interconnections between functions?**
To answer that question, I'll rephrase it as:
how are the domino functions **composed**?
At the language level,
Uncle Alonzo and Uncle John tell us how a function like `count` composes:
```clj
(str (count (filter odd? [1 2 3 4 5])))
```
We know when `count` is called, and with what
argument, and how the value it computes becomes the arg for a further function.
We know how data "flows" into and out of the functions.
Sometimes, we'd rewrite this code as:
```clj
(->> [1 2 3 4 5]
(filter odd?)
count
str)
```
With this arrangement, we talk of "threading" data
through functions. **It seems to help our comprehension to frame function
composition in terms of data flow**.
re-frame delivers architecture
by supplying the interconnections - it threads the data - it composes the dominoes - it is the lines between the boxes.
But re-frame has no universal method for this. The technique it uses varies from one domino neighbour
pair to the next. Between 1 and 2 it is a queue & router,
between 2 and 3 it is an interceptor pipeline, and along the 3-4-5-6 domino axis there's a reactive signal graph. The right
tool for the job in each case, I'd argue.
While interconnections are critical to how **re-frame works**,
you can happily **use re-frame** for a long time and be mostly ignorant of their details.
Which is a good thing - back we go to happy brains focusing on the **parts**.
## It Leverages Data
You might already know that ClojureScript is a modern lisp, and that
@ -431,16 +479,16 @@ and useful 3rd party libraries.
We haven't looked at much code yet, but **at this point you
already know 50% of re-frame.** There's detail to fill in, for sure,
but the core concepts, and basic coding techniques, are now known to you.
but the core concepts, and even basic coding techniques, are now known to you.
Next you need to read read the other three articles in the documentation [Introduction section](/docs#introduction):
Next you need to read read the other three articles in the [Introduction section](/docs#introduction):
* [Application State](/docs/ApplicationState.md)
* [Code Walkthrough](/docs/CodeWalkthrough.md)
* [Mental Model Omnibus](/docs/MentalModelOmnibus.md)
This will get your knowledge to about 70%. The
final 30% will come incrementally with use, and by reading the
final 30% will come incrementally with use, and by reading the other
tutorials (of which there's a few).
You can also experiment with these examples: <br>
@ -457,7 +505,7 @@ https://github.com/Day8/re-frame/blob/develop/docs/External-Resources.md
Good news. If you've read this far,
your insiders T-shirt will be arriving soon - it will feature turtles,
[xkcd](http://xkcd.com/1416/) and something indicating "data all the way down".
[xkcd](http://xkcd.com/1416/) and something about "data all the way down".
But we're still working on the hilarious caption bit. Open a
repo issue with a suggestion.

View File

@ -100,6 +100,17 @@ source of data is elsewhere.
6. The ability to do time travel debugging, even in a production setting. More soon.
### Get You A Leveragable Schema
You, really do need a schema for `app-db`. Yes, it is optional, and I breezed past this
earlier, but now I'm thumping the table and my face is red with intensity. You need one.
The todomvc example (in this repo) shows how to check `app-db` against your schema
after every single event has been processed.
This is good: <br>
https://www.youtube.com/watch?v=VNTQ-M_uSo8
***
Previous: [This Repo's README](../README.md)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

View File

@ -461,9 +461,9 @@ structure exists in `app-db` before any subscriptions or event handlers run.
- write and register query functions which implement nodes in a signal graph (query layer) (domino 4)
- write Reagent view functions (view layer) (domino 5)
## Further
## Further Code
You should look at the [todomvc example application](https://github.com/Day8/re-frame/tree/develop/examples/todomvc).
You should also look at the [todomvc example application](https://github.com/Day8/re-frame/tree/develop/examples/todomvc).
***

View File

@ -18,7 +18,7 @@ and help you to get the best from it.
This tutorial is a tour
of these ideas, justifications and insights. It is a little rambling, but
I'm hoping you'll have had at least one "Oooh, I see" moment before the end.
I'm hoping you'll have had at least one "Aaaah, I see" moment before the end.
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
@ -220,7 +220,7 @@ contrived in other kinds of architecture (in my experience).
So, members of the jury, I put it to you that:
- the first 3 dominoes implement an [Event-driven finite-state machine](https://en.wikipedia.org/wiki/Event-driven_finite-state_machine)
- the last 3 dominoes a rendering of the FSM's current state for the user to observe
- the last 3 dominoes render of the FSM's current state for the user to observe
Depending on your app, this may or may not be a useful mental model,
but one thing is for sure ...
@ -259,3 +259,17 @@ Your love for re-frame will be deep, abiding and enriching.
Previous: [First Code Walk-Through](CodeWalkthrough.md)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Up: [Index](README.md)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Next: [Effectful Handlers](EffectfulHandlers.md)
[SPAs]:http://en.wikipedia.org/wiki/Single-page_application
[SPA]:http://en.wikipedia.org/wiki/Single-page_application
[Reagent]:http://reagent-project.github.io/
[Dan Holmsand]:https://twitter.com/holmsand
[Flux]:http://facebook.github.io/flux/docs/overview.html#content
[Hiccup]:https://github.com/weavejester/hiccup
[FRP]:https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
[Elm]:http://elm-lang.org/
[OM]:https://github.com/swannodette/om
[Prismatic Schema]:https://github.com/Prismatic/schema
[Hoplon]:http://hoplon.io/
[Pedestal App]:https://github.com/pedestal/pedestal-app

View File

@ -5,65 +5,7 @@ We'll look at the underlying reactive mechanism.
BUT we'll start by looking at the overall picture ...
## Interconnections
Ask a Systems Theorist, and they'll tell you that a system has **parts** and **interconnections**.
Human brains tend to focus first on **parts**, and then, later,
**interconnections**. But we Software Architect might focus on
the interconnections earlier because they're so often critical to an understanding of the system.
"Focus on the lines between the boxes" we might lecture anyone kind enough to listen.
In the case of re-frame, dominoes are the **parts**, so, tick, yes, we have
looked at them first. So, I hope your brain is happy. But, let's now
indulge our inner Systems Architect and think more about **interconnections**.
So, if the **parts** are functions, what then are
the **interconnections**?
What does it even mean to talk about **interconnections between functions?**
To answer that question, I'll rephrase it as:
how are the domino functions **composed**?
At the language level,
Uncle Alonzo and Uncle John say a function such as `count` composes like this:
```clj
(str (count (filter odd? [1 2 3 4 5])))
```
Clojure's semantics tell us when `count` is called, and with what
argument, and how the value it computes becomes the arg for a further function.
We know how data "flows" into and out of the functions.
Sometimes, we'd rewrite the code above as:
```clj
(->> [1 2 3 4 5]
(filter odd?)
count
str)
```
When we arrange our code like this, we talk of "threading" data
through functions. **It seems to help our comprehension to frame function
composition in terms of data flow**.
re-frame delivers architecture
by supplying the interconnections - it threads the data - it lives in the gaps.
But there's no one method of threading. The flow varies from one domino neighbour pair to the next. One time it is a queue,
another a pipeline, and along the 3-4-5-6 axis there's a reactive signal graph.
Fine. So how, then, does data get threaded through the domino functions of re-frame?
How does data flow out of one function (domino)
into the next? What theory of computation is driving this bus?
My first, weak answer is: how wonderful is it that you don't need to worry about
this too much, re-frame looks
after it for you. It will thread (convey) data from one domino function to the next.
It will call your functions at the right time, with the right (data) arguments.
My second, equally unsatisfactory answer is: the method/transport varies
from one domino pair to the next. There's no one method. You'll need to read the further docs on "Flow".
At this point, my goal was to start you thinking about "the lines between the boxes". That's where re-frame lives.
## 1 -> 2