These are chat archives for jdubray/sam

26th
Feb 2016
Stardrive Engineering
@HighOnDrive
Feb 26 2016 00:06

@avesus I see the difference between state and model as what is activated, let me explain. My app has multiple models, which I'm likely now going to have stored in RethinkDB, the new RethinkDB Horizon project looks super!

From the models in RethinkDB users of my app activate one of many possible instances for each of the models. These activated models then become state, optionally also stored in a local client cache.

One of the models is a JSON config that represents the control states of a state machine. This config represents the constitution of the app and only one of it's control states (modes) can be active at once.

These control states involve multiple key-value pairs where the values can be simple values or the names of specific logic functions in different modules. I'll keep this short but these control states as I define them are what controls the reactive loop.

Since my app has one primary surface component the control states repurpose it's reactive loop according to the stages my app has, which also flow in sync with the levels of the SAM pattern.

In this way, I inject values into one reactive loop to transform it per control state, which define and package all the knowledge required by a specific app feature or tool.

The app constitution config can also be nested so that a complete component tree can be generated from it. Each component can have it's own reactive loop and have it's injectables defined by the control states under it. Control states also define NAP functions.

There are more details to this way of managing the reactive loop and a component tree. At this time I'm just working to sync the levels of my reactive loop with SAM. The control states my app constitution defines operate within those levels, where it's key-values are also sectioned into the same levels.

The most important aspects in all of this are SAM, the reactive loop (built with RxJS) and the app constitution, which defines a state machine as a config, which can be exchanged as a way to also define different app versions or levels of access for users.

