These are chat archives for jdubray/sam

1st
Sep 2016
Anthony
@tribals
Sep 01 2016 08:37
hi there!
just read about SAM, and it sounds amazing. But, there is some gotchas that i can not understand. Can anyone try to explain it for me?
Jean-Jacques Dubray
@jdubray
Sep 01 2016 10:55
welcome!
Anthony
@tribals
Sep 01 2016 10:55
thanks!
Jean-Jacques Dubray
@jdubray
Sep 01 2016 10:56
It probably depends on what you are trying to do and the technology you plan to use.
Anthony
@tribals
Sep 01 2016 10:57
i really interested in you investigations, ability to straight decoupling of views and models is enchants me
Jean-Jacques Dubray
@jdubray
Sep 01 2016 10:57
Yes, this should be the main goal of anyone building the front-end.
The granularity simply cannot be the same, in other words you should not expect that what you see on the view should be commensurate to the units of work involved in modifying the model/application state
The main point to understand about SAM is that when all other Web frameworks focus on a simple (reactive) loop:
event -> (lots of code that updates the model) -> render the view
Anthony
@tribals
Sep 01 2016 11:00
the one big question is: what the model is? what you mean by 'model'? is it a one, big model of entire app, or it the "classic" model, that is the model of real life objects, like "users", or "books", or "posts"?
Jean-Jacques Dubray
@jdubray
Sep 01 2016 11:01
The application state, aka model should be viewed as a set of key value pairs
Single state tree is essential to SAM (and Redux for instance)
Now, SAM allows you to compose instances following a parent child structure when it makes senses (e.g. a wizard/complex form)
It's not so much of a burden to use a single state tree, as long as the business logic is well structured, and that's where SAM differs from other approaches. The business logic is structured in three buckets
Actions
Model
State
The rules to decide what goes where are usually easy to follow
So the flow in SAM is:
event -> action -> model -> state -> render the view
           ^                |
           |--------nap-----|
Anthony
@tribals
Sep 01 2016 11:08
simple exapmle: i've a model that holds state of the complete UI, like 'initial', 'listAllUsers', 'changeOneUser'. When i fire up an action, i.e. 'changeOneUser', i redraw some parts of UI to display form for user editing. But, because of my app is single page app, i 've a navigation bar, simple links that fires actions. I impelmented this easy, but messed up my actions, because the state of navigation bar also must be updated, for example, to highlight current app page.
what i realized is than the NavigationBar must be also a model, and must be embedded to reactive loop
it is true?
Jean-Jacques Dubray
@jdubray
Sep 01 2016 11:09
Yes that's not hard at all, yes it is true
this is where the State (function) heps, it is responsible for computing the state representation from the model
So technically you do not need to maintain a dedicated model for the nav bar
the state function could easily compute the state representation of the nav bar as a (pure) function of the number of records of the users array

The way you would structure your app is:
a) in index.html you have three divs

<div id="navbar></div>
<div id="data"></div>
<div id="footer"></div>

The state representation would also be structured accordingly.

Jean-Jacques Dubray
@jdubray
Sep 01 2016 11:14
Depending on your Web framework (or if you are using none), the stateRepresentation can compute new properties as inputs to the view components, the outputs of the view components themselves or closures passed to the view components to execute as they render individually
So it will look like:
stateRepresentation = {
    navbar: { ... props of the navbar as a function of the of model },
    data: { props of the table of users },
    footer: null
}
The convention is if the props are null, then nothing is rendered
You are free to decide how the state function relates to the view, but it's main goal is exactly to decouple the model from the view. The model should not know anything about the state representation (~ or very little, it might have to maintain some ancillary state for it)
The nap function (next-action-predicate) is triggered by the state and computes if there is any automatic action that needs to happen given the new application state computed by the model.
That's pretty much it
Anthony
@tribals
Sep 01 2016 11:20
just a moment, need to go to AFK for a while, sory
Jean-Jacques Dubray
@jdubray
Sep 01 2016 11:20
SAM allows each element of the pattern to exactly focus on its role, there is very little need to break the boundaries of actions, model or state (or view)
no worries
Anthony
@tribals
Sep 01 2016 11:20
well be very soon
Anthony
@tribals
Sep 01 2016 11:55
i currently trying to implement navbar's state representation as a selector of navbar item that shold be activated, and a navbar's view as a function that attaches the classes to needed navbar item, and nap as the function that fires deactivation of unwanted navbar items
Jean-Jacques Dubray
@jdubray
Sep 01 2016 11:56
the deactivation should be part of the state representation, unless I do not understand what you are asking
Anthony
@tribals
Sep 01 2016 11:58
what i want to achieve is composition of models with its own states, state representotion, actions and views
Jean-Jacques Dubray
@jdubray
Sep 01 2016 12:00
sure, but as I mentioned you have to be careful, which one do you need?
  • state / model decoupling
  • parent/child instance
