These are chat archives for jdubray/sam

5th
Jul 2016
Edward Mulraney
@edmulraney
Jul 05 2016 11:39
no its actually related to that tweet you posted of someone asking where they should fire one-time data-fetching request in react component. (they thought componentDidMount). so currently i've been putting this in NAP, where if !state.isReady -> hydrateAction()
but as @foxdonut pointed out, this means you render before you have the data available to populate the view (hydrate)
then you render again with the data
so i was suggesting that you could introduce a pre-render action step hydrate but this may not be the best idea
Edward Mulraney
@edmulraney
Jul 05 2016 11:46
e.g. you have a list of users. you click on a user, and render the view for that user. however, the data for that user doesn't exist in the model yet. so the state.ready function will be false, and the view will render a loading screen. in our NAP we dispatch the action getUser(...) and then on the second render we can display the user
i suppose that's fine really
Jean-Jacques Dubray
@jdubray
Jul 05 2016 11:54
We talked about that with @chiwoojo yesterday (in person). He is also coming from a React background and the natural design seems to be this extra loop while you are fetching data. I'd like to challenge that.
It's not really a "hydrate" thing. For me hydrate/dehydrate is more related to sessions, not for sync'ing the model with the (persistent) store.
IMHO, you don't need to involve the model to maintain the "state" of fetch operations.
First, you can initiate spinners following that sample: https://github.com/jdubray/sam-samples/blob/master/react-spinner/index.html (it's react based, but it works with any Web framework).
The I would recommend you make these API calls in the actions, the action will present the record(s) to the model when it gets the response.
Jean-Jacques Dubray
@jdubray
Jul 05 2016 12:00
There is absolutely no need to involve the model and render while you are waiting for the API to respond. You can also cancel that call if you wish by presenting a cancel proposal to the model, that will block the fetch action (see SAFE example).
The Create/Update/Delete operations are up for discussions. Vincent suggested that Actions could also call these APIs
The only problem I see is that they are not "cancellable". You need to compensate to effectively cancel them.
That's why I prefer calling these APIs from the model because in effect, the application State cannot be known until they complete successfully or they are compensated/marked for compensation
Fred Daoud
@foxdonut
Jul 05 2016 12:16
@edmulraney @jdubray I was actually experimenting with code yesterday, for the same purposes. What I found worked best was as JJ described.
Jean-Jacques Dubray
@jdubray
Jul 05 2016 12:18
The SAM article is #1 in Japan today (for the whole year)
blob
Edward Mulraney
@edmulraney
Jul 05 2016 12:23
@foxdonut, JJ is describing putting the API call into the action yeah? but that action has to be called from somewhere. where are you calling it from if not NAP?
Jean-Jacques Dubray
@jdubray
Jul 05 2016 12:23
no, it's from the UI event
It's counter intuitive, but it works really well. Not having to involve the model to manage "fetching" states is removing lots of unnecessary bloat.
Fred Daoud
@foxdonut
Jul 05 2016 12:52
@edmulraney as JJ said, from the UI event (intent). If it is for the initial load, I'm calling it from the ready function (Meiosis).
Jeff Barczewski
@jeffbski
Jul 05 2016 15:57
I've been trying to get my head around SAM and a few things are confusing to me. From the Sam.js.org page state is described as a pure function that computes the view and next-action predicate. But that doesn't seem to be the best word to describe it, especially since earlier on the page one mentions that normally in computer science states are the set of properties transformed by actions. Some articles or presentations mention that semantics matter and since most people would intuit that state is a thing (noun), maybe this pure function should be called something else?
Jeff Barczewski
@jeffbski
Jul 05 2016 16:05
I would suggest step fn but I'm guessing that is not a good name either since it would seem that a step would include everything that happens between state1 to state2 including the presentation to the model. So it seems like the pure fn which takes the model and creates a view or state representation is simply a transform fn. Other possible names that would seem similar are view-model and presenter pattern, but those seem confusing too, especially the latter since we're also discussing model.presents.
Mike Nichols
@mnichols
Jul 05 2016 16:06
I stumbled across your SAM article and the state machine it sounds like you might endorse is a Behavioral State Machine? I have an implementation of this here that's based on erlang state machine (https://github.com/mnichols/possum) that supports keeping the 'state' being acted upon separate from the machine which is responding to inputs (actions)? Not trying to plug anything here...just wanting to understand better the relationship between state and actions and how to describe them
Jeff Barczewski
@jeffbski
Jul 05 2016 16:06
So I don't have a good idea, I just raise the question since it seems we can do better on naming. I can see lots of confusion in trying to explain this to students as it is currently.
Vincent Jo
@chiwoojo
Jul 05 2016 16:07
Hey JJ, I've started refactor on keeping the fetching state on the UI component level, and it's a small deviation but I can live with it. My code is becoming much more cleaner now. I was thinking about the CUD operation being done in the model yesterday and was thinking "what would happen if the CUD operations failed?".. would the model call another action inside of the model?
I was reading some stuff over synchronous action that you and Fred was talking about... I didn't 100% get it and I was wondering if the idea was to call nextAction() inside of the model rather than inside of render function?
Jeff Barczewski
@jeffbski
Jul 05 2016 16:12
Another question I have is regarding the model.presents implementation. It was mentioned that the model should only be processing one intent or proposal at a time, so if the model has to do some asynchronous call for that processing, I assume that we should be queuing any additional intents/proposals until after the model has finished dealing with the current one. Can you point me to any samples where that queuing is actually being performed? I don't see that happening in the examples I have looked at thus far.
Jean-Jacques Dubray
@jdubray
Jul 05 2016 16:15
@jeffbski I accept the critic, all I am trying to say is that in SAM application state resides only in the Model. I call a function something that does not hold state perhaps wrongly. I am happy if someone finds a better definition. The State "function" does not hold any application state. It transform the Model property values into a State Representation that can be displayed by the view. It also computes the next-action-predicate to check if there are any automatic action.
Vincent Jo
@chiwoojo
Jul 05 2016 16:16
@jeffbski I was reading through the SAFE framework that JJ built yesterday and it was keeping track of something called 'allowedactions'... I'm not 100% on this and JJ can definitely help here, but my impression was that it blocked other actions from happening when one was called.
Jean-Jacques Dubray
@jdubray
Jul 05 2016 16:16
@jeffbski @chiwoojo Correct, in SAFE I implement a "blocking" mechanism, but I have not had time yet to queue additional actions.
Vincent Jo
@chiwoojo
Jul 05 2016 16:17
ummm I see
Jeff Barczewski
@jeffbski
Jul 05 2016 16:17
So this state function is basically doing a model to state rep transform and computing the next-action-predicate. So we need a nice name for the combination of those two features.
Mike Nichols
@mnichols
Jul 05 2016 16:17
Another approach is to have a machine that 'defers' inputs until either transition to a state that is valid to handle it or other criteria? Basically replay the input after the criteria is met?
Jean-Jacques Dubray
@jdubray
Jul 05 2016 16:18
They key is that after every step the list of allowed action is computed (in SAFE) and therefore the queue would have to be checked for the allowed action. You can also take a look at the Paxos protocol for an "eventual consistency" mechanism and concurrent proposals.
@jeffbski happy to take suggestions, I am not good at naming.
@mnichols yes, very smart mechanisms can be implemented in specific scenarios.
Jeff Barczewski
@jeffbski
Jul 05 2016 16:19
Maybe the function is a "transpute" function since it transforms model to state rep and computes the next-action-predicate?
I'm terrible at naming too.
Jean-Jacques Dubray
@jdubray
Jul 05 2016 16:20
@jeffbski @mnichols you may also like the "Action Hang Back" concept that is a big strength of SAM and directly coming from separating the proposal / acceptor.
Mike Nichols
@mnichols
Jul 05 2016 16:20
Thanks @jdubray
Jean-Jacques Dubray
@jdubray
Jul 05 2016 16:20
SAFE supports action hang back, in essence, you can run multiple actions in parallel and only one is able to present its proposal. Once it happens all the other proposals are dropped.
This means that you get a generic cancellation mechanism mechanism for long running actions
Mike Nichols
@mnichols
Jul 05 2016 16:23
Do you model states explicitly caused for each input to make it easier to understand what inputs are eligible during a long-running transaction or just do predicates internally during the same state?
Jeff Barczewski
@jeffbski
Jul 05 2016 16:23
Thinking in terms of user events like key-presses or external events like push updates from the server, wouldn't we want to queue these events/proposals rather than just dropping them if one is already in flight?
Mike Nichols
@mnichols
Jul 05 2016 16:24
if you transition to a 'errored' or 'cancelled' state then inputs could be dropped since they arent defined
Jeff Barczewski
@jeffbski
Jul 05 2016 16:25
The key presses could actually be correcting the error though.
Jean-Jacques Dubray
@jdubray
Jul 05 2016 16:25

