These are chat archives for jdubray/sam

17th
Feb 2016
Jean-Jacques Dubray
@jdubray
Feb 17 2016 00:02
I tend to dislike big dispatchers, that's what I like about "generating" the view, you can generate the proper wiring/handlers as well, without creating this big coupling between everything.
Michael Solovyov
@msolovyov
Feb 17 2016 00:36
can you explain b) in the context of the rocket example, do you mean we'd have .addEventListener("click", function() in a separate file?
Michael Solovyov
@msolovyov
Feb 17 2016 00:43
I'm just having a hard time visualizing it as I don't see how that would decouple button code from counter code
Michael Solovyov
@msolovyov
Feb 17 2016 00:59

for example there's

view.counting = function(model) {

    return (
            "<p>Count down:"+model.counter+"</p>\n\
             <form onSubmit=\"JavaScript:return actions.abort({});\">\n\
                <input type=\"submit\" value=\"Abort\">\n\
            </form>"
        ) ;

}

where there's a button and the counter in one

maybe two separate sam loops, one for buttons, another for counters
Maas-Maarten Zeeman
@mmzeeman
Feb 17 2016 09:36
You could easily use https://github.com/google/incremental-dom for the view functions. That will probably result in some performance benefits on views which update a lot. It also allows one to use a template language which will be easier to use for front-enders.
Gunar Gessner
@gunar
Feb 17 2016 14:29
@mmzeeman from what I understand @jdubray is reluctant to use a framework for his examples or otherwise people might think that "X is needed for SAM", when in fact SAM is just an architecture you can implement with anything (or nothing, bare JS).
Certainly some kind of DOM Diffing would be greatly beneficial and I'm heading that direction.
Maas-Maarten Zeeman
@mmzeeman
Feb 17 2016 14:31
Indeed, it is just an optimisation of course.
Gunar Gessner
@gunar
Feb 17 2016 14:32
IncrementalDOM looks interesting.
Funny to see google using Github
brusand
@brusand
Feb 17 2016 14:33
And what about typescript to modèle and simplement like star java ?
What i understand is even the concept of encapsulation data + method in a class is antipattern. Each class should have a model, stage, view interface and methods(actions) should update the model throw a sam pattern ?
Gunar Gessner
@gunar
Feb 17 2016 14:40
@msolovyov no need for two complete SAM loops. you could have something like Pub/Sub, where two View-objects subscribe to the same State independently.
Michael Solovyov
@msolovyov
Feb 17 2016 15:16
@gunar do you mean with object.watch or with a library like amplify/radio?
Gunar Gessner
@gunar
Feb 17 2016 16:13
@msolovyov this is how i've done it https://jsfiddle.net/gunar/aw1zdpLs/2/
listeners = [];
const subscribe = listener =>  listeners.push(listener);
...
listeners.map(l => l(state)); 
...
model.subscribe(state => { ... });
there could be many model.subscribe(function (state) { ... }), one updating the button, the other updating the count, if that's what you want.
Michael Solovyov
@msolovyov
Feb 17 2016 16:39

is there a way to do this backwards?

