These are chat archives for jdubray/sam

5th
Feb 2016
Jean-Jacques Dubray
@jdubray
Feb 05 2016 01:03
welcome Kristian
Gunar Gessner
@gunar
Feb 05 2016 01:29
Hi Jean, I'm curious as to how SAM would manage not to send more info than necessary by the front end. Couldnt understand this part. Thank you.
Jean-Jacques Dubray
@jdubray
Feb 05 2016 02:45
So there are different deployment models for SAM, the Model and the state could be on different tiers, and work with any technology. That being said, let's take an example where HTML created on the server for instance using Node.js, then there is no data traveling to the browser, just plain HTML.
Node may have fetched more than the view needed but that's irrelevant.
You could also have an architecture where the function S() that creates the state representation runs on the client. In that case you would have to decide how much of the model you send, and you could send as little as you need with a view-model function.
What is important to note is that the work of the front-end developer changes with SAM, SAM works like React where the front-end developer looks at the model that is provided and create the rendering based on the model values. It does not know how the model got there. I cannot prevent you to think in terms of Req/Resp, but in reality that would be the wrong thing to do. It's better to think in terms of model and states, from which you create state representations.
Jean-Jacques Dubray
@jdubray
Feb 05 2016 02:50
I'll continue coding that sample I am working on and show how this works with a login screen
Jean-Jacques Dubray
@jdubray
Feb 05 2016 04:05
This is what the menu model could look like
menu.items = menu.items || [
              {heading: 'NAVIGATION'}
            , {item: {link: "index.html", label: 'Homepage', iconLeft: 'home', iconRight: 'angle-right'}}
            , {item: {link: "#", label: 'Features', iconLeft: 'cog', iconRight: 'plus', 
                subMenu:[
                     {item: {link: "typography.html", label: 'Typography', iconLeft: 'angle-right', iconRight: 'circle'}}
                    ,{item: {link: "jquery.html", label: 'JQuery', iconLeft: 'angle-right', iconRight: 'circle'}}
                    ,{item: {link: "others.html", label: 'Others', iconLeft: 'angle-right', iconRight: 'circle'}}
                ]}}
            , {item: {link: "#", label: 'Gallery', iconLeft: 'camera', iconRight: 'plus', 
                subMenu:[
                     {item: {link: "gallery-square.html", label: 'Square Thumbs', iconLeft: 'angle-right', iconRight: 'circle'}}
                    ,{item: {link: "gallery-round.html", label: 'Round Thumbs', iconLeft: 'angle-right', iconRight: 'circle'}}
                    ,{item: {link: "gallery-wide.html", label: 'Wide Thumbs', iconLeft: 'angle-right', iconRight: 'circle'}}
                ]}}
            , {item: {link: "contact.html", label: 'Contact', iconLeft: 'envelope', iconRight: 'angle-right'}}
            , {heading: 'SOCIAL'}
            , {item: {link: "#", label: 'Facebook', iconLeft: 'home', iconRight: 'angle-right'}}
            , {item: {link: "#", label: 'Twitter', iconLeft: 'cog', iconRight: 'plus', 

        ] ;
and the function that generates the main menu from it:
theme.menu = function(items) {
    var menu = items.map(function(i) {
        if (i['heading'] !== undefined) {
            return(' <div class="sidebar-heading">\n\
                        '+i.heading+'\n\
                    </div>')
        } else {
            if (i['item'] !== undefined) {
                return (this.menuItem(i.item)) ;
            }
        }
        // not supported
        return '' ;
    })
    return ('<div class="sidebar-navigation">'+menu+'</div>') ;
}
PaulRogers909
@PaulRogers909
Feb 05 2016 07:22
With the theme, ES6 template strings with template placeholders would help in reducing the need for \n and + https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/template_strings.
bjordan2010
@bjordan2010
Feb 05 2016 09:29
Your client comes to you after you deliver the Rocket "app". They say, hey we like it, we launched 50 rockets yesterday. However, we want to also be able to "abort" after launch, but we want that action to be "destruct" but it should "do the same thing as an abort" just after the launch.
Jean-Jacques Dubray
@jdubray
Feb 05 2016 16:04
yes, that should be very easy to do
that's a new action that's enabled once you are in the launched state
First the model:
var model = {
         counter: COUNTER_MAX, 
         started: false,      
         launched: false, 
         aborted: false,
             destructed: false} ;
then a new action:
actions.destruct = function(data, present) {
    present = present || model.present ;
    data.destructed = true ;
    present(data) ;
    return false ;
}
Jean-Jacques Dubray
@jdubray
Feb 05 2016 16:10
then a new state, while updated the other states:
state.aborted = function(model) {
    return (
        (  model.counter <= COUNTER_MAX) && (model.counter >= 0) 
        && model.started && !model.launched && model.aborted  && !model.destructed) ;
}

state.destructed = function(model) {
    return (
        (  model.counter <= COUNTER_MAX) && (model.counter >= 0) 
        && model.started && model.launched && !model.aborted && model.destructed) ;
}
then the views:
Jean-Jacques Dubray
@jdubray
Feb 05 2016 16:15
view.launched = function(model) {

    return (
            "<p>Launched</p>"
             <form onSubmit=\"JavaScript:return actions.destruct({});\">\n\
                <input type=\"submit\" value=\"Destruct\">\n\
            </form>"

        ) ;

}

view.destructed = function(model) {

    return (
            "<p>Destructed</p>"
        ) ;

}
then the representation:
state.representation = function(model) {
    var representation = 'oops... something went wrong, the system is in an invalid state' ;
        ...
    if (state.destructed(model)) {
        representation = state.view.destructed(model) ;
    }
that should do it
Jean-Jacques Dubray
@jdubray
Feb 05 2016 16:22
Now, I don't want people to walk away with the impression they always have to do that. You can use the semantics of a state machine when you choose too.

All that SAM says is that you need to structure the response to an action as follows

V = S( vm( M.present( A(data) ) ), nap(M) )

where S, vm, A and nap are pure functions.

bjordan2010
@bjordan2010
Feb 05 2016 17:12
That worked nicely. So it seems the state machine is meant to control flow or even what actions are available. When you say "you can use semantics of a state machine when you choose too" how would you control flow or what actions are available without it? Do you mean when you "need" to as in when there is a workflow or do you mean you can just display the actions and let the user chose the state?
brucou
@brucou
Feb 05 2016 18:40
Hi @jdubray , forgive me if I did not read the previous comments, maybe the answer to my question is somewhere there. I am analyzing right now the example code from https://bitbucket.org/snippets/jdubray/9dgKp/sam-sample
My first remarks (there are a few more, but step by step) : there are closures in a number of places. Don't that render your code more coupled and less functional. Namely, action.start is like so actions.start = function(data, present) { present = present || model.present ;
does not that mean that actions.start is not 100% functional (less so 150% as you say in one article)?
Should it not be, actions.start = f (data, present, model.present)?
damn, sorry can't seem to success in formatting code nicely with markdown...
brucou
@brucou
Feb 05 2016 19:16
This message was deleted
actions.start = f (data, present, model)
brucou
@brucou
Feb 05 2016 19:25
Second point, the state variable is in a closure of model. Quoting
model.present = function(data) {        
    if (state.counting(model)) {
That is acceptable, because it can be considered a constant as it is never modified (like, say, COUNTER_MAX) but that actually obscures a bit the understanding of what flows from what and comes from where, I believe.
brucou
@brucou
Feb 05 2016 19:40
But my main issue is probably the separation of concerns. model.present updates the model AND state.renders. state.render ... renders (i.e. display on the screen, i.e. updates the DOM) AND is responsible also for executing next actions. Those actions at the difference of others are 'business-logic'-triggered, if I may say, not user-triggered. And the 'business logic' in particular is that some actions can only be triggered when the model holds a particular set of values ; are automatically triggered when the model holds that set of values.
brucou
@brucou
Feb 05 2016 19:48
This goes a bit against the single responsibility principle in my opinion, and gives you a lot of functions who perform side-effects, and hence are harder to reason about (though at least you have ensured that some actions will be executed only if the model is in some 'state').
Fred Daoud
@foxdonut
Feb 05 2016 19:48
@bjordan2010 adding destruct to Cycle.js example is also easy: http://codepen.io/foxdonut/pen/JGmEQd
brucou
@brucou
Feb 05 2016 19:59
Last thing:
V = S( vm( M.present( A(data) ) ), nap(M) )
you say S, vm, A and nap are pure functions.
It escapes me how this is so from your sample code. Could you expand on that, i.e. what is S, vm, A, nap in the example?
brucou
@brucou
Feb 05 2016 21:03
@foxdonut The cycle.js is certainly more functional as expected. But I am waiting to see what exactly is the SAM about. I think the current code the way it is written does not make it justice (probably).
brucou
@brucou
Feb 05 2016 21:52
damn I have two diagrams I made to upload, but I canť find how to do that in this chat format
alt
This is the hierarchic diagram
brucou
@brucou
Feb 05 2016 21:57
alt
This is the orthogonal diagram
not very pretty, it is done quickly with yed.
brucou
@brucou
Feb 05 2016 22:04
When between two big boxes (which are functions in the example), an edge denotes sequentiality, i.e. Present happens after Action. When between a small box (origin) and a big box (target), an edge denotes that the small box is a parameter for the big box.
Small boxes are object, Big boxes are functions
An edge between small boxes (like model and data for instance) means that data MAY be derived from model
Hopefully I did not get it too wrong, but I published it here because it helps me have an overview of the data and call flow
brucou
@brucou
Feb 05 2016 22:23
Sorry, here are the corrected diagrams, I can't seem to be ale to delete former messages.
Jean-Jacques Dubray
@jdubray
Feb 05 2016 22:28

@bjordan2010

how would you control flow or what actions are available without it?
you can use if-then-else, this is how people have done it for decades. Even TLA+ uses if-then-else. If you ask me, after a beer or two, I would tell you that GOTO was not the problem, it was if-then-else. The right way to write a program is to use state predicates, but I understand why people find it cumbersome. I believe JavaScript makes it a lot less painful to write (say compared to Java), but still people would look at this code and say I don't want to write it that way and I would understand.

brucou
@brucou
Feb 05 2016 22:29
alt
corrected orthogonal diagram
This message was deleted
alt
hierarchic diagram
Jean-Jacques Dubray
@jdubray
Feb 05 2016 22:33
@brucou Bruno, no sorry, this would not qualify as a closure. This is merely a default value. There is no coupling there, the action must be a pure function and I would argue it is.
Fred Daoud
@foxdonut
Feb 05 2016 22:37
@brucou I agree with you. It's disheartening when the theory sounds great but then the code is...not.
@jdubray if your action function is function(data, present) and then within the function you refer to model, then that's not a pure function.
Jean-Jacques Dubray
@jdubray
Feb 05 2016 22:40

@brucou

Second point, the state variable is in a closure of model

Yes, you are correct, this is not the best factoring for the pattern, the model should be independent of the "state" construct as much as possible. The state controls the authorized action, once an action is authorized, it should be able to present data. That being said, you I didn't want to make the example too complicated. In the end, because this decision is based on Model values it is not such a bad place to put it. If you don't have automatic actions, that's probably where it will live.

@foxdonut come on guys, there is nothing that says how you have to write it. A default value/shortcut does not qualify as a breakage of the theory, there no other reason for having that line of code in the action, other than I am lazy and don't want to type it outside every time. This does not break in any way the theory.
Jean-Jacques Dubray
@jdubray
Feb 05 2016 22:47

@brucou

It escapes me how this is so from your sample code. Could you expand on that,
i.e. what is S, vm, A, nap in the example?

S -> state
vm -> no view model in the sample code (people might actually complain that passing the model as an argument to the view is bad, which is true, I should pass arguments like "counter" to the view, not model
A -> actions
nap -> state.nextaction()

@brucou

corrected orthogonal diagram

Bruno, your diagram is close but I am not sure why the model would "present". The sequence is as follows:
data ' = action(data)
model = model.present(data')
view = state.render(model,nap)

Fred Daoud
@foxdonut
Feb 05 2016 22:52
@jdubray thank you for clarifying.
brucou
@brucou
Feb 05 2016 22:56
Jacques, in your example, present is a function of data but also of model (through closure once again).
so it is more like model' = model.present(data', model)
Jean-Jacques Dubray
@jdubray
Feb 05 2016 22:58
@foxdonut thank you for writing the sample with cycle.js. I'll have to digest it. Part of the value of the pattern is that we can do simple things relatively simply. The problem I see in our industry is that we quickly make things out of reach for average developers, SAM starts with a very low barrier of entry.
brucou
@brucou
Feb 05 2016 22:59
I don't consider present to be a function of state though, because state is never modified, hence it can be considered a constant
one benefit of the diagram is that it shows that present is the only function modifying model
Jean-Jacques Dubray
@jdubray
Feb 05 2016 23:02
@brucou you can "wire" the pattern any way you want, in the code sample, I wanted to show the elements of the pattern (view, action, model and state) as well the "reactive" loop as opposed to the "interactive" aspects of MVC: the action does not wait on a response from the model, the model does not wait on a response from state, the state does not wait on a response from the view, the view does not wait on a response from the action.
This reactive loop is the most important thing to consider, it does not matter how you achieve it.
"Interactive" programming needs to go? what do you think?
brucou
@brucou
Feb 05 2016 23:06
I hear the words and the intention but I am confused about the meaning and the theory.
I don't see how the barrier of entry will be low, if the theory is hard to understand and the example does not illustrate it well. I am not discussing the theory here, which could be totally valid, just that it is not well defended by your example.
I have no doubt everything is clear to you, the issue now is to educate others about it, and that requires more rigor in the presentation and explanations.
rosencreuz
@rosencreuz
Feb 05 2016 23:09
I actually can understand the concepts looking in the sample code. A little difficult to get it in the first glance, but that's not because the concepts are difficult to get, but because coding of the sample is not that great.
brucou
@brucou
Feb 05 2016 23:09
it allows understanding, criticism, and improvements
rosencreuz
@rosencreuz
Feb 05 2016 23:10
I think a good JS dev can easily make this code more understandable.
I actually have another question. How to go to next step from here. How can I create a component and use it in another component?
I also agree that it's very crucial to understand the reactive loop. It took me some time. The formule V=... was not particularly useful for me. I understand it from code. It would be very useful for me if there was a list of each step in the reactive loop with explanation of what happens in each function.
Jean-Jacques Dubray
@jdubray
Feb 05 2016 23:15
I don't write code for living, so please feel free to criticize my code. I also use the pattern with node.js and generally without automatic actions. I just wanted to create a standalone example that was doing some non trivial things. Perhaps the best is that I start sharing some of my node.js code?
rosencreuz
@rosencreuz
Feb 05 2016 23:22
sorry jj, no criticism on the coding, no big expectation on that. The pattern is very interesting, but it was very difficult for me to get it from the article, I guess for others as well. The code made it clear for me. Unfortunately, it looks like not everyone has the same experience with the code neither.
brucou
@brucou
Feb 05 2016 23:23
In my opinion, the level of your example is fine, but you really have to rewrite it or ask somebody to rewrite it, and match that with the formula you wrote here.
rosencreuz
@rosencreuz
Feb 05 2016 23:23
Maybe you can also write another article for dummies :smile:
brucou
@brucou
Feb 05 2016 23:23
I would also be careful about my terminology, because reactive and interactive may mean different things to different people.
rosencreuz
@rosencreuz
Feb 05 2016 23:27
i say that's bs. This is about a new pattern/new concept. You should expect that there's different terminology.
brucou
@brucou
Feb 05 2016 23:27
I fail to see how this is less interactive or more reactive than, say, react+redux, cycle.js, even Ember to be honest. You are reacting to the user input through actions, all the rest is the chaining of imperative function calls. Why is your 'architecture' (don't know how to call it) more reactive?
I fail to see how it is more functional through your example because there is almost no pure functions used. But that could be rewrote in a more functional way I am sure but I would need to see it. Making functions pure actually cause a few headaches, that will be interesting to see how they are resolved - and proving that it can in fact be resolved.
rosencreuz
@rosencreuz
Feb 05 2016 23:29
It's not like you change model and then wait for something to update itself based on your change (that's the magic frameworks are doing). Here user action goes and changes everything.
brucou
@brucou
Feb 05 2016 23:31
And when that is all done, I don't see the definitive advantage, that clearly this architecture has and the others don't. Which is the one thing that must be absolutely clear to everybody to drive adoption of this architecture.
Jean-Jacques Dubray
@jdubray
Feb 05 2016 23:35
If you look some of the examples from Redux, you see that the pattern tangles actions and model. That's less "reactive". SAM avoids that problem with nap(). Since that's coming from TLA+, that's pretty solid. At a high level I'd be the first one to admit that's the major difference, between SAM and everything else. I tried to talk to Dan Abramov about it, but he never replied to me.
With that being said, I also wanted to show that you actually don't need a framework as heavy as React+Redux or even Cycle.js. I am sure there are good reasons to use them, but I see today the Frameworks being in the way of good architecture. Take React for instance, they started with a great foundation / principle and I feel the framework they built destroyed it all. The framework must come to solve specific problems.
Jean-Jacques Dubray
@jdubray
Feb 05 2016 23:41
@brucou the clear advantage is that you don't need a Framework, learning curve is nearly zero.
Second, and as I said in the article my goal was to decouple the APIs from the view. That is a clear tangible achievement, no more BFF pattern. I know of entire companies which collapse under the weight of "ephemeral" APIs and the BFF pattern.
brucou
@brucou
Feb 05 2016 23:45
jacques, forgive me but I would argue with the last point. First, it is like saying that the clear advantage of coding just with jQuery is that the learning curve is nearly zero. Second, as I said before, don't underestimate the learning curve of something which is not well explained and new (i.e. no book on the subject, no help forum, no good simple and complex examples, etc.) I mean many people could do stuff and think that they are doing SAM when they are actually doing whatever.
I read your article about BFF, all that is new to me, and very interesting, and I will read more about the subject.
Jean-Jacques Dubray
@jdubray
Feb 05 2016 23:45
When you put these two things together, low barrier of entry/common skills and significantly lower API effort on the server. Not sure what's left to argue. Who wants to learn angular2? who wants to build 80% more API code?
I hear you and it is clear I need to share more code.
brucou
@brucou
Feb 05 2016 23:48
Probably so. I am interrupting my conversation, I am going to read some articles about TLA+, maybe that might help.
rosencreuz
@rosencreuz
Feb 05 2016 23:52
It would be really nice, if you eli5 a little about how to create and use components
Jean-Jacques Dubray
@jdubray
Feb 05 2016 23:54
@rosencreuz if you share your email, I can send you some files, I just can't share them publicly because they embed copyrighted materials
@brucou TLA+ is a bit hard to approach, because it comes with its own syntax and tools and it's not a programming language
I tried to talk to Dr. Lamport about bringing the semantics of TLA+ to developers, because I see a big value, but, he is busy with other things. He got a Turing award for TLA+, so all I can say is that it's really solid. AWS is using it for finding bugs they cannot find otherwise
Jean-Jacques Dubray
@jdubray
Feb 05 2016 23:59
@PaulRogers909 yes the template syntax would work great, I tend to be religious about my coding patterns in JavaScript, one I find one that works, I just never question it... I am sure a lot of people would relate to that. That being said, I am not sure we can get read of the \n\