These are chat archives for jdubray/sam

28th
Oct 2016
devin ivy
@devinivy
Oct 28 2016 17:40
one up-side of accepting proposals: you know if your app is in an invalid state, allowing you to reasonably fall-back to a crash less often.
i.e. without feeling bad
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 17:41
:thumbsup:
devin ivy
@devinivy
Oct 28 2016 17:47
haha it's a pretty big up-side
you know that critical errors in the acceptor are by far the most important ones to understand. SAM actually pushes critical errors into one area of your app. hm!
Edward Mulraney
@edmulraney
Oct 28 2016 17:50
@devinivy isn't that more an upside of single state tree? if you have access to the entire model you can determine if you're in an invalid state?
for example, you could pass the entire model to the action
im not saying you should, or would want to
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 17:56

The way I view it is that the separation action, model, state gives you 3 clear points to understand failures:

  • is that an incorrect action?
  • is that an incorrect update?
  • is that an incorrect state?

Without that delineation it's harder to understand the nature of the defect and correct it appropriately.

You also get a clear chance to detect unwanted states and avoid propagating them to the view, even when you screwed up at the action or model level.
There are many cases where such error detection would have saved a company billions of dollars (e.g. the Societe General trader who lost $10B in 2007 or 2008). I am hoping in the future people will start adding these safety conditions we were talking about.
Charles Rector
@chuckrector
Oct 28 2016 18:44
@edmulraney hmm, single state tree does put all data in one place. but seemingly the logic coordinating that data is still diffuse. by putting all that logic in the acceptor, all the logic is also put in one place
we could pass the entire model around anywhere, but then if everybody has access to it, they don't necessarily know the logic to maintain correct states
Edward Mulraney
@edmulraney
Oct 28 2016 18:50
@chuckrector i suffixed my statement by saying you wouldn't want to pass the model around every where ;) my point was not about passing model around. your point about diffusing logic is also true, but we're not talking about that
Charles Rector
@chuckrector
Oct 28 2016 18:50
ah, i took it to mean "not saying you should, but could"
my bad ^_^
Edward Mulraney
@edmulraney
Oct 28 2016 18:52
it was specifically about identifying what gives you the ability to detect invalid state - which I thought was having access to entire model. @deviny was attributing it to the acceptor function and I was wondering if it was just because the acceptor function has access to the whole model
Charles Rector
@chuckrector
Oct 28 2016 18:55
perhaps it's more that the acceptor is the only function that has access to the whole model, and has been assigned that duty. if we pass the entire model around to multiple functions, then the logic begins to diffuse again
data by itself is useless without an observing eye
but you cannot observe it without logic. and so put it all in one bucket
Jean-Jacques Dubray
@jdubray
Oct 28 2016 18:56
@chuckrector both model and state function have access to the whole model, but only the model can mutate it
Edward Mulraney
@edmulraney
Oct 28 2016 18:56
sure, within the context of SAM you access the whole model in the acceptor, but in another conceivable architecture that isn't SAM, we could also have access to the whole model and calculate the exact same invalid state that you can in SAM
Charles Rector
@chuckrector
Oct 28 2016 18:57
ah, right. model is responsible for observing, state is reponsible for... serving :^D
Edward Mulraney
@edmulraney
Oct 28 2016 18:57
this was just about attributing the ability of detecting invalid states
acceptor is a good logical provide access to the model, rather than diffusing - absolutely
Charles Rector
@chuckrector
Oct 28 2016 19:05
i think the hardest thing for me to wrap my head around when i was initially learning about SAM was the repurposing of the term "state"
i had to read quite a lot of material before i was able to separate how it was intended to be different from "model" since i had always used them synonymously
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 19:10

Think of a Tesla car, what does it mean that it is in the state "started"? The model has static property values such as:

  • battery level
  • brake pressure
  • destination

You can only be in the state "started" if the model property values are such that the current battery level will allow you to reach your destination (since recharging is generally out of the picture, but the same argument would apply to the next charging station).

So there is a difference between the model property values and the "state" of the system. You could also have different state functions on top of the same model structure.

