These are chat archives for jdubray/sam-examples

12th
Feb 2016
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:00
in general the persistent store would sit below the model, the model something like the session data
so I looked at your code. I am not too familiar with Babel, but from what I can see
You are not far
however...
you seem to be writing code like in Redux
Gunar Gessner
@gunar
Feb 12 2016 00:01
hmm right... sorry. yeah I went straight to ES6 syntax.
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:01
that's a big nono for SAM
actions cannot change the model
You cannot write code like:
 case 'SHOW_ARCHIVED':
        database.currentRoute = 'archive';
        break;
The showArchived action need to present the value currentRoute = 'archive' to the model
The model is free to accept it or not (based on other constraints well outside the scope of the action
Gunar Gessner
@gunar
Feb 12 2016 00:03
I see
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:03
That's a very, very important point. Similarly, the action can do stuff well beyond the scope of the model.
This is an essential decoupling, Redux couples strongly the actions with the model, that's a very very poor choice
Gunar Gessner
@gunar
Feb 12 2016 00:04
yeah well it's confusing since in Redux model and state are kinda the same thing
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:04
Yes, my point exactly
Gunar Gessner
@gunar
Feb 12 2016 00:04
Yes, but I only see it now :P
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:04
Dan needs to go back to school and study State Machine 101
The other thing you did was, you rendered the view in the model:
let view = showTodos(todos) + showToggle(route);
Gunar Gessner
@gunar
Feb 12 2016 00:05
Well, have a BS in Electrical Engineering to I'm way out of "scope" here :)
I*
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:05
me too...
Gunar Gessner
@gunar
Feb 12 2016 00:05
rly? awesome
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:05
I have a master in microelectronics and a PhD in physics
who needs a degree to write software anyways?
Gunar Gessner
@gunar
Feb 12 2016 00:05
so I should just present the state to the view, and let it render it
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:06
not quite
Gunar Gessner
@gunar
Feb 12 2016 00:06
Nice. I've worked with Electronic for 3 years, but coding in JavaScript is way more fun then Embedded C :D
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:06
I agree!!
I would recommend you add a method to the model call "present" and the dispatch action will call the "present" method with { currentRoute: 'inbox'}
The model will then understand the intent of setting the currentRoute value to 'inbox'
I know it's overkill for that example, but I am just trying illustrate how the pattern works
Gunar Gessner
@gunar
Feb 12 2016 00:08
yeah yeah sure thing
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:08
Then once the model accepts the value, it calls the state object
I don't think you have a state object
This is where the state looks at the model value and decide how the view should look like
you can use "states" (as in State Machine) or a bunch of if-then-else, the pattern does not care. It only cares that the decision of which State Representation is chosen is outside the model
The last step fo the pattern is the nap(), but in your example you don't have a need for nap()
Babel looks interesting too. How do you like it?
Gunar Gessner
@gunar
Feb 12 2016 00:11
Babel is great. It's actually using syntax that will be/is implemented in the next version(s) of ECMAScript (JavaScript)
so as of today most browsers don't understand it yet, you can transpile the code from ES6 (ECMAScript 2015 actually) to ES5 (which most browsers support)
then, in the future, when browsers update their javascript engine (and users update their browsers) you are able to no longer transpile the code, keeping your codebase
(roughly, thats it)
should I always "present" data that matches my store/persistent-data? like you mentioned
I guess function present's argument can be called intent
Gunar Gessner
@gunar
Feb 12 2016 00:22
What kind of stuff would the action do that's beyond the scope of the model?
An AJAX request?
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:37

I guess function present's argument can be called intent

not quite... all these semantic distinctions are very important. I am a "modeler" and semantics is essential here.

The intent is at the action level (interface to the action). Many actions can modify overlapping properties of the mode. This is why it is important to establish a many-to-one relationship to the model
otherwise you'll start putting CRUD operations in the actions. That's the whole problem of MVC
The best decoupling between the actions and the model is presenting a dataset
All these semantics were not chosen arbitrarily, they represent the "true" factoring of what's going on, even though when you constrain the problems to a single example you could come to the conclusion you don't need that burden.

What kind of stuff would the action do that's beyond the scope of the model?
An AJAX request?

Yes, let's call it an API call to enrich the user data, validate it further, ... something the model does not care about. All the model cares about is that we present data that it can process

Gunar Gessner
@gunar
Feb 12 2016 00:42
but when I defined function present(<what to call this argument?>) {
I see the problem of CRUD in the view/actions
Hm... "dataset"
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:43
you would pass a dataset that the model can understand (form data, Query by example attributes, ...)
Sometimes you would have no choice but to propagate the "intent" for the model to understand what you do
But I argue that the dataset argument offers the best decoupling when possible.
Basically the dataset says "I'd like the model to have these values in the corresponding attributes"
Gunar Gessner
@gunar
Feb 12 2016 00:45
yup
I see
your "state object" defines how the view should look like
I'm using a subscribe/listeners flow but it should work the same
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:47
pus/sub works great!
The pattern does not prescribe how the elements are wired
so the dispatch function looks good
though I would prefer seeing individually defined functions, because these functions can be reused across solutions (with different models and states).
as long as we agree that putting everything inside dispatch will not happen in the real world, it's good
present looks great too. It's good great you put some rules before you update the model. That's exactly where they belong and what the model needs to do (not the actions), again the reason is because the rules can span properties completely outside the control of the actions.
Gunar Gessner
@gunar
Feb 12 2016 00:50
so showArchive() and showInbox() instead of dispatch('SHOW_ARCHIVE')?
there's a lot of discipline involved in using SAM without a framework
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:53
I think the dispatch method is ok, but the implementation of the actions should be outside dispatch
So the makeState function looks good too. I don't understand the magic of the babel syntax
but the implementation looks right
Gunar Gessner
@gunar
Feb 12 2016 00:54
const makeState = db => { = function makeState(db) {
~= actually ^^
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:55
that I understand :-)
Gunar Gessner
@gunar
Feb 12 2016 00:55
oh, yeah sry. what then?
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:55
it's the return ( route: ...)
I don't see how the HTML is generated from the JSON structure
Gunar Gessner
@gunar
Feb 12 2016 00:55
why so? I'm returning an object
JSON = { key: 'value' }
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:56
I understand the JSON structure, but I don't see where it is fed to generate the HTML
Gunar Gessner
@gunar
Feb 12 2016 00:56
in JS it's that easy to instantiate objects
ohhh I get it
in the pub (from pub/sub)
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:57
I guess it's here: listeners.map(l => l(state));
Gunar Gessner
@gunar
Feb 12 2016 00:57
in my present function, after any mutations to my store, I do
    state = makeState(store);
    // Update view
    listeners.map(l => l(state));
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:57
yes, I see now
yes, I'd say that's a great way to implement SAM
Gunar Gessner
@gunar
Feb 12 2016 00:58
Happy to hear it!
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:58
All I ask is that you don't try to "tweak" the semantics we just went over. As you can see it is easy to go one way or another.
Gunar Gessner
@gunar
Feb 12 2016 00:58
I defined makeState b/c I'm pushing only visible TODOs into the state.
That's ok too or would you do it some other way?
of course I could load all TODOs in my state, what i mean is... the State should derive from the Model, so that's ok too right?
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:59

I defined makeState b/c I'm pushing only visible TODOs into the state.

Yes, that's the right way to do

Gunar Gessner
@gunar
Feb 12 2016 00:59
awesome
Jean-Jacques Dubray
@jdubray
Feb 12 2016 00:59
you have two states in your system (inbox and archive)
So it's all good
Gunar Gessner
@gunar
Feb 12 2016 01:00
well thank you very much Jean-Jacques
Jean-Jacques Dubray
@jdubray
Feb 12 2016 01:00
As you can see, no (real) need for a framework when you use SAM. You get some of the benefits of Redux for free
You are welcome!
Happy to share
I learned a lot too! Babel looks interesting
good to hear! here you can try it out in real time and see the transpiling going on
heck, you could actually put my code in there... not sure how pretty it will look, though
Jean-Jacques Dubray
@jdubray
Feb 12 2016 01:03
it's smaller ...
Gunar Gessner
@gunar
Feb 12 2016 01:04
it's what all the cool kids are using LOL
I've heard it has ~40% from CoffeeScript
Jean-Jacques Dubray
@jdubray
Feb 12 2016 01:04
Sorry, I just took a JavaScript class, was tired of writing all this COBOL
;-)
I am way behind
Gunar Gessner
@gunar
Feb 12 2016 01:05
you can run JS pretty much anywhere now days
Jean-Jacques Dubray
@jdubray
Feb 12 2016 01:05
yes, I love it. This is such a wonderful language. I can't believe it was there all along and hardly anyone looked at it
Gunar Gessner
@gunar
Feb 12 2016 01:06
well define "anyone"
Jean-Jacques Dubray
@jdubray
Feb 12 2016 01:06
well, 10-15 years ago, no one was looking at it other than for those pesky HTML handlers
Gunar Gessner
@gunar
Feb 12 2016 01:07
oh, yeah sure. there always better languages sure, but nowadays the ecosystem is so big it's very encouraging to use it
a lot of open-source, and an easy module manager (npm)
I'm heading out now. Thank you again so much for today. I'll let you know as soon as I have something to show. I have some ideas :D
bjordan2010
@bjordan2010
Feb 12 2016 21:36
@jdubray I worked on a similar example. Could I get some feedback on this example https://github.com/bjordan2010/sam_approach/blob/master/todo.html
Jean-Jacques Dubray
@jdubray
Feb 12 2016 23:15
some comments:
first I would try to not to couple too much the model and the state. It's not wrong and indeed sometimes you need to know the (control) state of the model to make the correct update.
So, I would try to avoid using statements like:
if (state.inbox(model)) { model.archive = data.archive || false;
then, I would definitely no tweak the model based on the (control) state, such as:
model.todos = data.todos.filter(model.isArchived);
This should happen in the State object, if this is not reasonable to do in the computation of the view (say because that computation happens in the browser and you do not want to pass the complete ToDo list to the client, you can consider creating a viewModel function vm() that will performa that operation.
Jean-Jacques Dubray
@jdubray
Feb 12 2016 23:22
Otherwise, I want to emphase that you don't need a "state machine" unless you have automatic actions. It would be easier to rewrite the example with if-then-else rather that state.ready, inbox, archived.
There is an argument to be made that state machine end up to be verbose and complex to reason about, so you want to use them when you really need to.
otherwise you are very close! thank you.