model.subscribe(state => {
  const todos = state.todos || [];
  const route = state.route;

So that the states subscribe to the model

Gunar Gessner
@gunar
Feb 17 2016 16:50
that's precisely whats happening
model generates a state, which is sent to the view
MODEL.subscribe(STATE => { VIEW })
Stardrive ENGG
@HighOnDrive
Feb 17 2016 17:39

As an analogy we could say frameworks are like ensembles of musicians, both modern and older collections of musical timbres available today. The point being that today's composer (programmer) writes with a whole kit of timbres and modern music (apps) might be designed for the over all effect using many timbres (reflecting a little more than just the single melody instrumentation did back a few hundred years ago).

Bringing this back I see SAM as knowing the vocabulary of one specific primary musical scale system and it's chordal functions. Then pointing out these functions whenever they are seen in modern scores (apps). I think this is a super reduction and frankly to simple to account for the types of multi-timbral scores (apps) we have these days. Of course the basic vocabulary can be seen in most places, so what!

This is just my current contemplation on all this as I slug my way through engineering a reactive loop with Cycle.js, RxJS and states. :smile:

Jean-Jacques Dubray
@jdubray
Feb 17 2016 18:03
Apologies, just waking up. All these are fantastic discussions!
Just a word on Frameworks. Frameworks tend to come with their own semantics, that's the point, their value. The problem is that these semantics combined with the black-box effect is going constrain the way you can build a given solution. When the problem's solution is aligned with the semantics of a framework, that's good, then it is not, then really bad things happen.
The reason why SAM looks different and do not seem to require a lot of framework is because of its semantics, they seem to fit the problem with precision and scalability.
I know this is a broad claim and "time will tell", but I would refrain from overlaying semantic frameworks on top of SAM.
Jean-Jacques Dubray
@jdubray
Feb 17 2016 18:09
Wiring frameworks are ok (such as pub/sub)
Templates/Databinding frameworks are not ok as they change the relationship between the view and the state/model
incrementalDOM or other virtual dom frameworks seem to be ok,
React.js/JSX is ok as long as the React components are pure functions
Cycle.js seems to be ok
Gunar Gessner
@gunar
Feb 17 2016 18:14
I guess anything is OK as long as they either handle a single part of the equation or do it independently (letting you wire them as you wish, i.e. SAM). V = S( vm(M.present(A(data)), nap(M)))
Jean-Jacques Dubray
@jdubray
Feb 17 2016 18:14
Correct
Gunar Gessner
@gunar
Feb 17 2016 18:15
e.g. React/JSX being used solely for the V = S(state)
Jean-Jacques Dubray
@jdubray
Feb 17 2016 18:15
Correct
You could also put some parts of the model in react components, looks like the React team is encouraging that kind of implementation, but that would be strictly forbidden from a SAM's perspective
Gunar Gessner
@gunar
Feb 17 2016 18:16
I believe this leaves room for new small focused libraries.
Jean-Jacques Dubray
@jdubray
Feb 17 2016 18:16
Yes, I agree
I apologize for being so rigid on the pattern's semantics, first I didn't cook them up. This is the work of Dr. Lamport, the "Temporal Logic of Action" is a proven theory in computer science, with lots and lots of applications in distributed systems
second, when you start "tweaking" them you create a lot more problems than you can resolve.
That's why I don't believe frameworks are needed.
I understand that lots of people have looked at this question and they have formed their own beliefs, but, please become familiar with TLA+ before starting a discussion around, "my semantics are better than yours"
Jean-Jacques Dubray
@jdubray
Feb 17 2016 18:22

@brusand in particular...

What i understand is even the concept of encapsulation data + method in a class is antipattern.

yes, OO is just as bad as MVC, at least from my perspective. Most problems should not be solved with OO semantics.

Gunar Gessner
@gunar
Feb 17 2016 18:28
I'm still trying to get my head around nap(M) in V = S( vm( M.present(A(data)), nap(M) ) ). So M.present(...) returns a dataset, which vm() translates into a State to be used by the View. Now nap(M) is the second argument to vm(), so it is a list of actions the vm() should "dispatch" (A(data)) immediately after producing the State, is that right?
Jean-Jacques Dubray
@jdubray
Feb 17 2016 18:31
careful, vm() is the view-model function, it factors out some simple computations that bring the model closer to what the view needs (including slicing and dicing the model with just the parameters the view needs for instance). vm is totally optional, just an optimization.
nap is a call back that happens once the view is rendered. From the state definition, it computes the next (automatic) action if any, and executes it.
In the rocket example, the "launch" action is automatic once the counter reaches zero
nap does not belong in the model, not it belongs to the view
nap is pretty much the reason why the pattern is called SAM and not VAM. The view is somewhat irrelevant, it is jus the state representation, what is important is the state
nap() will allow you to deal with concurrency fairly elegantly.
at least not have to worry too much about it, without the need for a framework
Gunar Gessner
@gunar
Feb 17 2016 18:36
nap does not belong in the model, not it belongs to the view
so nap is independent. it takes values from the model, and dispatches actions to the model. that's it?
I can never get this quotations right
Jean-Jacques Dubray
@jdubray
Feb 17 2016 18:36
yes, that's it
However, it is based on computing the control state, that's why it is tied to the state representation.
Gunar Gessner
@gunar
Feb 17 2016 18:37
yes makes sense.
Jean-Jacques Dubray
@jdubray
Feb 17 2016 18:37
Given a (control) state, you can derive the state representation (view) and the next-action (nap)
Gunar Gessner
@gunar
Feb 17 2016 18:38
in the rocket launcher, you need to decrease the counter by 1 every one second. where does this logic go?
I'd put it in nap(), but the decreasing shouldn't happen immediately after rendering the view, but rather 1000ms later.
Jean-Jacques Dubray
@jdubray
Feb 17 2016 18:39
The way I implemented it is by invoking the decrement action from nap since we are in the state counting and counter>0, but I presented it to the model after 1s. Not sure that's fully TLA+ compliant,
However, the general structure of the implementation is TLA+ compliant
Gunar Gessner
@gunar
Feb 17 2016 18:40
*I'd put it in nap(), but the decreasing shouldn't happen immediately after rendering the view, but rather 1000ms later.
Jean-Jacques Dubray
@jdubray
Feb 17 2016 18:41
Careful...
the rendering is not happening following nap
nap merely opens a new reactive loop A -> M -> S -> V, nap()
That's what I am saying by be very careful with the semantics
someone could tell me I could render the view after nap is called, that would be absolutely the wrong thing to do
Gunar Gessner
@gunar
Feb 17 2016 18:43
So there's no actual order, it's a independent reactive loop
Jean-Jacques Dubray
@jdubray
Feb 17 2016 18:43
I believe that's the strength of the pattern, unlike Redux or Angular, there are really two reactive paths that need to be considered
yes absolutely
It's not completely independent because after a nap() a new state representation will be created at the end of the loop
so, somehow, that state representation needs to make it to the view
Gunar Gessner
@gunar
Feb 17 2016 18:44
true
could an event in the reactive loop be initiated by the model instead of by an action?
I'm thinking the decreasing of the counter could be implemented inside the model
which would make sense for me
Jean-Jacques Dubray
@jdubray
Feb 17 2016 18:52
no... it has to be initiated by nap
now inc/dec operations are also CRUD operations, so they are not the best examples to reason about
The whole point of the model is to translate actions into CRUD, that's why when it comes to inc/dec you might feel, why put it in the actions, it seems to fit better in the model.
I don't disagree, but the problem is that everyone is using "counter" as an example, so I had to use it too, but I was also able to introduce the nap function as well.
That's why it is so important to be careful making inferences on simple use cases. That's often what framework people do. They find an interesting set of semantics that seem to fit a use case or two, and before you know it, they produced a million line of code to solve a problem nobody has.
Maas-Maarten Zeeman
@mmzeeman
Feb 17 2016 19:06
Timeouts are alway's tricky in these kind of situations. The reference to the timeout needs to be placed in the state so the timeout can be cancelled upon an abort.
Jean-Jacques Dubray
@jdubray
Feb 17 2016 20:02
Not exactly true, you can take the point of view that if an abort occurs then the state will be different and presenting a new "counter" value in that state is not possible. The decrement action will have no effect on the model. You don't need to cancel the timeout...
That's where I believe the strength of SAM resides: it is this absolute decoupling between the mutation and the actions, unlike Redux and that's why I am so critical of Redux. Actions are not just events/intents that tell the model what to do, they compute the values that they believe the model should accept, without the guarantee that they will be accepted. Redux is also missing nap().
This is an extremely powerful pattern, again totally aligned with the semantics of state machines but without requiring the traditional burden of state machines, which I understand leads to very verbose code.
Maas-Maarten Zeeman
@mmzeeman
Feb 17 2016 20:07
That is awesome indeed. I was looking for such a pattern. Currently I use state machines a lot in combination with mithril and pub/sub.
Jean-Jacques Dubray
@jdubray
Feb 17 2016 20:08
In other words (and that's an ugly short cut), TLA+ allows you to use state machine semantics with if-then-else, otherwise you would have to do like what I have done in the rocket example and create "state" predicates that given the model property values tell you which state you are in.
Yes, when I started to read about TLA+ I just could not stop
Everyone who writes code should know and learn TLA+, I believe this is a game changer in Software Engineering
Maas-Maarten Zeeman
@mmzeeman
Feb 17 2016 20:09
It seems to have a lot in common with this paper also. http://www.cs.swan.ac.uk/~csharold/cv/files/bufferautomata.pdf
Jean-Jacques Dubray
@jdubray
Feb 17 2016 20:11

well, ... when I read things like:

A buffer is essentially an object for some data along with
several functions for manipulating and accessing that object

I have doubt that it is the same, everyone falls in the same trap and attach the actions to the model

They also make no reference to TLA+
Maas-Maarten Zeeman
@mmzeeman
Feb 17 2016 20:13
No, it is totally separate from TLA+, but in the same domain. Trying to prevent the explosion of states one usually get with state machines.
Jean-Jacques Dubray
@jdubray
Feb 17 2016 20:13
I cannot emphasize enough that the semantics of SAM are not chosen randomly and anyone should be extremely careful in tweaking them. Anything that "looks like" TLA+ IS-NOT TLA+
I hate to say these kinds of things because I always feel that these statements are fabricated, but I really mean it: "These discussions are awesome" thank you!
Maas-Maarten Zeeman
@mmzeeman
Feb 17 2016 20:16
No it isn't the same indeed. I was looking at the similarities which I find interesting, especially because the author was looking for a solution for a similar problem.
Jean-Jacques Dubray
@jdubray
Feb 17 2016 20:17
@mmzeeman Structured programming was invented "to prevent the explosion of states", so we should not try to change that, and I made it clear the I was not trying to do that.
That being said, it seems to me that structured programming is not ... structured enough, and we need to go one step further and be more deliberate in how State-Action-Model relate with each other. Within each bucket, structured programming works just fine.
Maas-Maarten Zeeman
@mmzeeman
Feb 17 2016 20:21
Especially true for distributed interactive systems.
Jean-Jacques Dubray
@jdubray
Feb 17 2016 20:21
Absolutely, absolutely!!!
I actually started to work on SAM last year just to deal with the complexity of distributed system interactions.
For instance to manage service/api call orchestrations
SAM works very well there too
Sorry, TLA+ works very well there too
Maas-Maarten Zeeman
@mmzeeman
Feb 17 2016 20:23
I'm doing interactive browser - server - browser things... Between different users, things like cobrowsing, chatting.
Jean-Jacques Dubray
@jdubray
Feb 17 2016 20:24
yes, I believe you are going to like SAM a lot. One model, One state, multiple views, serializing actions, nap()...
Maas-Maarten Zeeman
@mmzeeman
Feb 17 2016 20:24
I've gone the route of mithril + state-machines. But our front end guy is a bit unhappy because he can't use templates right now.
Jean-Jacques Dubray
@jdubray
Feb 17 2016 20:25
well, as stated before, I am not a big fan of templates, because they add complexity to the model (the model must always match what the view needs)
You can use templates in SAM provided you front-end the model with the vm() functions
I am by no means a front-end developer, but I like the raw power of simple HTML snippet generators. I can buy a beautiful HTML5 template and translate it into a beautiful web app/web site in a couple hours.
I can't do that with templates
Maas-Maarten Zeeman
@mmzeeman
Feb 17 2016 20:27
Yes. I was busy with something which renders the initial html view together together with a js function which can use a client side model.
It is more that we have separate roles. For instance if he now has to add a class to something or add a div somewhere he has to ask me to do it.
Jean-Jacques Dubray
@jdubray
Feb 17 2016 20:32
yes, and no, I don't think that these javascript function are out of reach for front-end designers
They are very very basic javascript functions.
Maas-Maarten Zeeman
@mmzeeman
Feb 17 2016 20:34
Yes, but get one quote wrong and it says "syntax error" and nothing works. That is what is putting him off mostly. He is afraid to touch things.
Jean-Jacques Dubray
@jdubray
Feb 17 2016 20:38
I understand
You can use templates then...
Jean-Jacques Dubray
@jdubray
Feb 17 2016 23:50
@mmzeeman actually the same question was asked on StackOverflow for Redux
http://stackoverflow.com/questions/35411423/how-to-dispatch-a-redux-action-with-a-timeout
...
As you can imagine without decoupling the actions from the model and a next-action-predicate, the answer can only be ugly

This was the question:

I have an action that updates notification state of my application. Usually this notification will be an error or info of some sort. I need to then dispatch another action after 5 seconds that will return the notification state to initially one, so no notification. Main reason behind this is to provide functionality where notifications disappear automatically after 5 seconds.
I had no luck with using setTimeout and returning another action and can't find how this is done online. So any advice is welcome.