These are chat archives for jdubray/sam

1st
Feb 2017
Jean-Jacques Dubray
@jdubray
Feb 01 2017 02:27

@sladiri I am not sure if you looked at what I have done in SAFE, but I would prefer cancelling per stepID rather than action ID. I would not do something like that

setTimeout(() => {
      if (cancelledID !== actionID) {
        propose(model)({value})
      }
    }, 2000)

It's ok to have a global variable for cancelledID, that's what I call the "fabric" in SAFE, however, the last thing you want is the cancellation mechanism to be coded inside the action itself. SAFE rewires an existing SAM instance and takes this kind of decision as a middleware.

It's also true of "allowed actions", the last thing you want is the action to perform that kind of check
Rodrigo Carranza
@DrecDroid
Feb 01 2017 14:56

I have this problem with naps execution, so I'm assuming that naps can be executed one after another synchronously, blocking the next nap until this nap finishes. But this leads to an incorrect order of execution of the naps, because, first the nap receives the model to look if some action is needed to be executed, so the next nap keeps stalled until this nap ends, the first nap executes an action, then the model is modified, then the nap1 doesn't need to be executed, but now it have to end all the naps with the new model to be finished to execute the previous naps that kept stalled.

This explains better the above wording.

model -> nap1(model) -> [action() -> model -> model' -> nap1(model') -> nap2(model') -> nap3(model') ] -> nap2(model) -> nap3(model)

asynchronously It would be

model -> [ nap1(model) -> action() -> model -> model' -> nap1(model') -> naps... ] | [ nap2(model) -> action() -> model -> model' -> nap1(model') -> naps... ] | ...

Rodrigo Carranza
@DrecDroid
Feb 01 2017 15:09

The other solution is to stop the execution of subsequent naps

model -> nap1(model) -> [ action() -> model -> model' -> nap1(model') -> nap2(model') -> naps...] -> nothing to do here, subsequent naps execution were prevented because some condition was met

Rodrigo Carranza
@DrecDroid
Feb 01 2017 15:20
But to do this the nap and state should have a way of one of these:
  • Tell the state that a condition was met and It will execute some action so subsequent naps should not be executed.
  • When a condition is met in a nap It communicates the state its intents to execute an action, the state knows that anytime when a nap wants to execute an action, subsequent naps should not be executed, the state executes the action.
Jean-Jacques Dubray
@jdubray
Feb 01 2017 15:32
@DrecDroid Theoritically, there is only one next action, remember a "step" is action->model->state->nap, there is never a time where nap should trigger two actions.
nap should trigger the corresponding action directly.
Now, I also use nap to perform some actions on the view components (e.g. turn on a date picker on an input field), but I never go through the model, it's more a convenient place to put this kind of code.
nap can return a value to the state (true,false) which could instruct the state not to render the view and wait for the next action to complete. I never had to use that, but I could imagine there would be scenarios where that makes sense.
Rodrigo Carranza
@DrecDroid
Feb 01 2017 15:36
I was working like that because It allowed me to add functionality registering multiple naps, I was considering state.representation one nap more, so there were two in fact, and I said, why not more naps?.
But of course in fact there is only one nap including the state.representation
Jean-Jacques Dubray
@jdubray
Feb 01 2017 15:37
You can register as many naps as you want, but at every step only one should be executed
Rodrigo Carranza
@DrecDroid
Feb 01 2017 15:38
But somehow each nap has to tell the state that a condition was met and subsequent naps should not be executed
Jean-Jacques Dubray
@jdubray
Feb 01 2017 15:39
yes, I consider the rendering of the view as an extension to the state representation, or a message to the display component.

But somehow each nap has to tell the state that a condition was met and subsequent naps should not be executed

I am not sure why, nap is independent of the state function.

The state function should communicate the "current state" (ready, counting, ...) which can be used by nap to decide if, given a state, there is a next action to trigger. Once it has found one, since you are in a given state, no other action should logically trigger.
nap would look like this:
nap(model, curentState) {
     if (currentState === state.ready) {
            actions.myNextActionForReady(model.someProps)
     }

     if (currentState === state.counting) {
            actions.myNextActionForCounting(model.someOtherProps)
     }

}
Rodrigo Carranza
@DrecDroid
Feb 01 2017 15:41
but what if a have multiple of these functions registered
Jean-Jacques Dubray
@jdubray
Feb 01 2017 15:43
Yes you will always have many of them but they will be triggered, given a state
Rodrigo Carranza
@DrecDroid
Feb 01 2017 15:43
my current propose function or model.present function is like this
propose(proposal){
   this.acceptor(proposal)
   this.currentState = this.state(this.model)
   this.naps.forEach(nap => nap(this.model, this.currentState))
}
But that generates the problem I wrote first
model -> nap1(model) -> [action() -> model -> model' -> nap1(model') -> nap2(model') -> nap3(model') ] -> nap2(model) -> nap3(model)
Jean-Jacques Dubray
@jdubray
Feb 01 2017 15:44
yes, that works, but only one nap will trigger per currentState
It would be a violation to have the forEach loop trigger more than one
Rodrigo Carranza
@DrecDroid
Feb 01 2017 15:45
of course that generates the problem
Jean-Jacques Dubray
@jdubray
Feb 01 2017 15:45
I am not talking about rendering, or communicating the state representation
I am really talking about the application state, triggering a next-action that will ultimately present a new proposal
the current state representation can also be queried, if that made sense (in some cases).
Rodrigo Carranza
@DrecDroid
Feb 01 2017 15:48
I have to iterate through every nap, if some condition is met in one of the naps, prevent the execution of posterior naps and execute the corresponding action.
because naps are like extensions, one could register many naps at the creation of the system
Jean-Jacques Dubray
@jdubray
Feb 01 2017 15:55
yes, but logically only one nap can execute, that's why it is important to focus on the programming model, you can'd drive your programming model through other considerations like Redux, our programming is what it is because of Time Travel, similarly, you can't drive your question because it makes the code modular. In the present case, the code would be wrong, there is no logical reason for having more than one next-action given a state (unless you are doing function composition, i.e. something like a composite action makes sense, but I am not a big fan of composite actions). Composition at the action level should only come from a code reuse perspective.
Rodrigo Carranza
@DrecDroid
Feb 01 2017 15:59
No, I don't want that, I want my naps to adhere to SAM pattern but I just trying to find a way.

For example,
I could have multiple of this naps, each with different logic

nap(model, curentState) {
     if (currentState === state.ready) {
            actions.myNextActionForReady(model.someProps)
     }

     if (currentState === state.counting) {
            actions.myNextActionForCounting(model.someOtherProps)
     }

}

At some point I register each nap in the order they will be evaluated, but only one action should be executed

I have a kind of solution and It is to pass a custom actions function like

nap(model, curentState, actions) {
     if (currentState === state.ready) {
            actions("myNextActionForReady", model.someProps)
     }

     if (currentState === state.counting) {
            actions("myNextActionForCounting" , model.someOtherProps)
     }

}

That way I could "tell" behind the scenes to the state that an action will be triggered, so no other naps will be evaluated, is like having only one nap, but they're registerable

Jean-Jacques Dubray
@jdubray
Feb 01 2017 16:57
yes, that works