These are chat archives for jdubray/sam

23rd
Feb 2016
Jean-Jacques Dubray
@jdubray
Feb 23 2016 05:05
If you missed it we had a great discussion with Dan in the Sam-Architecture track https://gitter.im/jdubray/sam-architecture
edbienes
@edbienes
Feb 23 2016 05:08
@jdubray wow it finally happened! :) can't wait to read these discussions. Heading to that room now. :+1:
Jean-Jacques Dubray
@jdubray
Feb 23 2016 05:21
yes, so happy it happened to. The summary is that the semantics are more aligned that I claimed, but you have to bring two pieces into the Redux core: thunks and sagas.
I guess the next question is what is the boundary of Redux core? is it adequate as it is or does the boundary needs to move?
I remain convinced that SAM offer a better conceptual foundation as you can get the benefits of Redux Core + Thunks + Sagas without a single library no matter how tiny it is, SAM is just pure code factoring.
Now I am not saying that you'll never need a library to deal with more complex problem.
I actually have my own for dealing with these kind of cases, STAR.
Gunar Gessner
@gunar
Feb 23 2016 12:23
How do I prevent a nap() from becoming an infinite loop?
If nap() dispatches actions, I have to have switches to prevent infinite loops?
Jean-Jacques Dubray
@jdubray
Feb 23 2016 12:24
yes, it if it is possible, you need to create a state (say based on counters in the model) where nap stops
there is no magic there
Jean-Jacques Dubray
@jdubray
Feb 23 2016 20:04
there is a complete duality between actions and states, if you are in a state where an automatic action is always enabled, you have to move the system to a state where it is not, again, absolutely no magic. This is how things worked since the first computer instruction was written.
Action leads to a particular state, which enables possible actions and/or execute an automatic action.
Gunar Gessner
@gunar
Feb 23 2016 20:39
yes, I understand that know. I got into a loop while writing my SAM-Redux implementation ( https://github.com/gunar/sam-redux ). I want messages do disappear after 5s, so I store the current time, display the message, and call dummy empty present(null) every 1s to "tick" the counter and check if the message should be removed. What do you think of that?
Jean-Jacques Dubray
@jdubray
Feb 23 2016 20:46
The correct way to implement that in SAM is to set a delay on the present function of the action. You simply delay presenting the values to the model. It is irrelevant is an action computes at t=0 and present the results at t=5.
Gunar Gessner
@gunar
Feb 23 2016 20:49
Yeah that makes sense
Jean-Jacques Dubray
@jdubray
Feb 23 2016 20:50
you are writing code faster than I can read it :-)
Gunar Gessner
@gunar
Feb 23 2016 20:51
I woke up 4:30am and I knew I just HAD to write it.
Jean-Jacques Dubray
@jdubray
Feb 23 2016 20:51
:-)
Gunar Gessner
@gunar
Feb 23 2016 22:23
In the Rocket example, after starting the countdown, what decreases the counter? nap()?
Jean-Jacques Dubray
@jdubray
Feb 23 2016 22:24
yes, nap computes automatic actions and invokes them (~dispatch). Then the action is configured to present the value one second after it was triggered.
Obviously I wouldn't launch a rocker on that code (or from a GUI at all :-) ), but it was just to illustrate the use of nap() which seemed to have been a problem big enough in Redux to create a separate library (Thunks)
Gunar Gessner
@gunar
Feb 23 2016 22:26
ok but some state has to change for nap() not to dispatch the delayed-action every time nap() gets called (e.g. for other actions)
the "loop-problem" i was talking before
Jean-Jacques Dubray
@jdubray
Feb 23 2016 22:26
yes when "counter === 0" the action changes from dec to launch
that's why nap is tied to State not model. The purpose of State is to understand control state and "react" to it (create state representation(s)) and nap()
have to go to a meeting
Gunar Gessner
@gunar
Feb 23 2016 22:27
i mean, in nap: if (status === 'STARTED') { setTimeout(present('DECREASE), 1000) }
that would work as long as no other actions are fired, otherwise there would be concurrent timers running (and more then 10 after all)
I guess I'll take advantage of SAM's presenting/proposing a value and I'll just go ahead and schedule all actions (1...10)
Jean-Jacques Dubray
@jdubray
Feb 23 2016 23:09
Yes, absolutely, however you would implement the "dec" action as a CRUD method (which it is kind of, when you look at at DBMS). You'll pass to the model { decrementBy: "1"} if you have concurrency issues. You cannot just present the counter's value
Gunar Gessner
@gunar
Feb 23 2016 23:11
Ok so this scheduling has to be on nap() - because the model can't present values to itself - right?
Jean-Jacques Dubray
@jdubray
Feb 23 2016 23:11
CRUD is always done by the model (add/remove, inc/dec, create, update, delete...). The actions should never be in the position to mutate anything.
I prefer doing scheduling in the action, conceptually, nap computes the next action and triggers it with the correct parameters from the model
I'd prefer keeping these semantics
It is the model that decides whether to accept property values from a dataset
When race conditions are possible, the model is ultimately responsible for resolving them.
In particular when you allow to accept actions are a rate that cannot be processed by the model, they should be processing the queued action in nap()
nap, based on the state of the model should validate if that action is still relevant
Gunar Gessner
@gunar
Feb 23 2016 23:14
yes this semantics look better
Jean-Jacques Dubray
@jdubray
Feb 23 2016 23:14
if not, it should not even be able to trigger
the inc/dec add/remove actions are a bit harder to reason because they are CRUD
Gunar Gessner
@gunar
Feb 23 2016 23:15
still, wouldn't this make the action know an awful lot about the implementation?
Jean-Jacques Dubray
@jdubray
Feb 23 2016 23:15
they should really be presented as {incrementBy: 1} not by { counter: data.counter + 1}
Gunar Gessner
@gunar
Feb 23 2016 23:15
sure, that's what I'm doing and I see the benefit of that
Jean-Jacques Dubray
@jdubray
Feb 23 2016 23:16
great !!

Sorry, I don't understand what you mean by:

still, wouldn't this make the action know an awful lot about the implementation?

Gunar Gessner
@gunar
Feb 23 2016 23:17
Well, in the rocket example, clicking START would present { status: 'STARTED' } and then scheduling 10x present { decrementBy: 1 }
Jean-Jacques Dubray
@jdubray
Feb 23 2016 23:17
yes, that works
Gunar Gessner
@gunar
Feb 23 2016 23:17
works but IMHO the countdown should be handled in the model, right?
it's like a property of the model
Jean-Jacques Dubray
@jdubray
Feb 23 2016 23:18
what do you mean by that? the decrement? or the timeout?
Gunar Gessner
@gunar
Feb 23 2016 23:18
the decrement
Jean-Jacques Dubray
@jdubray
Feb 23 2016 23:18
well yes and no
Gunar Gessner
@gunar
Feb 23 2016 23:18
the countdown from 10 to 1
until LAUNCH
Jean-Jacques Dubray
@jdubray
Feb 23 2016 23:19
could be {decrement: true}
but in other contexts you could have different value to decrement with (where the refresh loop is longer)
I would argue the opposite, the model should not know the value of decrementBy
the model should be as pure as possible and hold the counter value only
So can imagine things like unit conversions and so forth, that should be handled in the vm() function, the model should never hold multiple values for the same property.
I would recommend keeping the model to a "need to know" principle.
Does the model need to know "incrementBy" "decrementBy", I'd argue not, the action is the one applying that property. Could even be "zero", why not.

@gunar
the countdown from 10 to 1
until LAUNCH

the model cannot trigger action, that is spaghetti

you are breaking the reactive loop
Jean-Jacques Dubray
@jdubray
Feb 23 2016 23:25
The model is only responsible for mutating the property values (Redux's state) it knows as little as possible about actions and control state, nap, state representation, ... properties should be kept to the strict minimum.
Gunar Gessner
@gunar
Feb 23 2016 23:45
Hmm so business logic should be spread between Actions, Model and nap()

I see now I've mixed decrementing the value with the countdown itself.

Does the model need to know "incrementBy" "decrementBy", I'd argue not, the action is the one applying that property. Could even be "zero", why not.

I fthe model doesn't know incrementBy, how to increment the value then?