@mnichols so I am trying to avoid

modeling states explicitly

It is sometimes clearer, it is sometimes a burden. SAM / TLA+ offer enough structure in which a state machine can be landed, but does not require that you think in terms of State/Action/Transition

The predicate can be written in terms of if-then-else
Mike Nichols
@mnichols
Jul 05 2016 16:27
@jeffbski If I understand you, then that input would transition back to another state that can continue handling inputs? I am new on this...hope I am not causing confusion :)
@jdubray thanks for the input...it helps me follow your line of thought
Jean-Jacques Dubray
@jdubray
Jul 05 2016 16:27
@jeffbski the reality is that you can implement any strategy you want. They key is that SAM implements a "Step" and therefore it has the notion of an "action instance" and you can decide to drop it or not, your choice. (SAM is a pattern) SAFE is a library, so SAFE is opinionated, SAM is not
@mnichols any time, happy to answer any question you have if I can
Jeff Barczewski
@jeffbski
Jul 05 2016 16:28
ok, sounds good.
Jean-Jacques Dubray
@jdubray
Jul 05 2016 16:29
I would however recommend you follow the semantics of the pattern. It does not matter how/when the proposal got constructed as long as you are able to decide whether the proposal can be accepted or not
Jeff Barczewski
@jeffbski
Jul 05 2016 16:30
@mnichols I'm new to this idea as well. Just started reading up this weekend and wanting to understand the ideas and how it is different than what we are already doing. So it's all good, we're all trying to learn here.
Jean-Jacques Dubray
@jdubray
Jul 05 2016 16:30
In the extreme, I could have an action that runs for a month and finally deliver its proposal. SAM does not precludes that.
Jeff Barczewski
@jeffbski
Jul 05 2016 16:31
So would one be able to process other proposals while waiting?
Jean-Jacques Dubray
@jdubray
Jul 05 2016 16:31
So far, it seems that people who invest the time to understand SAM get a lot out of it, but please keep me honest.
@jeffbski yes absolutely, that's why you want to separate proposers from acceptors
It really helps factor your code. This is where you'll get the most value of SAM, and that's really trivial to do.
Then things like creating the state representation independently of the Model, nap(), allowed actions, steps, action hang back, come handy when you need them.
Jeff Barczewski
@jeffbski
Jul 05 2016 16:33
@jdubray what's your favorite example that showcases these SAM features the best?
Jean-Jacques Dubray
@jdubray
Jul 05 2016 16:33
the crud-blog post, also features time travel
Jeff Barczewski
@jeffbski
Jul 05 2016 16:33
ok. thanks. I
I'll give it a good look.
It's based on SAFE
Jeff Barczewski
@jeffbski
Jul 05 2016 16:34
excellent.
Jean-Jacques Dubray
@jdubray
Jul 05 2016 16:34
It also shows that SAM allows you to write isomorphic code by design
I have shown over and over that all Actions, Model and State run unchanged either on the browser or server (Node.js)
You of course just need to "wire" the pattern properly (present, render...)
@jeffbski if you ever want to create a course / section on SAM, happy to help you.
Jeff Barczewski
@jeffbski
Jul 05 2016 16:37
Right. That wiring can be an important part of the solution since if done well then the code can be reusable but if not then it is hopelessly coupled. So I like examples that break things out into files like you would expect in the real world where you want to get some reuse.
Thanks @jdubray after I get my head around it and try it out a little bit then that might be the next order of business.
Jean-Jacques Dubray
@jdubray
Jul 05 2016 16:39
@mnichols I didn't ditch the question on behavioral state machine. @brucou had the same questions a while back, and he built a library for Cycle.js
Let me do a bit of research and I'll try to come up with a reasonable answer
In general I try to avoid traditional state machine semantics, but I understand BSM is different and includes a Model. All I can say at this point is that SAM is a direct translation of TLA+ concept and as I see it (I am not alone), TLA+ seems to be the ultimate semantics of state machines, from which you can build all the other ones (Petri Nets, ...).
Mike Nichols
@mnichols
Jul 05 2016 16:46
Thanks @jdubray . I'll learn more about that to understand better. It seems like separating the strategy for states with their transitions based on action results and the actual representation being acted upon ('representation' in the article code) is a close implementation but I am not sure yet
Edward Mulraney
@edmulraney
Jul 05 2016 17:20