This is what a navbar implementation could look like:
adminConsole.navBar = function(dropDowns) {
    dropDowns = dropDowns || [] ;
    var dd = '' ;
    for (var k = 0 ; k < dropDowns.length ; k++) {
        dd += dropDowns[k] ;
    }
    return  (
              '<nav class="navbar navbar-'+adminConsole.navBarColor+' navbar-static-top" role="navigation" style="margin-bottom: 0">\n\
                  <div class="navbar-header">\n\
                      <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">\n\
                          <span class="sr-only">Toggle navigation</span>\n\
                          <span class="icon-bar"></span>\n\
                          <span class="icon-bar"></span>\n\
                          <span class="icon-bar"></span>\n\
                      </button>\n\
                      <img src="'+adminConsole.logo+'"/>\
                      <!-- a class="navbar-brand" href="'+urls.index+'">'+labels.title+'</a -->\n\
                  </div>\n\
                  <!-- /.navbar-header -->\n\
                   \n\
                  <ul class="nav navbar-top-links navbar-right">\n' 
                  + dd
                  + util.endtag('ul') 
                 + util.endtag('nav')) ; // end navBar
} ;
This is some old code, so let's not discuss the syntax, just the structure
The state representation has computed the dropdowns
Anthony
@tribals
Sep 01 2016 12:03
as i mentioned above, i currently just started to understand SAM, and can miundestood or completely do not understand something
Jean-Jacques Dubray
@jdubray
Sep 01 2016 12:03
it's ok, happy to help
Anthony
@tribals
Sep 01 2016 12:03
why deactiovation should be part of state representation?
Jean-Jacques Dubray
@jdubray
Sep 01 2016 12:04
the way I understand it, this a new state representation, this particular menu item in that dropdown is no longer available
an action modifies the application state
I think what you are talking about is given a model property, this menu item is not available
You could say that given a model property, I want to trigger an action that disables a menu item, but that's not the way the pattern works, this is better implemented as part of the state representation
Anthony
@tribals
Sep 01 2016 12:11
the navbar's itmes can have only two states: active and inactive. So, there are two actions: activate one and deactivate rest. When action activates item, the navbar accepts nev state (like { active: 'home' }, or { active: 'users' }), state representation computes new representation (which is selector of active item) from model, computes next-action-predicat which fires action 'deactivateRestItems, which launches reactive loop again, and finally view renders new state through jQuery'saddClass(no DOM replacement). The 'deactivateRestItems' walk through each step and finaly view doremoveClass` on inactive items
Jean-Jacques Dubray
@jdubray
Sep 01 2016 12:12
The way I do it is that recompute the entire navbar (as show in the example above) and I replace it in place or if you use a virtual-dom library it will do that for you.
A dropdown would look like this:
adminConsole.adminDropDown =
'<li class="dropdown">\n\
    <a class="dropdown-toggle" data-toggle="dropdown" href="#">\n\
        <i class="fa fa-user fa-fw"></i>  <i class="fa fa-caret-down"></i>\n\
    </a>\n\
    <ul class="dropdown-menu dropdown-user">\n\
        <li><a href="'+urls.profile+'"><i class="fa fa-user fa-fw"></i> '+labels.userProfile+'</a>\n\
        </li>\n\
        <li><a href="'+urls.settings+'"><i class="fa fa-gear fa-fw"></i> '+labels.settings+'</a>\n\
        </li>\n\
        <li class="divider"></li>\n\
        <li><a href="'+urls.logout+'"><i class="fa fa-sign-out fa-fw"></i> '+labels.logout+'</a>\n\
        </li>\n\
    </ul>\n\
</li>' ;
As you recompute the new state representation you can enable/disable any item you'd like. There is no need to do it individually.
I need to step out for 10 min
Jean-Jacques Dubray
@jdubray
Sep 01 2016 12:30
Let me ask the question in a different way, what prevents you to recompute the complete navbar?

I am not sure seing the navbar as a model would help, when you say:

navbar accepts nav state (like { active: 'home' }, or { active: 'users' })

That's a bit overkill

