Skip to content

Commit

Permalink
Update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
actions-user committed Nov 6, 2023
1 parent ff23db0 commit d103b21
Show file tree
Hide file tree
Showing 6 changed files with 1,330 additions and 1,314 deletions.
54 changes: 35 additions & 19 deletions Flows/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -953,8 +953,15 @@
</li>

<li class="md-nav__item">
<a href="#why" class="md-nav__link">
Why?
<a href="#the-dataflow-paradigm" class="md-nav__link">
The DataFlow Paradigm
</a>

</li>

<li class="md-nav__item">
<a href="#motivation" class="md-nav__link">
Motivation?
</a>

</li>
Expand Down Expand Up @@ -1676,8 +1683,15 @@
</li>

<li class="md-nav__item">
<a href="#why" class="md-nav__link">
Why?
<a href="#the-dataflow-paradigm" class="md-nav__link">
The DataFlow Paradigm
</a>

</li>

<li class="md-nav__item">
<a href="#motivation" class="md-nav__link">
Motivation?
</a>

</li>
Expand Down Expand Up @@ -1877,24 +1891,26 @@ <h2 id="the-story-so-far">The Story So Far<a class="headerlink" href="#the-story
</ol>
<h2 id="flows">Flows<a class="headerlink" href="#flows" title="Permanent link">&para;</a></h2>
<p>This tutorial introduces <code>Flows</code>, which occur in step 3 after an effect changes <code>app-db</code>.</p>
<p>A <code>Flow</code> calculates a derived value "automatically".
<p>A <code>Flow</code> calculates a derived value "automatically".
When one part of the application state changes, another part is recalculated.
More concretely, when the values change at one or more paths within <code>app-db</code>, then the value at another path is recalculated automatically.</p>
<p><code>re-frame's</code> tagline is "derived values, flowing", and <code>Flows</code> implement dataflow. But note: these is synchronous dataflow, not to be confused with <a href="https://github.com/day8/re-frame-async-flow-fx">async flows</a>.</p>
<h2 id="why">Why?<a class="headerlink" href="#why" title="Permanent link">&para;</a></h2>
<p><code>Flows</code> help you to maintain the integrity of data derived from multiple other pieces of data.</p>
<p>One easily relatable usecase is of trying to maintain cascading error states. Imagine your UI has a validation rule: <code>start date</code> must be before <code>end date</code>. </p>
<p>After a change to the value of either <code>start date</code> or <code>end date</code>,
an error value must be calculated, and it will be used to determine if the <code>submit</code> button is enabled or not, and if an error message
<h2 id="the-dataflow-paradigm">The DataFlow Paradigm<a class="headerlink" href="#the-dataflow-paradigm" title="Permanent link">&para;</a></h2>
<p>Using <code>Flows</code>, you can create simple dataflows.</p>
<p>The dataflow programming paradigm emerged in the 1970s, so it is almost as foundational as functional programming. Indeed, reactive programming - so much the rage these days - is simply a subset of dataflow programming. </p>
<p>Both the functional and dataflow paradigms have profoundly influenced the design of re-frame. There's a reason <code>re-frame's</code> tagline is "derived values, flowing". </p>
<blockquote>
<p>BTW, this is synchronous dataflow. You should not confuse this with <a href="https://github.com/day8/re-frame-async-flow-fx">async flows</a>.</p>
</blockquote>
<h2 id="motivation">Motivation?<a class="headerlink" href="#motivation" title="Permanent link">&para;</a></h2>
<p><code>Flows</code> will help you in at least two usecases. </p>
<p><strong>First</strong>, your app has to maintain a value calculated from multiple inputs, each of which varies independently (ie. the inputs are updated via different event handlers).</p>
<p>One relatable example is that of trying to maintain cascading error states. Imagine your UI has a validation rule: <code>start date</code> must be before <code>end date</code>.
After the user changes either value, the error state must be calculated, and this is used to determine if the <code>submit</code> button is enabled or not, and if an error message
is displayed or not.</p>
<p>Now, make it more complicated. Imagine your UI has more than one validation rule and that each is a function of multiple different values. Now, there are many error states to be calculated,
one for each rule, and the submit button state is a calculation involving all the error states combined. Cascading, derived values - a multi-step dataflow.</p>
<p>On any data entry, all the rules should be reevaluated to
determine if they are broken (derived values!). If they are, then particular messages should be generated (more derived values!).
Then, in the final step, the state of the submit button should be determined (another derived value!) from the error state of all the rules (previously derived!). </p>
<p>So, cascading error states is a generic, relatable example, but there will be many other, domain-specific examples also neatly handled by <code>Flows</code>.</p>
<p>Warning: given the wording above, some end up thinking of <code>Flows</code> as having something to do
with a rules/logic engine, but it absolutely isn't that. It is just a method for implementing dataflow.</p>
<p>Now, make it more complicated: imagine your UI has many validation rules and error state must be calculated for each of them. And the submit button state is
a secondary calculation that combines these error states. Cascading, derived values. In this tree-ish arrangement, data flows from the leaves (what the user entered), through intermediate nodes (error predicate functions), through to the root (submit button state). In this tree, both the intermediate values and the root value are important.</p>
<p><strong>Second</strong>, if you find yourself asking the question: "how do I use a subscription in my event handler?". Answer: you don't. Instead, you use a Flow. </p>
<p><code>Subscriptions</code> calculate a derived value. So do <code>Flows</code>. A key difference is that <code>Flow</code> values are stored in <code>app-db</code> and that makes them available to event handlers. Of course, subscriptions are delightfully simple, because they both calculate and deliver data to views, and their lifecycle is automatically handled by the views using them. Flows are more manual/flexible. But when you need a derived value in an event handler, you have moved beyond <code>subscriptions</code> to needing a <code>Flow</code></p>
<h2 id="flow-specification">Flow Specification<a class="headerlink" href="#flow-specification" title="Permanent link">&para;</a></h2>
<p><code>Flows</code> are registered using <code>reg-flow</code>, which is part of the re-frame API. You call it with a single argument, which is the <code>flow specification</code> - a map - defining: </p>
<ul>
Expand Down
Loading

0 comments on commit d103b21

Please sign in to comment.