@jeffbski I struggled to understand that state function also, and I think that's because I couldn't work out what it's responsibility was. Rendering the view? Executing the next action? Where is the state? etc. I realised it's none of these, and that it's closest familiar term is really "status" or control-state. Then I differentiated what the state function can help determine, vs what the state function actually does. How I understand it is: the state function only calculates what the current control-state is of the component. From this control-state you can then:

  1. render a view based on the control state
  2. execute an action (nap) based on the control state

But there is no reason why the render and nap function must be called inside the state function, and personally I don't do this because I believe it's:

  1. an uneccessary coupling
  2. a confusion of responsibilities
  3. unnecesary repeated code (it's the same call for all components, no point repeating yourself)

I think the state function's only responsibility is to determine control-state. You can put render and nap in the state function but I don't see a benefit in doing so. I think it's the responsibility of the assembler to call render and nap, not the control-state function.

@foxdonut @jdubray re: initial load action. So for cold loading a page would you just suggest wiring onLoad to your initial action?
Jean-Jacques Dubray
@jdubray
Jul 05 2016 17:23
yes, I often just include an "init()" in the page main script. It could either call an action, or directly present a proposal to the model to initialize or to accept some initial state value
you have a choice. Of course on the server it would look different
Edward Mulraney
@edmulraney
Jul 05 2016 17:24
okay sounds good
Jean-Jacques Dubray
@jdubray
Jul 05 2016 17:24
+1 @edmulraney
I also want to emphasize that you can use the same structure (SAM) without "control" states. You could think in terms of "pages" if you'd like and just using if-then-else. Control states are great to visualize what it does, but it's not always the best choice to implement a particular scenario.

I think it's the responsibility of the assembler to call render and nap, not the control-state function.

I am not opposed to it, for me it was the dependency on the control state that "coupled" those two activities, but either way it's ok.

Jeff Barczewski
@jeffbski
Jul 05 2016 17:53
Thanks for your input @edmulraney and @jdubray, that makes sense.
Jean-Jacques Dubray
@jdubray
Jul 05 2016 18:20
@mnichols do you have a paper describing what you call "behavior(al) state machine"? I thought I had found a good reference when I discussed the topic with @brucou but I can no longer find it
Mike Nichols
@mnichols
Jul 05 2016 18:27
I don't have a formal spec other than what I learned when i wanted separation of state from transition rules (under the hood the machine itself is the state by default but I wanted to split them). I 'stole' the idea from machinajs and improved (IMO) on the api and ability to compose machines ... since then I've read around the interwebs on BSM's used in a variety of contexts. I am playing around with it in conjunction with RiotJS atm . I'll try to find a good doc on it to throw on my repo and post here
Jean-Jacques Dubray
@jdubray
Jul 05 2016 18:34
I'll try to look at your code, but it will take longer
Jeff Barczewski
@jeffbski
Jul 05 2016 18:42
OK, indulge this uninformed TLA+ question: How does TLA+ influence (or prove) SAM? It seems to me that TLA+ is a formal specification language (from wikipedia), it doesn't seem to imply any particular design pattern. It seems that TLA+ could be used to specify all sorts of systems that operate in any manner of ways. So what is the TLA+ significance that I am obviously missing?
State machines provide a framework for much of computer science. They
can be described and manipulated with ordinary, everyday mathematics—
that is, with sets, functions, and simple logic.
Hence TLA+ can be used for much of computer science
The semantics can be derived from Dr Lamport's book http://research.microsoft.com/en-us/um/people/lamport/tla/book-02-08-08.pdf
Edward Mulraney
@edmulraney
Jul 05 2016 18:58
@jdubray @foxdonut I'm starting to think the UI event is not the right place to dispatch the initial action, and perhaps a custom onLoad or hydrate function is required. The reason being is, one of the strengths of SAM is removing BL from the view. So it shouldn't matter whether we use HTML templates, React, Angular, or console.log. The logic shouldn't depend on the rendered component to dispatch an initial action, in the same way we don't depend on the view to dispatch post-render actions (nap).
I know whether or not to hydrate the model before the view has been rendered, so I shouldnt depend on the UI event for that decision to be made
Jean-Jacques Dubray
@jdubray
Jul 05 2016 19:00
@edmulraney There might be many ways to achieve this result, it would depend also on the architecture
Edward Mulraney
@edmulraney
Jul 05 2016 19:01
otherwise if I swap my view from HTML template to React, I'm going to have to rewrite logic/code. Whereas if I move the initial action responsibility outside the view, I won't have to rewrite code
Jean-Jacques Dubray
@jdubray
Jul 05 2016 19:05
@jeffbski in a meeting, I'll send pointers later about TLA+ semantics
@edmulraney yes, it makes sense.
TLA+ also has an "init" predicate
Jeff Barczewski
@jeffbski
Jul 05 2016 19:27
@jdubray ok, thanks, no rush, whenever you have time. I'm reading through the references you mentioned, but I'm still not seeing the direct connection. State machines provide a framework for many use cases (though not all hence the word "much"). So what makes their use here so valuable? I mean I can kind of see that if you have a specific set of requirements, that you could come up with a TLA+ spec to describe and validate that. Is that what you have done here? Maybe if I understood the set of requirements that would help. For instance when I compare an existing React/Redux unidirectional flow where we are using primarily stateless functional components then it looks very much like SAM except for the ability to accept/reject actions. Is that flow not a legitimate TLA+ flow too? Or is the key point in TLA+ that you need to have an accept/reject in the mix to prevent potential invalid states? I'm not discounting the fact that SAM isn't valuable in cleaning up our flows (I think it could be), but I'm just having trouble seeing the TLA+ tie-in. Thanks in advance.
Jean-Jacques Dubray
@jdubray
Jul 05 2016 22:03

@jeffbski

A speci cation is a written description of what a system is supposed to do (p1)

TLA+ is a specification language. There is no opposition between sharing semantics between specification and implementation. It's actually a desirable thing, as long as it doesn't get in the way of constructing the system.
Our basic tool for writing speci cations is mathematics
TLA+ specifies a system by describing its allowed behaviors|what it may do in the
course of an execution.
As you can see that's seem very relevant to the problem at hand. It's not relevant however to write every single line of code in your program
TLA makes it practical to describe a system by a single formula
Jeff Barczewski
@jeffbski
Jul 05 2016 22:17
I like this formula you have on the site V = S( vm(M.present(A(data))), nap(Model) ) since I think it helps to describe what is going on in one shot. I'm not sure why there is an S and a vm. I was kind of thinking the S represents the State function, but then I thought vm was for view-model so I'm confused a bit since I didn't know we'd have both. Also while the function is useful for helping understand, is it accurate? The present call is asynchronous (reactive) it doesn't return anything. Math and compatibility of functions is straight forward when synchronous. Maybe TLA+ has some nice ways to represent that and I must guess that you were able to write it in TLA+ form, but I'm guessing it might be a bit involved from reading the examples in the book.
Mike Nichols
@mnichols
Jul 05 2016 22:30
@jdubray I updated possum docs with SAM in mind here to spare you looking through code. I extracted the JS api from you sample here and it feels similar. I am working on a PoC using RiotJS and possum and could use some approval later
Jeff Barczewski
@jeffbski
Jul 05 2016 22:39
I see you do mention that about the formula that it doesn't take into account reactive flow or wiring options. Sorry I missed that in my first reading of it. I guess S is whatever is rendering the view.