It's not false, but in it is not in spirit of SAM
Anthony
@tribals
Sep 01 2016 12:36
there is no critical need to prevent recomputation of entire navbar, why i do it in that way is because my app is very simple, and i write ot navbar completely in html, not in js. I thought about the way you recommend to do the thing, and i feel it is more clear and concise
Jean-Jacques Dubray
@jdubray
Sep 01 2016 12:39
yes, the examples I provided a vanilla.js, but it's always better to recompute large chunks of the view rather than manipulating the DOM with actions
It's not a good idea to initiate an action to change one thing in the DOM
The pattern (and other Web frameworks using the same approach) deliver the most value when you express the View as a function of the application state. Which in SAM is equivalent to V = State(Model)
Anthony
@tribals
Sep 01 2016 12:59
got it, thanks
but i've another question
what about receiving data from some api? where in reactive loop this chunk of code lives?
and how to first init model with data from api?
Jean-Jacques Dubray
@jdubray
Sep 01 2016 13:15
That's a great question, that's probably where SAM shines the most.
Anthony
@tribals
Sep 01 2016 13:16
aww, tell me
Jean-Jacques Dubray
@jdubray
Sep 01 2016 13:16
I would put queries in the actions and present the result of the query when available to the model
then render the results via state representation
Anthony
@tribals
Sep 01 2016 13:16
that's exactly how i imagine it!
Jean-Jacques Dubray
@jdubray
Sep 01 2016 13:16
Great!
Fred Daoud
@foxdonut
Sep 01 2016 13:17
That's a great question, that's probably where SAM shines the most.
+1
Jean-Jacques Dubray
@jdubray
Sep 01 2016 13:17
for create/update/delete types of APIs you could also put them in the actions, but IIMHO, they are better positioned in the model because you cannot change the application state until you got a response
but that's not a hard rule. I am generally concerned with exception handling. Create or Update fails, what do you do? the user has moved on, he was not waiting for the result of the API call.
Anthony
@tribals
Sep 01 2016 13:18
i very excited i realized it after first reading of your article, and it is why i very corious in SAM
Jean-Jacques Dubray
@jdubray
Sep 01 2016 13:18
thank you!
Fred Daoud
@foxdonut
Sep 01 2016 13:19
@jdubray indeed this is where Redux trips and falls, while SAM is clean and smooth
Jean-Jacques Dubray
@jdubray
Sep 01 2016 13:19
thank you Fred!!
Anthony
@tribals
Sep 01 2016 13:20
so, going to code my app armed with new knowledge, and with sparkle in the eyes
Jean-Jacques Dubray
@jdubray
Sep 01 2016 13:20
@tribals you may want to look at the framework that @foxdonut has developed , it really helps with structuring a SAM based app. It's very light weight too.
You should see a big difference! happy to hear your feedback good or bad. If you have any question let us know.
Fred Daoud
@foxdonut
Sep 01 2016 13:23
Thank you for the approval JJ! @tribals I started working on Meiosis using RxJS, but then with @jdubray 's help I discovered SAM and it changed everything!
Anthony
@tribals
Sep 01 2016 13:23
where to look at this framework? during developing my app i devoloped something like framework, and i will be pleased if anyone yet do the work for all of us
Fred Daoud
@foxdonut
Sep 01 2016 13:24
Anthony
@tribals
Sep 01 2016 13:25
thanks, going to check it out
again, thank you guys, going to do the work
Fred Daoud
@foxdonut
Sep 01 2016 13:26
I recently went back to the beginning and looked at the code when I was using RxJS... I am much happier with it now that I am using SAM instead.
I see all the stumbling and struggling in the redux community... I wish some would be more open-minded to consider another approach.
Jean-Jacques Dubray
@jdubray
Sep 01 2016 13:28
can I quote you?
Fred Daoud
@foxdonut
Sep 01 2016 13:36
which part? :)
Jean-Jacques Dubray
@jdubray
Sep 01 2016 14:25

That one:

I see all the stumbling and struggling in the redux community... I wish some would be more open-minded to consider another approach.

Anthony
@tribals
Sep 01 2016 14:30
faced out another problem: where is to attach actions to events?
is an attached event handler parto of representation? or part of which it is?
Jean-Jacques Dubray
@jdubray
Sep 01 2016 14:38
another great question, there a couple of ways I use
this is perhaps the cleanest sample I produced: https://github.com/jdubray/sam-samples/tree/master/todomvc-app
It also implements both ES5 and ES6
In ES5 you somehow need a global var like: var actions = {} ;
then I use a set of "intents" to map user events to actions:
actions.intents = {
    edit: 'actions.edit',
    save: 'actions.save',
    done: 'actions.done',
    displayAll: 'actions.displayAll',
    displayActive: 'actions.displayActive',
    displayCompleted: 'actions.displayCompleted',
    toggleAll: 'actions.toggleAll',
    delete: 'actions.delete'

} ;
Then you can use the intents that way:
const toggleCheckbox = '\
                <input class="toggle-all" type="checkbox" onclick="return '+intents['toggleAll']+'({});">\n\
                <label for="toggle-all">Mark all as complete</label>\n' ;
Fred Daoud
@foxdonut
Sep 01 2016 14:43
@jdubray how about this instead: "If you find yourself somewhat struggling with Redux, and piling on redux-* libraries... Be open-minded to consider another approach."
Jean-Jacques Dubray
@jdubray
Sep 01 2016 14:44
sure, I don't want to make you say something you don't want to say.
Fred Daoud
@foxdonut
Sep 01 2016 15:03
Thank you.
@jdubray along the same lines, while I do refer to SAM in Meiosis, I hesitated to say it was a SAM library in case you didn't approve/endorse it as "SAM-compliant". But if you do approve, I'd like to make SAM more prominent in the Meiosis docs because SAM + the discussions with you are truly what inspired me. My goal with Meiosis really is to implement/facilitate using SAM in applications.
Jean-Jacques Dubray
@jdubray
Sep 01 2016 15:09
Yes, I endorse it, I believe it's a lot closer to SAM than other models.
I am not territorial. Only focus on the end goal, helping people do things better.
Fred Daoud
@foxdonut
Sep 01 2016 15:11
Great! I appreciate that. I feel the same way.
Jean-Jacques Dubray
@jdubray
Sep 01 2016 15:13
:thumbsup: