Skip to content

Commit a8ebbb9

Browse files
author
Steve Krouse
committed
edited frp draftinto more of a traditional paper format
1 parent bb68b4d commit a8ebbb9

File tree

1 file changed

+51
-42
lines changed

1 file changed

+51
-42
lines changed

drafts/frp.md

Lines changed: 51 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,22 @@
22
title: FRP
33
---
44

5+
* TOC
6+
{: toc }
7+
58
# Functional Reactive Programming and Modular Comprehensibility
69

710
If you wanted to understand the entirety of a software project, you'd have to read every line of code. But what if you only wanted to understand a single module? Can you get away with only reading a similarly smally piece of the code? In other words, is module comprehension proportional to the amount of code read? We can refer to such a project as "modularly comprehensible."
811

9-
<iframe width="560" height="500" src="https://www.desmos.com/calculator/2dfy7ke1mp?embed" frameborder="0" allowfullscreen></iframe>
12+
<iframe width="560" height="500" src="https://www.desmos.com/calculator/gzeqaru5pe?embed" frameborder="0" allowfullscreen></iframe>
1013

11-
Most programming languages are not modularly comprehensible in such a linear fashion but in an exponential one, as demonstrated in the yellow curve above, where understanding is dim until you've read almost all the code, at which point your understanding expands very quickly.
14+
Most programming languages are not modularly comprehensible in such a linear fashion but in an exponential one, as demonstrated in the yellow curve above, where understanding is very limited until you've read almost all the code, at which point it expands very quickly.
1215

1316
The lack of modular comprehensibility slows down the time it takes a programmer to make a change to an unfamiliar project. This is particularly relevant in open-source software, because developers have limited time to contribute. Have you ever wanted to make a small bug-fix or improvement to an open-source project, but gave up after a few hours of failing to understand how the code works?
1417