Stardrive Engineering
@HighOnDrive
Feb 26 2016 00:30
I should also add that these control states as I define them also act as virtual-components. Long story short I found that not everything needs to be a component. Instead, it is much better to repurpose a component to behave differently, as defined by the active control state (virtual-component).
This message was deleted
Jean-Jacques Dubray
@jdubray
Feb 26 2016 00:36
Yes, absolutely. This is exactly what is happening, in the past logic was added to the view(s) to account for control state representation (in particular nap()).
SAM decouples that logic from the component.
Michael Terry
@formido
Feb 26 2016 01:13
Since TLA+ is for concurrent systems, not necessarily GUIs, which SAM concepts specifically are borrowed from TLA+? How are they adjusted to fit?
Jean-Jacques Dubray
@jdubray
Feb 26 2016 01:20
If you want to see a pure TLA+ implementation (which you can use for SAM), you can look at this library I wrote last year.
https://bitbucket.org/jdubray/star-javascript
The TLA+ concepts are S-A-M, the view being a "state representation", not part of TLA+, what works well though is being able to express the view as a function of the Model. The pattern would not work as well in an "interactive" mode where the View is an entity of its own, independent of the SAM lifecycle
Keep in mind that when the (current) view quicks in a reactive loop, the result of the loop is a new view, not a response to the view that triggered the action. Physically this is implemented over HTTP and yes, optimizations might look make the new state representation look like a response of some sort, but logically at least it is truly not.
Michael Terry
@formido
Feb 26 2016 01:25
S-A-M: State, Action, Model
...but TLA+ didn't invent State or Model
at least in these discussions, Model seems to be pretty much what it means with any pattern, nothing TLA+ specific
What I'm getting at is what the central TLA+ vocabularly is that matches the TLA+ PDF, so I can read the source
Jean-Jacques Dubray
@jdubray
Feb 26 2016 01:28
There are different terminologies. TLA+ is the "temporal logic of actions", but there is a duality between action and state.
The (control) state appears as a variable called PC in TLA+, I talked to Dr. Lamport about making this an explicit semantic of TLA+ rather than a reification of the control state into the model, but he believes that this is not necessary.
Jean-Jacques Dubray
@jdubray
Feb 26 2016 01:34
TLA+ is a formal method to analyze code, not a programming model. I suggested to him that there would be value in bringing the semantics of TLA+ to the developer level last June, after some investigations he said thanks but no thanks. He seems to be a lot more interested by the connection of TLA+ to mathematics and the formal method aspect of it.
The semantics that are very important in TLA+ that I captured with the present method is the ' semantics, data' = A(data)
Michael Terry
@formido
Feb 26 2016 01:38
the next data is the function of the action on the previous data?
Jean-Jacques Dubray
@jdubray
Feb 26 2016 01:39
Interestingly he calls it the next-state predicate, but again because of the duality action/state, I feel it is preferable to call it the next action. Ultimately it will trigger an action that will reach the next state.
but I believe it's clearer to label it as next action.
I didn't integrate the method aspect (safety and liveliness) in the pattern but they can be be use advantageously because you can define at the level of state representation safety conditions (states that you don't want the model to reach at all -> exception) and liveliness (states that you are interested in when they are reached). It can be a bit too much for most Front-Ends
He also does not use the semantics of state machines, which are (roughly) equivalent to if-then-else
That's also what I recommend when possible
Michael Terry
@formido
Feb 26 2016 01:43
so nap() is the borrowed aspect from TLA+?
if nap() is a null function, which I think you said would be common?
Jean-Jacques Dubray
@jdubray
Feb 26 2016 01:44
As I said, A, M and S (including nap, but excluding state representation) are directly from TLA+
yes, it is common, it's not often in a Front-End that you are in a state that requires an automatic action.
But it is common enough, and important enough to have it properly positioned in the pattern. Otherwise you'd be tempted to put it in the view (terrible) or in the model, even worse.
The moment I think I kind of got it is when Dr. Lamport asks the question:
we must decide what constitutes an [action]. How many [actions] are performed in executing a statement such as f = i ∗ f?
SAM is an attempt to decompose such statement, up to what happens next.
That's pretty much one of the core issue I have with Redux, Dan has not answered that question properly.
He writes reduces like:
state.counter = state.counter + 1
Michael Terry
@formido
Feb 26 2016 01:48
I like the idea of the nap(), but I think I was also intrigued by what appeared to be using control state to figure out which view code to render
Jean-Jacques Dubray
@jdubray
Feb 26 2016 01:49
This message was deleted
Control state in TLA+ is the variable pc
You'll notice that all TLA+ example use that variable pc, it's a variable like other variables, nothing distinguishes it from the other, however it always contains values that are "states" like "started" "stopped", ...
Michael Terry
@formido
Feb 26 2016 01:50
erg, I need to step out
will pick up later
Jean-Jacques Dubray
@jdubray
Feb 26 2016 01:50
ok
Milan Simonovic
@mbsimonovic
Feb 26 2016 14:43
going thru the docs, there's a paragraph that says: "One [typo, should be once?] the state representation is rendered, the State is responsible for invoking the next-action predicate (nap), which is a pure function of the model. ", so why then the nodejs example nap() function modifies the model:
function nap(m) {
    m.counter = m.counter || 0 ;

    if (m.counter > COUNTER_MAX) {
        m.counter = 0 ;
        getRssFeed({}) ;
    }
    m.counter += 1 ;
}
Milan Simonovic
@mbsimonovic
Feb 26 2016 15:53
ok, i see now that this was brought up earlier in the discussion
Jean-Jacques Dubray
@jdubray
Feb 26 2016 16:06
ouch... this incorrect sorry
Jean-Jacques Dubray
@jdubray
Feb 26 2016 16:17
will correct it
Jean-Jacques Dubray
@jdubray
Feb 26 2016 16:26
The nap code should be:
function nap(m) {
    m.counter = m.counter || 0 ;

    if (m.counter > COUNTER_MAX) {
        m.counter = 0 ;
        getRssFeed({m.counter}) ;
    }
}
the getRssFeed action should be a function:
function getRssFeed(counter,present) {
          present = present || model.present ;
          data = {} ;
          data.counter = counter + 1 ;
          request('http://myblog.org/feed', function(feed) {
                   data.feed = feed ;
                   present(data) ;
          }
}
adonirammedeiros
@adonirammedeiros
Feb 26 2016 17:16
This message was deleted
Milan Simonovic
@mbsimonovic
Feb 26 2016 18:59
but nap() again modifies the model, and therefore it's not a pure function
Jean-Jacques Dubray
@jdubray
Feb 26 2016 19:02
Sorry should not code in the middle of the night
Milan Simonovic
@mbsimonovic
Feb 26 2016 19:03
no worries, all clear now
Jean-Jacques Dubray
@jdubray
Feb 26 2016 19:03
thank you for picking it up
Milan Simonovic
@mbsimonovic
Feb 26 2016 19:06
after going thru all the docs and blog posts, 2 things jump out: you should not offend developers by not using templates (say coz it helps prevent xss), and there should be a few rock solid code examples (since SAM is a pattern, there's nothing to npm)
thanks a lot for spending time to document all this in your spare time, looks super useful, but needs time to digest
unfortunately, the entire first HN discussion missed the main point and got derailed
hopefully the community will pick up and polish the code so it doesn't turn people off before they see the light
Milan Simonovic
@mbsimonovic
Feb 26 2016 19:18
maybe a TODO app as an example, since it's a popular demo app to demonstrate how things are done
Brian Haak
@avesus
Feb 26 2016 20:18
I completely don't understand the model and don't see its advantages comparing to the Flux way. In flux, one can create an observer which will be subscribed to model change events. That observer will calculate new action and emit it by the Dispatcher. I never was trusting to the
To the Redux and other pure functional ways.
Jean-Jacques Dubray
@jdubray
Feb 26 2016 20:19
@mbsimonovic Thank you Milan, there is already a List manager (add, change, delete) you can find here: https://bitbucket.org/snippets/jdubray/zr9r6/item-list
Brian Haak
@avesus
Feb 26 2016 20:20
I don't see how they scaled and componentized. in Flux, a Store can be a small store for view-model, for example, reacting to children's height change.
Jean-Jacques Dubray
@jdubray
Feb 26 2016 20:21
@avesus SAM is just a factoring of your code, the claim behind SAM is that your code is easier to write (clearer), easier to debug (time travel, which is coming) and maintain (you can change your code more easily because of the factoring).
Brian Haak
@avesus
Feb 26 2016 20:22
People don't trust those 'pure' functional ways to do things because don't see the full picture. Main two questions: how to componentize and how to scale.
Jean-Jacques Dubray
@jdubray
Feb 26 2016 20:22
but in the end it is just a factoring, so for specific class of problems you may find a factoring that works better, but I can assure you that TLA+ is one of the most robust formalism in computer science
Brian Haak
@avesus
Feb 26 2016 20:22
In Flux, you have precise abstractions.
TLA+ is great and awesome!
Jean-Jacques Dubray
@jdubray
Feb 26 2016 20:24
The fact is nobody seems to like Flux, that's why Redux came along, and I prefer Redux a 1000 times over flux. That being said in the discussions with Dan we have seen that Redux and SAM are nearly aligned but IMHO the concepts of Thunks and Saga do not do justice to Redux. That's why I had tried originally to connect to Dan and convince him privately to look at TLA+ and align with it.
@avesus I have answered your question earlier, could you please look at it? SAM scales just as well as React in terms of building complex UIs, probably even better because you can't do stupid things easily such as putting state in the view or making the nap() stateful, though, even I did it... :-)
Brian Haak
@avesus
Feb 26 2016 20:26
Why people hate classic Flux? It pretty close to the Actor Model.
Jean-Jacques Dubray
@jdubray
Feb 26 2016 20:27
People hate it because its semantics lead to coupled business logic... that is the problem
When you use Flux in practice it does not scale at all
Brian Haak
@avesus
Feb 26 2016 20:29
Flux works only well when using microservices approach and having a lot of different stores on different levels of abstractions.
Maybe we think about different Fluxes :-)
Jean-Jacques Dubray
@jdubray
Feb 26 2016 20:31

@mbsimonovic Yes, maybe I should be more relaxed about it, we looked at implementing SAM in Angular2 yesterday and it works just fine. Perhaps my intent is to enable much more nimble framework to emerge such as Mithril or Cycle.js

The part I really like about not using a template is that I have much more room to express the view as a function. When you do that , you write a mini-code generator, a template is an interpreter. In MDSD, code generators beat interpreters any day. That's really the core of the argument. I understand the XSS aspects of it, and people have to remember to escape their parameters, when they use raw javascript functions.

Brian Haak
@avesus
Feb 26 2016 20:31
Please, please, please, create more simple examples. Using as less dependencies and closures as possible. Pure functions are those which receive data and return data, not doing "things" in between.
And it will be great if you show real components, routing, view state data (focus, height, cursor and scroll positions and so on).
Jean-Jacques Dubray
@jdubray
Feb 26 2016 20:33
Nothing prevents you in SAM to decompose your model into microservices bound model. Actually, that's probably a massive reason for using SAM (or even Redux) over Flux, because SAM gives you a level of discipline in your code that achieves a reasonable transactionality.
with nap() you can see that something has failed in the last step and you have a point to "clean up" which Flux doesn't
Jean-Jacques Dubray
@jdubray
Feb 26 2016 20:40
It looks like this guy read the SAM article on InfoQ, but you can see that React is not even impure, it's totally dirty https://www.youtube.com/watch?v=Pm0uwncSCo4&feature=youtu.be&t=14366
Brian Haak
@avesus
Feb 26 2016 20:47
All we know that it is dirty. You can use Snabbdom instead. The Purest and most clean virtual dom I ever know.
Brian Haak
@avesus
Feb 26 2016 21:02
So, is SAM a kind of Redux with nap() support?
Jean-Jacques Dubray
@jdubray
Feb 26 2016 21:08
Just two difference, really:
  • actions are functions (not events), as in they contain code (Redux offers Thunks for that, but I find it both ugly and unnecessary)
  • Redux uses Sagas for nap() which again is ugly and unnecessary
Brian Haak
@avesus
Feb 26 2016 21:11
Great! Hope for more precise pictures and complex examples. Maybe, to understand SAM one should know Redux with excellence? Because for me, Flux is a top of technology...
Jean-Jacques Dubray
@jdubray
Feb 26 2016 21:12
both thunks and sagas lead to spaghetti code where people are tempted to call multiple actions completely disregarding if the "State" of the model allows them. It's really not far at all, not sure why Dan would not align it further. Many examples in Redux contains this spaghetti code ignoring the SAM structure (A -> M -> S -> A ... ). With Redux people arbitrarily write things like AB -> M ->CDE -> M ... you just can't do that, that leads to a lot of unnecessary bugs, hard to maintain code
You cannot write all your code like that, but in Front-End architectures are coarse grained enough that it is cost effective
Brian Haak
@avesus
Feb 26 2016 21:14
Thanks! I'll dig further with Redux. To got your ideas!
Jean-Jacques Dubray
@jdubray
Feb 26 2016 21:14
Flux got a lot of things backwards, I would really encourage you to take a hard look at how the logic is factored.
no worries
Brian Haak
@avesus
Feb 26 2016 21:14
Thank you.
Jean-Jacques Dubray
@jdubray
Feb 26 2016 22:18

@mbsimonovic sample updated as it should have been https://bitbucket.org/snippets/jdubray/jna7B

I guess the old way shows exactly what people tend to do and that's the kind of leak that leads to bugs and hard to maintain code. The "clean" code was actually easier to write, much easier to maintain, and all the state remains in a single place.

Brian Haak
@avesus
Feb 26 2016 22:51
I think, you should trust more these guys than Dan Abramov: https://github.com/paldepind/functional-frontend-architecture
Jean-Jacques Dubray
@jdubray
Feb 26 2016 22:52
yes, I will take a look, thank you so much for the pointer
José Pedro Dias
@JosePedroDias
Feb 26 2016 22:55
hi there!
Jean-Jacques Dubray
@jdubray
Feb 26 2016 22:55
Hi ! welcome!
José Pedro Dias
@JosePedroDias
Feb 26 2016 22:58
Reading http://jdubray.github.io/sam/ now. Have you given a talk on this subject?
Jean-Jacques Dubray
@jdubray
Feb 26 2016 22:59
@avesus Dan is focused on Client side architecture and Time Travel. He is does not seem to be interested in code factoring, coupling, cohesion. He started with Flux and tried to fix it, then he went one problem after another (thunks, sagas) without ever looking back at the big picture
No sorry, not yet, just privately at one of my clients
José Pedro Dias
@JosePedroDias
Feb 26 2016 23:00
would be interesting to discuss it in strongloop or for instance on a react-related conf (as @staltz did with his cycle.js project)
Jean-Jacques Dubray
@jdubray
Feb 26 2016 23:04
Sure, I'd be happy too. Is there a StrongLoop conference coming up? I could apply to be a presenter.
I am expecting QCon would be a good place too.
José Pedro Dias
@JosePedroDias
Feb 26 2016 23:04
sorry, not strongloop
anyway there are many others: http://lanyrd.com/topics/functional-programming/
Jean-Jacques Dubray
@jdubray
Feb 26 2016 23:09
Yes, that's kind of next on my agenda.
José Pedro Dias
@JosePedroDias
Feb 26 2016 23:22
btw you can serve your examples with something such as
(converted from the raw url of the https://bitbucket.org/snippets/jdubray/9dgKp/sam-sample example)
this comparison table helps a lot:
http://jdubray.github.io/sam/#react
Jean-Jacques Dubray
@jdubray
Feb 26 2016 23:24
ah ah... thank you so much for the tip, APis APIs...
José Pedro Dias
@JosePedroDias
Feb 26 2016 23:25
anyway since you're hosting the SAM site from gh_pages, you can host the sample there...
José Pedro Dias
@JosePedroDias
Feb 26 2016 23:34
I'm tempted to try to rewrite a SAM example with snabdom, as explained here: https://medium.com/@yelouafi/react-less-virtual-dom-with-snabbdom-functions-everywhere-53b672cb2fe3#.pbdgm4b9g
Jean-Jacques Dubray
@jdubray
Feb 26 2016 23:36
Please !!
Link to githack now live: http://jdubray.github.io/sam/#rocket
José Pedro Dias
@JosePedroDias
Feb 26 2016 23:37
seems a decent compromise between innerHTMLing and react. you get a vdom and keep control without additional bloat
oh thanks. bear in bind that the raw url is probably linked to the bitbucket git state (meaning, you should get a new raw url if you ever edit that file)
José Pedro Dias
@JosePedroDias
Feb 26 2016 23:51
trying to adapt the rocket example...
Jean-Jacques Dubray
@jdubray
Feb 26 2016 23:54
Yes, there is just one thing that is important to preserve, it is the moment when the view is rendered. Again, React creates a horrific an unnecessary coupling between the View and the Model (State) as any change to the state will result in a rendering of the entire View hierarchy. I know there are ways to control, but it should be controlled by default. I hope Snabbdom has not the same architecture
The flow of the SAM pattern is very important and it is the model which passes control to the State, not the State that "listens" on changes to the model.
José Pedro Dias
@JosePedroDias
Feb 26 2016 23:54
read the medium article above (at least the very beginning, describing its setup)
snabbdom doesn't impose those, I believe it should work just fine
Jean-Jacques Dubray
@jdubray
Feb 26 2016 23:57

I agree, encouraged to read this:

Similarly we set event listeners through the ‘on’ object which get handled by the ‘eventlisteners’ module.

In particular that's essential for weaving APIs in the model and dealing with (some aspects of) concurrency. There has to be a time, where the model is isolated.