These are chat archives for jdubray/sam

18th
May 2016
Jean-Jacques Dubray
@jdubray
May 18 2016 01:00
Today I would not settle for anything less. I believe Vue2 is going that way too.
Jean-Jacques Dubray
@jdubray
May 18 2016 14:38

Not sure if anyone heard of FlapJax: https://pdfs.semanticscholar.org/fb49/4754be34e65abd7e8bb833a4e9555d955038.pdf

It's a programming language (or JavaScript library) that is based on three assumptions:

  • Event-driven reactivity is a natural programming model for Web applications.
  • Consistency should be a linguistic primitive.
  • Uniformity is possible when treating both external events (those from remote machines) and internal ones (those from local devices such as the mouse). Uniformity enables better abstractions and also reduces the number of concepts needed for reasoning and validation.

I particularly like "Consistency" especially in the context of Redux's Sagas.

Jean-Jacques Dubray
@jdubray
May 18 2016 14:51
The claim to fame of FlapJax is that it "tracks [] data dependencies
and automatically keeps them consistent."
I would argue that if your current framework does not handle consistency properly, you are probably going to fight a big battle as your application grows. That's the core problem of MVC and direct DOM manipulations.
devin ivy
@devinivy
May 18 2016 14:55

"tracks [] data dependencies and automatically keeps them consistent."

how does this differ from streams or a good implementation of observables?

Jean-Jacques Dubray
@jdubray
May 18 2016 14:56
well, the problem is consistency, this is the key problem in "reactive programming" (aka glitches)
You can't arbitrarily allow access/process the application state values unless you know they are in a consistent state
Unless you have a way to do that, there is a high probability that these glitches will show up and will be quickly untractable

Note that even Redux "supports" [direct DOM manipulation] (http://redux.js.org/docs/basics/ExampleTodoList.html) in the AddToDo.js file:

<form onSubmit={e => {
        e.preventDefault()
        if (!input.value.trim()) {
          return
        }
        dispatch(addTodo(input.value))
        input.value = ''
      }}>
        <input ref={node => {
          input = node
        }} />
        <button type="submit">
          Add Todo
        </button>
      </form>

(note the input.value = '')

devin ivy
@devinivy
May 18 2016 14:59
i see. i can't tell if flapjax deals with async glitches. in JS a glitch can only happen 1. in an asynchronous setting or 2. if all synchronous changes are not made at once and in the right order. observables and streams deal with the latter. doesn't flapjax also only deal with the latter?
Jean-Jacques Dubray
@jdubray
May 18 2016 15:00
They claim they do, "jax" comes from AJAX, but I am still parsing the paper.
devin ivy
@devinivy
May 18 2016 15:00
ah, i see. i'll take a closer look!
Jean-Jacques Dubray
@jdubray
May 18 2016 15:01
Yes, 1) is what they claim they solve
It's a JavaScript library so you don't even have to learn the language itself.
Jean-Jacques Dubray
@jdubray
May 18 2016 16:16
Deprecating the observer pattern in Scala.react
From Adobe presentation from 2008 [37] on the status of current production systems:
  • 1/3 of the code in Adobe’s desktop applications is devoted
    to event handling
  • 1/2 of the bugs reported during a product cycle exist in
    this code
We believe these numbers are bad not only because of the
number of bugs is disproportional. We also believe that event
handling code should account for a smaller fraction and that
the way to achieve this is to provide better event handling
abstractions.
Jean-Jacques Dubray
@jdubray
May 18 2016 16:33
Unfortunately, there is no guarantee for data consistency
in the observer pattern. Suppose we create a rectangle
that represents the bounds of our path, i.e., a publisher
that depends on changes in our original path. Also consider
an observer listening to changes in both the path and
its bounds in order to draw a framed path. This observer
needs to track explicitly whether the bounds are already
updated and, if not, defer the drawing operation. Otherwise
the user could observe a frame on the screen that has
the wrong size, which is an example of a glitch.
Jean-Jacques Dubray
@jdubray
May 18 2016 16:55

I found that article quite fascinating, in how they talk about stream/observers implementations:

Yet, three important issues remain. The control flow is
still inverted, we have to explicitly dispose the mouse move
observer and have no easy means to dispose the drag behavior
as a whole. Ideally, we want to directly encode a state
machine which can be described informally as follows:

  1. Start a new path, once the mouse button is pressed
  2. Until the mouse is released, log all mouse moves as lines
    in the path
  3. Once the mouse button is released, close the path
They suggest instead a programming model where they can write this kind of code:
Reactor.loop { self =>
// step 1
     val path = new Path((self await mouseDown).position)
           self.loopUntil(mouseUp) { // step 2
                 val m = self awaitNext mouseMove
                 path.lineTo(m.position)
                 draw(path)
           }
     path.close() // step 3
    draw(path)
}
Jean-Jacques Dubray
@jdubray
May 18 2016 17:03

And of course the implementation is "step" based to avoid the glitches:

Scala.React proceeds in discrete steps, called (propagation) turns. It is driven by two customizable core components, the propagator and the scheduler.

This is how they work together:

Once a turn is initiated by the scheduler, the propagator
takes over, collects all requests, and validates all affected reactives.
When done, it returns control to the scheduler, which
usually performs some cleanup and waits for further incoming
requests.

weepy
@weepy
May 18 2016 17:18
Is this the Same thing http://www.flapjax-lang.org
Jean-Jacques Dubray
@jdubray
May 18 2016 17:18
yes, that's the home of the language/library
Jean-Jacques Dubray
@jdubray
May 18 2016 18:09
I finally got to the bottom of the argument that Sagas (and ELM) are "testable" with respect to side effects and that no stubs are needed. Well, as expected that's a bit cheating. There is a good explanation of how Sagas work. The way the "test" works is by simply calling "next" on the generator function and expect to see as a result, the generator calling the "next" instruction (yield):
  it('forks the transpiler process', () => {
      const result = generator.next()
      expect(result.value).to.deep.equal(fork(foreman.startTranspiler))
    })
That's what you see above: result = fork(...) where fork(...) is the next yield statement in the Saga. So yes, you don't have to "mock" the side effect, but you don't test much either... If you can't write a couple statements in a row and you need to "test" that...