These are chat archives for jdubray/sam

3rd
Jun 2016
Kelyak
@kelyak
Jun 03 2016 06:49
Oh, I haven't read the angular/typescript sample yet, I'll take time to go through it, thanks. And the SAM components will run only on client side and connect to a php API.
Until now, with what I understood I try to have :
A single model that store the entire app "state"
In each "SAM" components : some actions and views.
Each "SAM" "parent" components pass to each "childs" components their relevant part of the model.
What I try to understand now is how to correctly do the equivalent of the "model.present" in each childs components and pass it to the parents (that will maybe do some additional validation). Then, when model update has been done, how to pass new relevant data to each childs components.
But my way of thinking certainly still need some improvement to fully understand and be able to use the SAM pattern.
(I hope there isn't too much information and that what I say is understandable... there is so much that I need to wrap my head around that I have many questions and each solution I find is followed by other questions/issues :p)
Jean-Jacques Dubray
@jdubray
Jun 03 2016 08:24
@kelyak It should make it easier to have all the elements of the pattern run in the browser.
you should only use child instances for dedicated components such as forms or wizard. Once the form or wizard is ready to submit its data to the parent.
This message was deleted
Yes, the key is to have a single state tree that manages the application state, however you are free to break it down however you see fit. The rule is that mutation to the application can only be proposed via the present method, there is no way to mutate the application state otherwise. It is best if Actions do not access the model (they get all the data they need from the view).
Jean-Jacques Dubray
@jdubray
Jun 03 2016 08:33
The TODO(MVC) sample should provide the best way to structure your code:
js/app.js (ES5)
mods/*.js (ES6)

What I try to understand now is how to correctly do the equivalent of the "model.present" in each child components and pass it to the parents

An action can choose which model it presents to. For instance the action wired to the submit button (or cancel) of a form can be calling the parent model.present({with_the_entire_form_data})

Kelyak
@kelyak
Jun 03 2016 08:57

I will have in fact all the elements of the pattern running in the browser. And certainly will do something like requesting the API (a CRUD API essentially) just after data validation and updating the model accordingly to the API response (at least for a first try with no optimistic UI).

Concerning the fact that actions should not access the model, I understand it but... if you do something like that (based on the snabbdom example) :

ready: function(model) {
            return h('div', [
                'Counter: ',
                model.counter,
                h('br'),
                h('button', {on:{click:function() { action.start(model.something); }}}, 'Start')
            ]);
        },

Does it means that I passed a part of the model to the action, or is it the right way of doing it ?

And finally, concerning what I said about multiples SAM "components", maybe I mixed everything in my head and I should have one "huge" SAM instance and break its elements in multiples elements of the same instance. I'll try to explain myself with an example : let's pretend that I have one page with a sidebar, a topbar and a content. I want to separate these elements in three "components". How should I do it ? A "master component" which contain the SAM instance "root", and the three subcomponents would extend this "master component" SAM instance ?

Kelyak
@kelyak
Jun 03 2016 09:04
I think my issue isn't my understanding of the SAM pattern (or at least its core concept), but just how to write my code to be able to separate my app in multiples parts/components without breaking the SAM pattern principles.
Trying to create some reusable components like we can create some reusable directive in angular is maybe a little bit difficult when beginning from scratch :p, but I'll try to do it anyway :p
Jean-Jacques Dubray
@jdubray
Jun 03 2016 09:57
I would do data validations and queries in the actions and updates (CUD) in the model, the application state generally depends on the result of Create, Update, Delete.
In other words you don't want to be in the position where the action creates a record and the model does not accept that record, otherwise you'll have to trigger some compensating action.
Logically this is what happens, but pragmatically the application state (model) has to be in sync with your DB, therefore it's ok to run these "actions" inside the model.
(IMHO)

Does it means that I passed a part of the model to the action, or is it the right way of doing it ?

yes, that's the right way of doing, it's better to pass the parts of the model you need via the view. Since you are running the entire instance of the pattern in the browser, it should not be a problem.

Jean-Jacques Dubray
@jdubray
Jun 03 2016 10:03

I should have one "huge" SAM instance and break its elements in multiples elements of the same instance.

Yes, you should use one "big" instance, though each parts can be broken down (especially the model). Child instances are only for self-contained elements like forms and wizards.

I want to separate these elements in three "components". .. a "master component" which contain the SAM instance "root", and the three subcomponents would extend this "master component" SAM instance ?

You'd have many actions
One model with 3 subelements (depending on how complex your header/footer are.
You'd have one state function which will control how the state representation (aka view) looks like
I'd organize the view components in a "theme", the idea being that you can replace the them by another one (that's key), if you cannot do that, you are doing something wrong. You could have a mobile theme and a web theme for instance.

Jean-Jacques Dubray
@jdubray
Jun 03 2016 10:09
The State function is responsible for deciding which component of the theme are visible and how to pass the application state (model) to these components (in general it's based to avoid passing the whole model, it's better to have a dedicated interface to theme components, without any knowledge of the model structure. These components should be reusable across "apps".
Kelyak
@kelyak
Jun 03 2016 10:23
Cool, I think I see a little better how to separate all these parts. Thanks a lot !
Fred Daoud
@foxdonut
Jun 03 2016 12:46
@jdubray I am almost ready to release a first version of my library, which is compatible with the SAM pattern. I hope that you can have a look and validate. Also, I am including credit/reference to you and the SAM web site in the docs. I hope that is acceptable.
Side note, in looking at the front page of http://sam.js.org I found the link to your profile, but on the page the link is broken. > This new pattern was first introduced in an InfoQ article, by Jean-Jacques Dubray.
Fred Daoud
@foxdonut
Jun 03 2016 14:29
Here is the Rocket Launcher using Meiosis to implement the SAM pattern: http://codepen.io/foxdonut/pen/pbJRrK?editors=1010
Jean-Jacques Dubray
@jdubray
Jun 03 2016 14:32
@foxdonut happy to look at it. Thank you!
I fixed the link
Jean-Jacques Dubray
@jdubray
Jun 03 2016 14:40
I'll have to go through the library to understand what it does, in general I prefer a stateful model to an immutable one. Immutability brings no value and limits scalability.
Fred Daoud
@foxdonut
Jun 03 2016 14:42
@jdubray sorry, where did you see "immutable" in what I posted?
Jean-Jacques Dubray
@jdubray
Jun 03 2016 19:40

When you say:

var receiveUpdate = function(model, update) { 
...
return model;
};

that's pretty much how a reducer works. There is no particular need for it.

Lots of people will choose to pass a copy of the model and substitute the model with the result
Fred Daoud
@foxdonut
Jun 03 2016 19:58
@jdubray I will make it clear in the documentation. You are free to mutate the model in that function and return the same object. If some people want to use it like a reducer, they can, but you can also use it like the model.present function. Aside from being function(model, presentedData) vs model.present = function(presentedData), it is essentially the same thing.
Jean-Jacques Dubray
@jdubray
Jun 03 2016 20:05
I found this article from Guido Salvaneschi et al inspiring: "Towards Distributed Reactive Programming"
In summary, distributed reactive programming is an open challenge. Existing reactive
languages take into account distribution in the sense that they are capable of transmitting
events or propagating function calls among remote hosts that independently
run a reactive system. In this way, however, consistency properties, locally enforced by
a reactive programming system, are not guaranteed over reactive data flows that cross
hosts [2]. We show that this limitation can lead to serious errors in the behavior of applications.
Despite reactive programming having huge potential as a means to coordinate
complex computing systems in a simple way, it struggles to succeed in this context.
Jean-Jacques Dubray
@jdubray
Jun 03 2016 21:46
blob
Since there is no such a thing as "remote reactive" you have to handle the state alignment between the server and the client by hand.
devin ivy
@devinivy
Jun 03 2016 21:51
"remote reactive"... are couch/pouchdb or gun.js so far off? or even meteor?
Jean-Jacques Dubray
@jdubray
Jun 03 2016 21:51
That's probably where Redux/GraphQL/Relay are heading
The problem is really the glitches. Without a way to make your implementation glitch free, you are just building a toy.
SAM is "glitch" free in somewhat of a brute force manner (using the model as a critical section)
Same for Redux
Jean-Jacques Dubray
@jdubray
Jun 03 2016 21:58
As soon as you have more than one input to your graph (client->server and server->client) you have to make a decision as to what is a unit of work.
Synchronizing data is not the problem, it "eventually" works, the problem is what happens in between.
In a reactive graph it's difficult to say what is a request and what is a response
that's the billion dollar question
devin ivy
@devinivy
Jun 03 2016 22:07
that's where you get into the idea of there only being streams of facts/events, and materialized views are a state-representation of all events that ever happened! have you read "turning the database inside out"?
Jean-Jacques Dubray
@jdubray
Jun 03 2016 22:17
yes, but facts/events have a granularity that's different from the individual values. Take something like MobX which "reacts" to variable changes. That just doesn't sound right.
The way reactive runtimes resolve glitches is by maintaining a tree dependency (the order in which the calculation must happen), I would assume in a complex UI, that quickly goes out of hand.
The next question becomes the "allowed" actions. "Everything is a state machine" therefore,
  • there are safety conditions (states you must not reach, the plane is landing and the runway is not clear)
  • some actions are now allowed (dispatch / present)
It starts to be very difficult to reason about these things in a truly reactive system
I can see why FRP works for Excel but (having spent 10 years building industrial process control systems) I fail to see how modern GUIs could hope to be truly reactive. Again I am open, but it seems that FRP is missing the notion of unit of work
devin ivy
@devinivy
Jun 03 2016 22:22
the dependencies form a directed acyclic graph, and usually it's pretty straightforward to sort out! not to get overly academic about it, but you use a topological sort, which is a well-understood, predictable thing.
Jean-Jacques Dubray
@jdubray
Jun 03 2016 22:22
Do you have a reference?
devin ivy
@devinivy
Jun 03 2016 22:24
code-wise here's a reference that is mine. i tried to keep the implementation as simple as possible https://github.com/devinivy/gert-topo-sort
here's a description of the algorithm http://www.geeksforgeeks.org/topological-sorting/
i only assume that this is what's under the hood of those reactive systems.
you set-up some dependencies between calculations, and you want to know the right order in which to perform the calculations.
to be clear, i think you're right that this isn't the solution to the problem that you mention.