Fred Daoud
@foxdonut
Oct 28 2016 19:11
Regarding SAM vs PAL (I like both), it just dawned on me that really it's just nouns vs verbs :)
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 19:11
ah ah good point!
Charles Rector
@chuckrector
Oct 28 2016 19:33
i guess you could say "model" is like tetris pieces -- coming in many shapes/sizes. whereas "state" is fitting them together logically as they come, preventing a tangle of junk from accumulating. haha :^D
hmm, but then it's the model acceptor that is supposed to keep that logical format tho, isn't it
Charles Rector
@chuckrector
Oct 28 2016 19:40
is Tesla fancy for some reason in that you must program the destination before starting?
that is, cars in general are easily started and can run in perfectly acceptable and good states with the intention of reaching a destination, without precisely knowing if the gas/power level is sufficient to reach the destination
extra "destination insurance" on top of that seems obviously valuable tho
Charles Rector
@chuckrector
Oct 28 2016 19:46
esp. in critical situations where you have NASA-like problems to solve, like enough fuel to get to the moon and back
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 20:16
I don't have a Tesla, I am just talking about an hypothetical case, to show that the "meaning" of "started" can vary.
It's not a far fetch situation, you already have similar checks around break-fluid pressure and so on (I hope :-)
Charles Rector
@chuckrector
Oct 28 2016 20:21
yes, i agree -- i wasn't sure if Tesla was used as an example for a special reason
but i guess it is cz Tesla is popular? (apologies -- i do not drive)
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 20:21
I am just trying to illustrate that the action cannot decide the "end state", as humans we are used to the correlation, but as software engineers we should know better.
The different with gas powered vehicles is that this is not a safety condition because the refueling network is such that it is not a constraint to reach your destination.
Though anyone who ran out of gas wish it was (never happened to me)
Charles Rector
@chuckrector
Oct 28 2016 20:23
ah, i see now
i hope to "know better" a bit more myself after learning SAM more intimately!
i think i need to gain some more familiarity with math too, or at least the notation
in your die hard article, i do not understand all of the symbols, though i can get a vague idea by viewing wikipedia list of math symbols and attempting to lookup
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 20:26
^ and v mean "and" and "or"
Charles Rector
@chuckrector
Oct 28 2016 20:27
and there are great resources these days for learning that stuff, perhaps khan academy (?)
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 20:27
One important aspect is the prime notation a' is the proposal from the action vs a is the value of the property at the previous step.
This is really where TLA+ shines compared to any other approach because the way we write code is without making clearly that distinction. Everyone else would start assigning properties.
It's trivial, yet fundamental
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 20:38
One way to understand the notation is to read the factorial example: http://research.microsoft.com/en-us/um/people/lamport/pubs/state-machine.pdf
Charles Rector
@chuckrector
Oct 28 2016 20:39
ah, so a' is sort of like "a?"
as in, "is a okay?"
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 20:39
a'is the proposed value of a
a is a property of the model
the factorial example is p9-12
the "states" are test, mult and done
Zach Dahl
@schtauffen
Oct 28 2016 21:47
i have two degrees related to mathematics and still got lost in some of the papers lol
Charles Rector
@chuckrector
Oct 28 2016 22:28
@metapgmr_twitter that section was helpful, thank you!
i will probably read that several times. i like the example of operations assumed to be atomic when an engineer thinks about it, but then falls down in concurrent situations
which i guess is what this is all about -- the "step"
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 22:38
As I said before, this notion of Step is key to state mutation, when you don't have a well defined step, you are just doing (random) assignments. The industry has been programming with assignments since its inception and as you can understand that's probably the cause of at least 50% of the bugs ever encountered.
Elm/Redux don't help much because their "step" is too wide (it generally encompasses action, model and state) and multiple steps could actually happen unwittingly.
Though unidirectional data flows go in the right direction (so to speak)
Zach Dahl
@schtauffen
Oct 28 2016 22:41
I'm not sure I follow. Since it is a reactive loop, action-model-state exist on a 1:1:1 basis.
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 22:43
Not quite, multiple actions can be triggered in parallel and only one will present its proposal, or alternatively, they could present their proposal as long as the model/state is complete.
However conceptually 1:N actions triggered in a step must be allowed in that application state, prior to computing the update resulting in the next step.
Zach Dahl
@schtauffen
Oct 28 2016 22:46
so right now in my simple examples my action-model-state loop is synchronous and I cannot have 1:N actions.
If I do something like: present(action1()); present(action2()) it would fire model.present-1, state-1; model.present-2, state-2
What you are talking about now is if we added some sort of throttle to state such as requestAnimationFrame ?
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 22:47
You can be pretty open to allow actions to present proposal, as long as the logic in the model/state is capable of validating with precision whether it is allowed or not.
Yes, exactly the pattern work when the system is synchronous, or not (provided that the model/state remain a critical section). It would not make sense to start working on a new proposal until you complete the acceptance or rejection of the first one.
Zach Dahl
@schtauffen
Oct 28 2016 22:48
so like present(Object.assign({}, action1(), action2())) ? where we assume action1 and action2 cannot collide?
Charles Rector
@chuckrector
Oct 28 2016 22:48
@metapgmr_twitter yes, i think i understand the "seed" value of Steps at this point. now i need to "water it" and let it grow beyond the theory by continuing to build apps with SAM. a very enjoyable experience so far. tbh, i have spent more time fiddling around with text cursor restoration than understanding SAM, haha
that is, SAM is quite easy (to follow)! so i look forward to growing beyond a trivial app
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 22:50
ah ah... I have hope that some day TLA+ will influence the design of HTML such that events / and state representation (such as focus) will be consistent
Yes, indeed, SAM is very easy to grasp, just a little of factoring, but conceptually it is not mind bending.
There is also no "magic", you can easily follow everything the reactive loop is doing.
Charles Rector
@chuckrector
Oct 28 2016 22:51
i have had a direct appreciation for that one early on, as i ran into the the need for thunks in redux almost immediately when i used it in a non-trivial app
but of course, it took me quite a while to realize that thunks were the thing to solve my problem
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 22:52
That's why I tend to be critical of RxJS wiring because they don't help enforcing these semantics, on the contrary, you often see like in Cycle.js the argument that you don't need an application state at all (kind of), i.e. the application state lives in the wire.
Redux is also fairly incomplete, thunks and sagas should be part of the core, not optional elements.
Zach Dahl
@schtauffen
Oct 28 2016 22:53
thunks and sagas fulfill the same role
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 22:54
Not quite, they can use interchangeably for async API calls, but as we spoke before Sagas are stateful (mini orchestration) and would equate to nap() in SAM. Thunks can't do that (as I understand it).
I know I am biased, but very quickly real-world redux becomes quite messy.
The problem I see is that Elm/Redux/Cycle all try to pretend that side effects don't exist when they should rather embrace them. Once you create meaningful "steps" you don't have to worry about mutation.
Zach Dahl
@schtauffen
Oct 28 2016 22:56
the thing I'm not quite understanding about nap... is that it seems to me the easiest way to trigger or cancels requests is based on actions and not model or state.
do i forward actions all the way to state?
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 22:57
it is the state function that triggers the action, the action as no knowledge as to why it is triggered other than its input parameters.
Zach Dahl
@schtauffen
Oct 28 2016 22:57
sagas enforce steps naturally. they require an action to start and only dispatch actions upon completion
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 22:58
yes, but by that time, the state of the system might have changed. It would be best is the Saga state was part of the same tree. Similarly the model might want to know the state of the Sagas. This is a major flaw in Redux.
What is a "step" then, the step in the saga? in the model?
As soon as I pointed that out to Dan he cut the conversation, never came back to discuss SAM (it's on Tweeter)
Zach Dahl
@schtauffen
Oct 28 2016 22:59
i understand the state triggers the action, but it is easiest to trigger based on action value. otherwise you have to do something like model.shouldFetch = 'url'then in state if model.shouldFetch instead of if (action.type === 'FETCH_SOMETHING') unless I'm not understanding something
I'm not sure if I understand. Do you pause the whole cycle until the async action concludes?
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 23:00
well, it's best that the model don't know about actions. That's why I call it the state-action fabric (State/Action go together).
Zach Dahl
@schtauffen
Oct 28 2016 23:01
do you mean state doesn't know? model is required to know
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 23:02
This is not a hard requirement, but I feel the code is better factored when the model knows as few actions as possible. It thinks only in terms of proposals and property values.
Zach Dahl
@schtauffen
Oct 28 2016 23:02
but all an action is, is the proposal no?
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 23:02
In the Tesla example, the model should not know how the State function derives "started"
It creates the proposal, it is a function that translates the event into a proposal. An action is not (just) a proposal. Redux semantics are incorrect.
The actions are often coded in the reducer
This is very clear in TLA+, an action is a function, not a data structure
Zach Dahl
@schtauffen
Oct 28 2016 23:07
so if I have model.present('INCREMENT') and in my model ... if (action === 'INCREMENT') model.count = count + 1 the proposal is model.count -> model.count + 1
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 23:07
when you change the nature of an action, then the code has to go somewhere.
Zach Dahl
@schtauffen
Oct 28 2016 23:07
so this would be an example of the "proposal in the reducer"
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 23:08
sometimes the event = proposal, but that's rare, you always have some validation rule/enrichment of the event values.
the event could be onMouseDown, but the action will translate the event into something like {add:1}
you don't want the view component to know that increment means {add:1}
that's the role of the action do this translation and therefore avoid the coupling of the view to the model. Redux, is 100% coupled. The view and the reducer share that message structure. IMHO, that's undesirable.
Of course you can implement the decoupling below in the reducer, but that's too late. I find it quite ugly. SAM even supports 3rd party actions where the event is directed to a 3rd party (say with an OAuth token) and the 3rd party action can present a proposal with the corresponding token.
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 23:14
For example, you could use a 3rd party Sales Tax Service that is triggered by nap() once you reach a point where it can be calculated (at least one item in your shopping basket). All that happens fairly transparently, the action presents the result that would eventually render the sales tax view component.
Zach Dahl
@schtauffen
Oct 28 2016 23:14
I think its pretty common in redux to just feed actions (increment, decrement, etc) to the view and have those "action creators" dispatch the actions so I'm not seeing the coupling. I understand if I literally have to remember and type dispatch({ ADD: 1 }) whenver I want to increment, but in reality I'm doing something like import { increment } from '../actions' then ... dispatch(increment())
Rick Medina
@rickmed
Oct 28 2016 23:16
@metapgmr_twitter what does the present function does?
Zach Dahl
@schtauffen
Oct 28 2016 23:18
I don't like nap starting asynchronous actions without notifying anything... it seems this is less step-compliant than sagas. with sagas I have a record of when async actions start AND complete.
and if you want to show a loading spinner or something you end up having to presenting twice
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 23:18
@schtauffen well, as I said, I believe Redux should be more prescriptive. I am saying you can't implement SAM with Redux, I am saying that you have lots of options and you have more reasons to the wrong thing, that the right one.
@rickmed present is a method of the model, which an action invokes to present a proposal. The model will then accept or reject that proposal (or partially accept). This is part of the reactive loop, so it returns nothing (of value) to the action.
Rick Medina
@rickmed
Oct 28 2016 23:20
what does accept means?
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 23:20
@schtauffen well, that's pure state machine... state machine have no memory! you reach an application state which happens to have automatic actions. There is no semantic violation.
Rick Medina
@rickmed
Oct 28 2016 23:20
I'm trying to understand the basics looking at the launcher example
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 23:20
It's the other way around, Sagas bring "memory" (aka state) when there should not be any, that is a semantic violation.
@rickmed in general an action's proposal would include the values we want to model to take, you should not expect to do too much calculation to process the proposal.
The action does not know about all the property values of the model, so it cannot take the decision to accept or reject these values on its own.
Rick Medina
@rickmed
Oct 28 2016 23:22
@metapgmr_twitter (btw, first of all, thank you for being so available to take questions)
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 23:22
accept and reject are fairly conceptual, it simply means that the model replaced its property values with the one from the proposal
Zach Dahl
@schtauffen
Oct 28 2016 23:23
thanks for your time @metapgmr_twitter , gonna jet and ponder our discussions :)
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 23:23
sure, my pleasure, I feel this is an important discussion to have, thank you for the discussions they are very constructive.
thank you @schtauffen
@rickmed if the model "rejects" a proposal, it might update an "error" property value and delegate to the state function how to communicate that to the user. You want to model to be as lean as possible, it should looks almost like a database (say Mongo).
At a minimum it is very data centric, business logic should be mostly in the actions and state function/nap.
Rick Medina
@rickmed
Oct 28 2016 23:27
ok. So so far, an init view is rendered, an event is produced (a click to start the counter), an action function is called with the event payload (optionally I guess) which "tells" the model (model.present) how "it wishes" to modify the state. so 1st question. The actions functions need to know the shape of the model, or not?
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 23:28
The example I take is that imagine you are a company in the US and all the sudden you decide to do business in Canada, so you could have proposals that come with or without the country. The model could fill in the blanks and decide by default to add US for all the proposals without a country.
They are an adapter to the model, so yes, it's better if they know or are close to the shape of the model.
That way the view components can have an arbitrary shape
ok. at line 207, why does actions.start returns false? AFIK so far, action functions does a side effect of presenting the data to the model
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 23:30
that's an idiosyncrasy of HTML
I didn't know myself when I wrote that sample (palm-face)
Rick Medina
@rickmed
Oct 28 2016 23:31
(I'm just trying to understand why the functions have the shape they have and how/if they are used/fit in other parts of the system)
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 23:31
nothing to do with the pattern
no these functions are "actions" they are invoked by view events and all present a proposal to the model
For instance they can't do DOM manipulations...
Rick Medina
@rickmed
Oct 28 2016 23:33
so actions don't return anything correct?
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 23:33
They should not access the model either (say like in Redux where you can do store.getState())
no they logically don't return anything of value to the view
In general you want the view to hold enough information to pass (older) property values of the model, you should never need to access the model in the actions.
That would be a big violation and probably the symptom that you are doing something wrong.
The action can enrich the event by calling an API for instance, wait for the response and then present the proposal to the model
Rick Medina
@rickmed
Oct 28 2016 23:35
model.present is the only allowed to mutate the state/model?
Jean-Jacques Dubray
@metapgmr_twitter
Oct 28 2016 23:35
yes, exactly, nowhere else can you assign a property of the model
This is 100% isolated, since no part of your program can do "model.getState()"
Once the mutation is complete the model invokes state.render(model)
Of course you might argue that the state accesses the model, but it is on the model's terms, nor arbitrarily.
Redux / Elm address this by wrapping the whole sequence action-model-state in one big function, so you are "isolated" but that's way too much
Sorry I have to go, I'll try to answer other questions later if you have some
Rick Medina
@rickmed
Oct 28 2016 23:40
thank you! I'll try to figure out the rest and post the questions so when/if you have time later...