15-
## Related issues
16-
17-
Of course, the modularity of comprehensibility is only one piece of code comprehensibility.
18-
19-
Another big piece is understanding how the files, folders, import statements, and build tools and parsed together into a unifed program. Where's the entry point for goodness sake?!
20-
21-
Another impediment to code comprehensibility is code's symbolic, abstract nature. In [A Human-Readable Interactive Representation of a Code Library](http://glench.github.io/fuzzyset.js/ui/), Glen Chiacchieri makes a library more understandale through editable concrete values at various stages of code execution. Glen's thesis that concrete values are key to comprehension is backed by research that found that "to comprehend programs, developers need to acquire runtime information [to inspect the state of the application]. For this, developers frequently execute the application using a debugger." [[Walid Maalej, Rebecca Tiarks, Tobias Roehm, and Rainer Koschke. 2014. On the Comprehension of Program Comprehension](https://dl.acm.org/citation.cfm?id=2622669)]
22-
23-
And of course, code comprehensibility is only a small part of making a change to a project, which also includes getting the code to compile and run on your machine, editing the code, and testing your changes - not to mention the social complexities of getting your pull request merged into the main project (which involves getting your code reviewer to *comprehend* your changes).
24-
25-
However, the scope of this post is limited to the modularity of code comprehension.
26-
2718
## Module dependencies
2819

29-
Code is often not modularly comprehensible because the way dependencies between modules are organized.
20+
Code is not modularly comprehensible because the way dependencies between modules are organized.
3021

3122
In [Reactive MVC and The Virtual DOM](https://web.archive.org/web/20180530055638/https://futurice.com/blog/reactive-mvc-and-the-virtual-dom), Andre Staltz discusses the trade-offs between the Interactive (or imperitive) pattern and Reactive patterns.
3223

@@ -40,47 +31,51 @@ In [Reactive MVC and The Virtual DOM](https://web.archive.org/web/20180530055638
4031
>
4132
> ![image](https://user-images.githubusercontent.com/2288939/42631121-3789f186-85a7-11e8-893f-6357c6aa8864.png)
4233
>
43-
> In the Interactive pattern, module X defines which other modules X affects.
34+
> **In the Interactive pattern, module X defines which other modules X affects.**
4435
>
4536
> The dual of Interactive is Reactive, where arrows are defined in the opposite end, in the arrow head, as such:
4637
>
4738
> ![image](https://user-images.githubusercontent.com/2288939/42631130-39df12ae-85a7-11e8-8ce3-ed48235efeb4.png)
4839
>
49-
> In the Reactive pattern, module X defines which other modules affect X.
40+
> **In the Reactive pattern, module X defines which other modules affect X.**
5041
>
5142
> The benefit of Reactive over Interactive is mainly separation of concerns. In Interactive, if you want to discover what affects X, you need to search for all such calls `X.update()` in other modules. However, in Reactive, all that it takes is to peek inside X, since it defines everything which affects it. For instance, this property is common in spreadsheet calculations. The definition of the contents of one cell are always defined just in that cell, regardless of changes happening on the other cells it depends on.
5243
53-
Note on the word "module": In his example above, Staltz uses JavaScript files as representative of modules, but you could replace the `foo.js` filename with `foo` the variable or function name for similar result. Modular comprehensibility has nothing to do with browserify modules. In other words, I'm using the dictionary definition of module: "any of a number of distinct but interrelated units from which a program may be built up or into which a complex activity may be analyzed."
44+
Note on the word "module": In his example above, Staltz uses JavaScript files as representative of modules, but you could replace the `foo.js` filename with `foo` the variable or function name for similar result. Modular comprehensibility has nothing to do with browserify modules. The dictionary definition of module is relevant: "any of a number of distinct but interrelated units from which a program may be built up or into which a complex activity may be analyzed."
45+
46+
I believe that Staltz understates the non-modularity of the Interactive pattern. Let's say you wish to understand the behavior of X, so you grep for `X.update` in all modules. For each module `X.update` appears in, you have to go to the call site(s) and understand that module well enough to know what triggers that line of code, and arguments it will pass in. If you're lucky, all that information is self-contained, but you'll likely be forced to understand yet more modules to understand how *this* module affects X.
5447

55-
I believe that Staltz understates the non-modularity of the Interactive pattern. Let's say you wish to understand the behavior of X, so you grep for `X.update` in all modules. Now you have to go to the call site in each module and understand that module well enough to know what triggers that line of code, and what the values of the arguments it will pass it. If you're lucky, all that information is self-contained in that module, but you'll likely be forced to understand yet more modules to understand how *this* module affects X.
48+
The modular comprehensibility of a language is a function of how explict or implicit data dependencies are between modules. The Interactive pattern, which is representative of JavaScript, can never be modularly comprehensible, because data dependencies are hopelessly implicit.
5649

57-
Explicit dependencies are a huge win for modular comprehensibility. For example, consider the program `A` below, which is explicitly defined in terms of its modules below. In this picture read an arrow from B to A as "A is defined in terms of B" or "B is an explicit depdency of A."
50+
The Reactive Pattern enforces explicit dependencies, which are a huge win for modular comprehensibility. For example, consider the program `A` below, which is explicitly defined in terms of its modules below. In this picture read an arrow from B to A as "A is defined in terms of B" or "A explictly depends upon B."
5851

5952
<iframe width="500" height="300" src="https://mermaidjs.github.io/mermaid-live-editor/#/view/eyJjb2RlIjoiXG5ncmFwaCBCVFxuICAgIFxuQi0tPkFcbkMtLT5BXG5ELS0-QVxuRS0tPkFcbkYtLT5CXG5HLS0-QlxuSC0tPkJcbkktLT5DXG5KLS0-Q1xuSy0tPkRcbkwtLT5FXG5NLS0-RVxuTi0tPkVcbk8tLT5FXG5LLS0-TlxuUS0tPk5cbiIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0In19" frameborder="0" allowfullscreen></iframe>
6053

61-
If you want to understand a module, you have to understand it's modules, recursively. So if you want to understand the entire program, A, you have to read everything. However, let's say you were only interested in module E. In this case you only have to read the children of E, highlighted below:
54+
If you want to understand a module, you have to understand it's modules, recursively. So if you want to understand the entire program, A, you have to read everything. However, let's say you were only interested in module E. In this case you only have to read the E and it's children, recursively, highlighted below:
6255

6356
<iframe width="500" height="300" src="https://mermaidjs.github.io/mermaid-live-editor/#/view/eyJjb2RlIjoiXG5ncmFwaCBCVFxuICAgIFxuQi0tPkFcbkMtLT5BXG5ELS0-QVxuRS0tPkFcbkYtLT5CXG5HLS0-QlxuSC0tPkJcbkktLT5DXG5KLS0-Q1xuSy0tPkRcbkwtLT5FXG5NLS0-RVxuTi0tPkVcbk8tLT5FXG5LLS0-TlxuUS0tPk5cblxuY2xhc3NEZWYgY2xhc3NOYW1lIGZpbGw6eWVsbG93LHN0cm9rZTojMzMzLHN0cm9rZS13aWR0aDo0cHg7XG5jbGFzcyBFLEwsTSxOLE8sUSxLIGNsYXNzTmFtZTtcbiIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0In19" frameborder="0" allowfullscreen></iframe>
6457

65-
Explicit data dependencies allow you to comprehend modules by reading their definitions, recursively. This allows you to *categorically rule out all the modules you do not have to read* in order to comprehend the relevant module. If a module is not an explicit dependency (or dependency of a dependency...), it's not relevant. In fact, it's explicitly *independent*.
58+
Explicit data dependencies allow you to comprehend modules by reading their definitions, recursively. This allows you to *categorically rule out all the modules you do not have to read* in order to comprehend the relevant module. In the above example, that's all the modules that are not highlighted. If a module is not an explicit dependency (or dependency of a dependency...), it's not relevant. In fact, it's explicitly *independent*.
6659

67-
## Related work
60+
## Restricting the model
6861

69-
TODO program slicing and program paths
62+
The Reactive Pattern enforces explicit dependencies by restricting the programming model, disallowing side-effects, such a mutable state, leaving us with only pure functions, and a langauge in the spirit of Haskell.
7063

71-
## Restricting the model
64+
This works beautifully for batch software that accept an input and return an output, but does not scale to interactive software that responds to inputs over time. That's where FRP comes in.
7265

73-
In order to enforce explicit dependencies, we must restrict our programming model by disallowing side-effects, such a mutable state, leaving us with only pure functions, and a langauge in the spirit of Haskell.
66+
## FRP
7467

75-
TODO need to defend this restriction.
68+
"Functional Reactive Programming is a way of writing interactive software using only **pure functions**" [[Ryan Trinkle](https://youtu.be/dOy7zIk3IUI?t=1m27s)]
7669

77-
This works beautifully for batch software that accept an input and return an output, but does not scale on its own to interactive software that responds to inputs over time. That's where FRP comes in.
70+
FRP is particularly useful for constructing software interfaces. The popular UI framworks of today, such as ReactJS, are inspired by FRP principles - but without entirely forgoeing side-effects.
7871

79-
## FRP and the Elm Architecture
72+
behaviors and events (streams)
8073

81-
"Functional Reactive Programming is a way of writing software using only pure functions." [[Ryan Trinkle](https://www.youtube.com/watch?v=dOy7zIk3IUI?t=1m26s)]
74+
I like to think about FRP as "zooming out." code is organized around pieces of data, and events are subordinated as explicit dependencies of data as infinite streams.
8275

83-
FRP is particularly useful for constructing software interfaces. The popular UI framworks of today, such as ReactJS, are based on FRP principles.
76+
space time issues
77+
78+
# The Elm Architecture
8479

8580
However, most web-based FRP frameworks share a data model that does not feature modular comprehensibility. The data model they share was originally concieved as for the Elm programming language, a pure langauge in the spirit of Haskell, and entitled "The Elm Architecture." It inspired ReactJS's Redux, VueJS's Vuex, CycleJS's Onionify, among many others.
8681

@@ -129,16 +124,6 @@ As it turns out, the FRP-inspired libaries we've discussed so far aren't truly r
129124

130125
The main distinction between [OG](https://www.urbandictionary.com/define.php?term=OG) FRP and Synchronous dataflow langaugse is whether they allow higher-order streams. Because Eve, ReactJS, and VueJS do not, they are closer in spirit to dataflow langauges such as Esterel and Lucid Synchrone, than they are to the OG FRP frameworks, such as Fran. (CycleJS does allow higher-order streams.)
131126

132-
## [OG](https://www.urbandictionary.com/define.php?term=OG) FRP
133-
134-
TODO
135-
136-
behaviors and events (streams)
137-
138-
I like to think about FRP as "zooming out." code is organized around pieces of data, and events are subordinated as explicit dependencies of data as infinite streams.
139-
140-
space time issues
141-
142127
## Cyclic FRP
143128

144129
Cycles are a major concern with explicit dependencies. For one, most FRP libraries in the wild do not support them. The only one I was able to find was Reflex, which is not nearly as popular as the other frameworks discussed.
@@ -180,10 +165,34 @@ view count = intButton [ onClick Increment ] count
180165

181166
Yes there's less coupling. But is that always a good thing? No, there is such a thing as too little coupling.
182167

183-
## Visualizing higher-order, cyclic FRP
168+
## Related Work
169+
170+
Code comprehensibility is only a one important piece of making a change to a project. Other issues worth considering which also include:
171+
172+
* installing the proper software to gett the code to compile and run on your machine,
173+
* editing the code,
174+
* and testing your changes -
175+
* not to mention the social complexities of getting your pull request merged into the main project (which involves getting your code reviewer to *comprehend* your changes).
176+
177+
And, of course, the modularity of comprehensibility is only one piece of code comprehensibility.
178+
179+
Another big piece is understanding how the files, folders, import statements, and build tools and parsed together into a unifed program. Where's the entry point for goodness sake?!
180+
181+
Another impediment to code comprehensibility is code's symbolic, abstract nature. In [A Human-Readable Interactive Representation of a Code Library](http://glench.github.io/fuzzyset.js/ui/), Glen Chiacchieri makes a library more understandale through editable concrete values at various stages of code execution. Glen's thesis that concrete values are key to comprehension is backed by research that found that "to comprehend programs, developers need to acquire runtime information [to inspect the state of the application]. For this, developers frequently execute the application using a debugger." [[Walid Maalej, Rebecca Tiarks, Tobias Roehm, and Rainer Koschke. 2014. On the Comprehension of Program Comprehension](https://dl.acm.org/citation.cfm?id=2622669)]
182+
183+
TODO program paths and slicing
184+
185+
## Future Work
184186

185187
Visualizing cyclic dependencies in a comprehensible way will be a challenge. I will freely admit that if it ultimately proves impossible to visualize cyclic dependencies in a comprehensible way, FRP may not be the silver bullet for modular comprehensibility I hope it can be.
186188

189+
## Conclusions
190+
191+
192+
## Acknowledgements
193+
194+
Thank you Jonathan Edwards for you continued mentorship.
195+
187196
## ToDo
188197

189198
* title ideas

0 commit comments

Comments
 (0)