These are chat archives for jdubray/sam-examples

Feb 2016
Feb 13 2016 16:30

@jdubray You said try to avoid
if (state.inbox(model)) { model.archive = data.archive || false;
However, that code was written by looking at your rocket.html example. So I appreciate the math and the TLA+ approach in SAM but for non-mathematicians we need to explain what is done where in terms of separation of concerns, an easier to understand concept for developers I think you'll agree.

Therefore, if the model should not be affected by state where would you update the model based on the actions from the user. Isn't that exactly what you are doing in the rocket.html example with
if (data.counter !== undefined) { model.counter = data.counter ; }
Are are you suggesting the data.counter actually only changes as part of the action as in
var d = data ; var p = present ; setTimeout(function() { d.counter = d.counter - 1 ; p(d) ; }, 1000)
To me, it's just moving the function, why is it important not to update the model as part of the state?

Jean-Jacques Dubray
Feb 13 2016 17:34
@bjordan2010 What is important is to decouple the state from the model, because the two kinds of logic (deciding which action is possible vs accepting values in the model) are very different in nature and reuseable independently (the same action could be applied to two different models, of the same rules could apply to two different models).
Jean-Jacques Dubray
Feb 13 2016 17:47
It is not always possible to fully decouple them and sometimes, (but not always), you need to know which (control) state you are in to update the model.
One of the problems with the example I chose is that you need to update the "status" of the launch (launched = true, aborted = true,...), so you can only accept these values if you are in the launch "status" is correct. I just want to point out that in general you may not have to do that.
Jean-Jacques Dubray
Feb 13 2016 17:52
So if you can, you should rather write the code in the model like that:
if (data.counter !== undefined) { model.counter = data.counter ; }
with some constraints that are relevant to your system (the model) not its state machine. For instance in my system counter >=0, if you present a negative value it will not be accepted.
Now if I want to report an error that the user has entered an incorrect value, I will simply not accept the value in the model, but I will have to tell the user that s/he can't do that.
so I'll "accept" a value for the mustBePositive flag like:
mustBePositive = (data.counter>=0) ;
and then in the rendering function I'll show this flag value as a hint, error, popup dialog,...
Jean-Jacques Dubray
Feb 13 2016 17:58

Are are you suggesting the data.counter actually only changes as part of the action as in

This is an important point, so let me try to make it clear, and I understand that it can be confusing

data is different from model, data represents some user entry, but also some values of the model that are made available to the action, in this case data is somehow initialized as:
data = { counter: model.counter}
Then the action is applied and in the case of an increment action, it's outcome is to add one to the input value and if there is none, initializes it.
data.counter += 1;
that logic is highly reusable, you cannot stash it / couple it with the model.
Jean-Jacques Dubray
Feb 13 2016 18:04
The problem is that a lot of the code I see people write is the actions knows about the model (MVC) or the model knows about the actions (Redux), when in reality, the desired factoring is action and model logic should be as decoupled as they can possibly be.