These are chat archives for jdubray/sam

24th
May 2017
Victor Noël
@victornoel
May 24 2017 12:03
Hello :)
I'm trying to wrap my head around SAM, so I have a few questions!
I've just read the discussion above about the difference between reducers and SAM and vuex, and I don't get it: @jdubray you say "I'll take vuex anytime over the best reducer" but I don't see how vuex differs from, say, redux, where you have actions (actions are just string and some payload) that you submit to the store (the call to context.commit() in vuex) and the reducer implementation (the mutations of vuex) that will modify the state. What is there in vuex that is not there in redux?
(I can see vuex has a dispatch and a commit, while redux and co usually only have a dispatch (which act as a commit since actions are handled synchronously), but this is just syntactic sugar to me, no?)
Victor Noël
@victornoel
May 24 2017 12:50
ah, I see the difference is that actions are used to do some work which can result in commits, while with redux (or at least with ngrx, which I'm familiar with), you would use actions to trigger both mutations (via the reducers) and what is currently done in vuex actions (in the effects).
so, in the end, you seem to get the same thing with a design just a bit different it seems…
devin ivy
@devinivy
May 24 2017 12:59
@victornoel yes, with some discipline you can definitely do the same thing with redux!
Victor Noël
@victornoel
May 24 2017 13:00
@devinivy ok, thanks for confirming. so now I can start thinking about SAM and it fits (or does not fit) within this frame of mind :)
Jean-Jacques Dubray
@jdubray
May 24 2017 13:00
The fundamental goal is to decouple the view components from the model. Things like 2-way databinding cannot scale with the complexity of front-end we are currently building, not to mention the omnichannel aspects (web, mobile, wearables, voice...). You want to be able to plug your app logic (and state) wherever the user wants to "inter-act". The industry is now pretty on the right path for view components V = f(M) has changed the game (thank you React) and given some props a view component renders (as a function) and emits events.
The problem with redux is that the basic programming model is these events are framed as "actions" (a data structure). Of course React/Redux is what it is you want it to be, once you select the 20 libraries or so you think you need, you are ready to achieve what SAM can do in a single line of code.
Victor Noël
@victornoel
May 24 2017 13:00
ok, yes, I see :)
thanks!
Jean-Jacques Dubray
@jdubray
May 24 2017 13:01
Actions cannot be simple data structures, an action needs to validate, transform and enrich events in such a way that the model is presented what it needs to decide what to do with the event.
event -> (intent) -> action -> acceptor (model)
What Redux does is that it cobbles together the (action->acceptor) step since it is a pure function it does not allow to call an API (within the reducer) to enrich the event.
So of course, you can use thunks and what not but when you leave 15 options open to achieve a particular outcome, discipline is something that doesn't come cheap, especially in diverse teams under tight deadlines.
devin ivy
@devinivy
May 24 2017 13:04
you want to be able to call an API in both the acceptance and proposal steps?
Victor Noël
@victornoel
May 24 2017 13:05
@jdubray ok, because with ngrx and ngrx/effects, you get that separation: you have on one hand the reducer (mutator of the state) that reacts to the actions (that are dispatched), and on the other hand the effects that reacts to the action by triggering side-effects and maybe dispatch new actions based on the result. So it is quite elegant (and integrates very well with rxjs).
so yes, there is one concept (action) designing the intents of both for the mutation of the state and the side-effects, but apart from that, it is comes naturally like this
Jean-Jacques Dubray
@jdubray
May 24 2017 13:05
@devinivy As I mentioned before I like to call queries in actions and create/update/deletes in the model.
@victornoel well, the problem with that is that you start maintaining ancillary state machines to keep track of these actions and that's not pretty at all. Redux has once promoted sagas but the drawback is that you no longer have a single state tree.
SAM has the next-action-predicate that allows you to achieve the same thing and that's not pretty at all when you manage enrichment that way. Lots of unnecessary boilerplate code.
Victor Noël
@victornoel
May 24 2017 13:08
hmm, I need to read more then, I'm not exactly clear on what you mean there :)
devin ivy
@devinivy
May 24 2017 13:10
first, i'm not a fan of sagas. at the same time, i have yet to see a solution that makes use of the state tree and is as flexible as sagas. the nap() can't do everything a saga can do.
but i would encourage folks to use nap()– it is definitely multi-purposeful.
Jean-Jacques Dubray
@jdubray
May 24 2017 13:11
When you trigger a new (secondary) action to enrich a primary action you need to keep track of that in the model (application state), otherwise you are not completely sure that you are waiting for this. You also need to detect in the reducer that's what you want to do. That's very very messy. It's a lot cleaner to do it in the primary action before it hits the model.
devin ivy
@devinivy
May 24 2017 13:11
that's interesting. i'll have to unpack that.
Victor Noël
@victornoel
May 24 2017 13:12
I'm not sure that's what happens with ngrx/effects…
devin ivy
@devinivy
May 24 2017 13:12
can you give a slightly more concrete example?
Jean-Jacques Dubray
@jdubray
May 24 2017 13:12
@devinivy ? me
Victor Noël
@victornoel
May 24 2017 13:13
See for example this very basic example: https://github.com/ngrx/effects/blob/master/docs/intro.md when there is an action of type LOGIN dispatched, a side-effect is executed and it will result on a new action being dispatched (in the map), but you could chain multiple actions that are related but wouldn't need to be stored in the state
devin ivy
@devinivy
May 24 2017 13:13
@jdubray yeah! the secondary action enriching a primary action, and making it less messy by doing some work in the primary action before hitting the model. having trouble picturing this.
Jean-Jacques Dubray
@jdubray
May 24 2017 13:16
The reason why it's quickly getting out of hand is that nap is really designed to identify "big" state/status, rather than working off ancillary states (like you need to trigger that action to get more data).
devin ivy
@devinivy
May 24 2017 13:18
well one thing i imagine using nap() for is this– imagine a model with 1. a map of Post records indexed by id and 2. a currentPostId.
Jean-Jacques Dubray
@jdubray
May 24 2017 13:18
my nap looks like this:
if (this.needsDataX(model,aid)) {
            a.getDataX({actionid: actionId, options})
            return false ;
        }
        if (this.needsDataY(model,actionId)) {
            a.getDataY({actionid: actionId, options})
            return false ;
        }
devin ivy
@devinivy
May 24 2017 13:18
when the user changes currentPostId, if that post isn't the map of all Posts then the nap() could kick-off an action to get it.
yes, you and i use it the same way.
(i think.)
this is very powerful because it let's the application operate headlessly, without view component lifecycles being necessary to get "required data." in other words, data isn't required just because it needs to be seen in the view. it's required because the application state reflects that it's necessary to obtain it.
Jean-Jacques Dubray
@jdubray
May 24 2017 13:20
then I need to detect the state from the model
  needsDataX(model,actionId) {
        try {
            if (!model.data.home.dataX) {
                if (model.data.home.dataY) {
                    if (model.data.home.dataZ) {
                        return true ;
                    }
                }
            }
        } catch(e) {
            // no table data

        }
        return false ;
    },
Victor Noël
@victornoel
May 24 2017 13:21
ok, the nap is triggered by nothing else than just the fact that the model (or the state…) was previously updated, right?
Jean-Jacques Dubray
@jdubray
May 24 2017 13:21
It's difficult to decide when it's the right time to get the data, unless you propagate the original action through the model. In this particular case I am collecting all the data to represent in the customer portal dashboard.
@victornoel yes,
nap is really the equivalent of "automatic actions" in a state machine.
It's not designed to managed ancillary state machines.
Victor Noël
@victornoel
May 24 2017 13:23
ok, with ngrx/effect, you wouldn't be able to express that like this I think… except if you dispatched a generic action after every action has been processed ^^
(and then we come back with the fact that it means you need many complexities/libs/abstractions to do what is easy to do with SAM)
things are a bit clearer, now I need to get clear on state versus model, I will read the sam page again before asking more question :)
Jean-Jacques Dubray
@jdubray
May 24 2017 13:29
The state (representation) is about decoupling the model from the view components. The state is a function that simply converts the model into properties consumable by the view components. Something again that React/Redux or Angular2 does not really consider, though @devinivy has shown how useful this idea can be in a React store.
Victor Noël
@victornoel
May 24 2017 13:30
ok
Jean-Jacques Dubray
@jdubray
May 24 2017 13:30
SAM is simple but not simpler, it's semantics are very precise and so far I am yet to see something I cannot do simply without a single library.
For Angular2 I use ngrx to wire the SAM pattern into ng2 components (pub/sub model). It works really well.
Victor Noël
@victornoel
May 24 2017 13:31
I would really love to see a clean use of the SAM pattern in an angular application (because that's what I am familiar with). I found the examples of github do be a bit difficult to read.
ah ok, and do you have published example of that?
that's exactly what I am looking for :D
Victor Noël
@victornoel
May 24 2017 13:32
ah, ok, I didn't realise it was that, I tried to read it but got confused by the code, I will fire up my IDE and explore it again
Jean-Jacques Dubray
@jdubray
May 24 2017 13:32
I worked on a foundational project for a Fortune 50 company last year, SAM/Angular2 is now their official application architecture.
There is also a video, but it's really trivial.
Victor Noël
@victornoel
May 24 2017 13:52
@jdubray now I'm even more confused, looking at the example in the video (the slide with the ng2 component on the left and the rest of the SAM architecture on the right), I really don't see how it differs from ngrx (not rxjs!) at all: there is a store (your injectedState), you can subscribe to some aspects of it via rxjs subscriptions (your call to subscribe()), you can dispatch some events to the store (your call to actions()...), you can mutate the state of the store via reducers (you model) and the ngrx store notify subscribers of changes (your State again).
If you have a websocket somewhere receiving extra events, you can dispatch them to the store too (and the view will be notified via the subscriptions)
If you have api calls to make you can define effects which are triggered by the events too and which can triggers new events at the end of these side effects, effectively triggering mutation of the state.
In a way, the only difference I can see is that events are both received by effects and reducers, so you these are two different concepts with the same name, and it's not the best.
And then there is the next state action, but don't see why you would need it if you have the effects… I will maybe need to research a bit more on that point (maybe @devinivy if you could point me to some example of how you used NAP with a react store as @jdubray was saying?).
I think it could be cool to have an example with angular 2 and ngrx, it would simplify a lot the code and better highlight were SAM differs maybe, because in your example you reimplement the store pub/sub mechanism by hand, so it makes thing a bit less clear :)
(ngrx or any other pubsub like system, if you want to avoid the store abstraction of ngrx and handle the state yourself)
euuh, the model sorry!
Jean-Jacques Dubray
@jdubray
May 24 2017 14:04
@victornoel I have lost track of where ngrx is, we don't hear much about it. If it has become the same, that's good, ultimately, I believe SAM is where the convergence will occur, even when you use a declarative way to write nap(), that's ok.
That being said, I certainly would encourage everyone to come to a single definition of what we call an action. Imagine if everyone had a different definition of what a function is?
But even such a trivial request is met by the highest contempt by Dan Abramov, Lee Byron or Michel Weststrate. I mean really?
I don't have time to write that kind of sample now. I'll do the vuex sample next.
Victor Noël
@victornoel
May 24 2017 14:07
great cool, thanks anyway for taking the time to answer questions :)
Jean-Jacques Dubray
@jdubray
May 24 2017 14:14
no problem, any time.
devin ivy
@devinivy
May 24 2017 14:14
@victornoel i don't have an example i can link you to– but the concept is mostly that the application can decide that there's "missing" data from the model, and dispatch an action on its own to go get that data. what you often see instead is dispatching the action in the view component that wants to display that data.
Victor Noël
@victornoel
May 24 2017 14:15
@devinivy and how do you manage to implement that? at which point to you put that decision in practice? I really like the idea yes!
Jean-Jacques Dubray
@jdubray
May 24 2017 14:16
@devinivy I would discourage that practice. It would mean that the view component has some state.
sorry, I misread your comment
Victor Noël
@victornoel
May 24 2017 14:16
:)
Jean-Jacques Dubray
@jdubray
May 24 2017 14:17
yes, that's the idea, you want the application state to make these decisions, not the view component at all.
Victor Noël
@victornoel
May 24 2017 14:18
@jdubray but how do your application state know that it needs to retrieve this data? it's because the view has been displayed, so at one point, you will need the view to tell the state that it needs this data, no?
Jean-Jacques Dubray
@jdubray
May 24 2017 14:20
the application is in a given "state", for every state it knows which data it needs. The State (representation) is a headless proxy of the view.
Victor Noël
@victornoel
May 24 2017 14:21
hmmmmmmm, ok, I once again confused state and model…
Jean-Jacques Dubray
@jdubray
May 24 2017 14:21
The way I see it is that from a model/business logic perspective the view components are just a source of events.
Victor Noël
@victornoel
May 24 2017 14:21
and how does the application knows that it is in a given state? as the result of an action?
Jean-Jacques Dubray
@jdubray
May 24 2017 14:21
The example I take is the one of an electric car. A state would be "started".
How do you compute the state from the model?
you need to take into account the battery level, but also the destination. There is no point in starting your journey if you can't get there.
the model holds the destination and battery levels, it knows nothing about "started" or "paused".
The model know nothing about next actions. This is really a question of roles and responsibility, a factoring that otherwise would lead to spaghetti code.
It would be much harder to maintain without breaking it down that way.
At least for me.
Victor Noël
@victornoel
May 24 2017 14:25
until there I follow you, but then, let's say I have an application with a list of articles, and there is a view to look at one of the article. how would you represent that then? the model is what? The list of articles titles as well as the content of the articles (but only those that have been retrieved when needed), right?
or is some of that the state?
(so I have an API call to get the list of articles titles/id, and one to retrieve each article)
Jean-Jacques Dubray
@jdubray
May 24 2017 14:28
That's where the decoupling makes sense, that's how I came to apply SAM to front-end architecture, what happens generally is that the designer of the view tells you it needs an API to get a single item to display that view. With SAM it the shape of the model (and therefore the APIs that populate the model) are no longer bound to the shape of a view (even when you use one-way data binding with say, ng2 templates).
The state function will be responsible for computing the view properties from the model. Nowadays, an API call is very cheap, you can get lots of data in 100ms. There is no reason to have one-to-one relationships between views and APIs.
SAM solves that problem really well.
Victor Noël
@victornoel
May 24 2017 14:31
so in my example, what do you put in the model? the id of the article to be read? (and then the state function would do the API calls to compute the data for the view?)
Jean-Jacques Dubray
@jdubray
May 24 2017 14:32
the state function never does any API call. API calls are always in action (queries) and model (create, update, delete)
what I was saying is that you can fetch everything in one call even if the view cannot display everything, it's there for the next event
SAM encourages building much coarser APIs, I don't think anyone would complain about it. Fine grained APIs are hard to maintain.
devin ivy
@devinivy
May 24 2017 14:38
@victornoel in redux, it's simply a store subscriber that fires actions :)
Victor Noël
@victornoel
May 24 2017 14:48
@devinivy ok, so it subscribes to the data it is interested in and fire actions when needed. Obvious once you say it :)
Daniel Neveux
@dagatsoin
May 24 2017 14:48
@victornoel
Your model could contains the id of the articles and the current open article content.
1- The view will trigger intent like {type: GOTO_ARTICLE, {id: 123}}
2- then the action will treat de demand thanks to an API call.
3- Once the data are received, the action will present the new article content to the model {mutationType: CONTENT, content: article.content}
4- Once the mutation is finished the State function will be aware that the model is mutated and its NAP function will look if it is in a specific change. If it is, the NAP function will (or not, depend of your logic) trigger a new automatic action (for exemple, FLUSH_OLD_ARTICLES)
5- Then the State will tell the view "hey, something changed in the Model, plz, refresh!"
Victor Noël
@victornoel
May 24 2017 14:49
@dagatsoin ok that seems fair, but I had the feeling that @jdubray was saying it shouldn't be done like that…
Daniel Neveux
@dagatsoin
May 24 2017 14:49
ha, where ?
Victor Noël
@victornoel
May 24 2017 14:49
hence my question (because that's exactly how I do it in my application)
Daniel Neveux
@dagatsoin
May 24 2017 14:50
could you point to the counter argument plz (he talks a lot...)
Victor Noël
@victornoel
May 24 2017 14:52
@dagatsoin that's what I gathered from my interactions, he didn't exactly say that, so I was trying to understand and clarify through my questions, look at the point where @devinivy said he didn't have an example for me to link to, at 16:14, and the discussion that follows
@jdubray in the application I work with, you can't just fetch all the data at once, you do need to select it at one point (depending on the state of your application). but I understand that I can separate the fact that I'm trying to view something and the fact that I need to fetch it from an API call.
Daniel Neveux
@dagatsoin
May 24 2017 14:56
It seems you understood the most part. Maybe you are still confused about what a computed state is?
Victor Noël
@victornoel
May 24 2017 14:56
maybe yes ^^ but my question at first wasn't about the state itself in any case
so @jdubray you agree with the design proposed by @dagatsoin (in term of pure SAM architecture : )
Daniel Neveux
@dagatsoin
May 24 2017 15:01
Important part of the last point that I missed: the view is not aware how the model is. The state sends a representation of the model to the view with just the informations the view need to know (a viewModel)
In Redux , it is like a bit the "connect" part.
Victor Noël
@victornoel
May 24 2017 15:03
yep ok
I think that what is misleading in the SAM website and videos is that it points to bad design behaviours (that it want to correct), but these are not behaviour I actually see and follow, so I have trouble really seeing how SAM differs from what I am doing. In a way, when you are doing similar but not quite, it is harder to see what is good in a different thing, it asks for more efforts to look for what is different. hence all my questions :)
Daniel Neveux
@dagatsoin
May 24 2017 15:06
I think the website seriously needs https://code-cartoons.com/ :)
Victor Noël
@victornoel
May 24 2017 15:07
hehe, nice find :)
Daniel Neveux
@dagatsoin
May 24 2017 15:07
I spent weeks to understand SAM too.
Victor Noël
@victornoel
May 24 2017 15:08
I've been looking at it for a long time, but today I finally decided to go ask questions (also now I'm clearer on redux and co, compared to before, so it is easier and harder at the same time)
devin ivy
@devinivy
May 24 2017 15:12
the three notable features of SAM (for me) are,
  1. have an intermediate representation of the application state, catering to the views. in redux this means add logic into connect() (don't just pass through values directly from your model).
  2. make sure your model is doing the job of keeping your application in a valid state, not just taking values from actions for granted. this allows callers of actions to not have to know about application rules, and not have to worry about invoking an invalid application state.
  3. use nap(), which can be thought of as subscriber to state changes that fires actions, so that your app state has control over itself and does not rely on the view to e.g. have live data.
Jean-Jacques Dubray
@jdubray
May 24 2017 15:14
@victornoel you can do it any way you want, I was just suggesting that you are not forced to do it that way.
Victor Noël
@victornoel
May 24 2017 15:15
yes, I'm mostly looking for example of how you would do it, to understand better the pattern
Jean-Jacques Dubray
@jdubray
May 24 2017 15:16
the advantage of SAM is that the view no longer drives the footprint of the APIs
Victor Noël
@victornoel
May 24 2017 15:16
yes, that part on coarser api and the non-view-driven is clearer for me now!
I have to go for now, thanks all for the time, I will let all of this integrate in my mind now :)
Jean-Jacques Dubray
@jdubray
May 24 2017 15:19
:thumbsup:
Jean-Jacques Dubray
@jdubray
May 24 2017 15:39
@devinivy I would add 4. a clear articulation between your application logic and APIs whether you use actions/nap or actions/model
@dagatsoin was it worthwhile? (I am not looking for praises, just your honest opinion).
Daniel Neveux
@dagatsoin
May 24 2017 15:45
The time spent? Definitly! It is like a magic wound that I point on all projects.
I use it in my MMORPG (mobx react) and in my daily job as a front end developper since a few weeks (vuejs vuex)
Jean-Jacques Dubray
@jdubray
May 24 2017 15:48
thank you!
Daniel Neveux
@dagatsoin
May 24 2017 15:49
I also think the main obstacle to popularity is an easy explanation. But I understand, regarding your bg, that it is not easy fir you. If code cartoons could be interested to explain what is SAM in her way, I have no doubt on the SAM future. Plus the name is great.
Maybe Vuex would also be also a good relay to lower the learning curves.
Marcus Feitoza
@mfeitoza
May 24 2017 15:52
@dagatsoin the explanation of SAM is simple. The main problem are the devs that are so dependents on examples instead of understanding concepts
In some of my reads of Dr. Lamport and watching some videos I really change my mind set.
Some of the videos I watch he said "examples are bad ways to understanding, because you will grasp in context of example" (something like this)
Daniel Neveux
@dagatsoin
May 24 2017 16:00
Well I am not sure this is as simple. Or I am very dumb to not understand it under several weeks :p
The way it is explained is very "universitary" (don't know the right word in english). With high abstraction semantic in opposition with low level examples in pure JS.
But, I agree that most front end developers are used to frameworks and don't know how learning without them. So the gap between mobx/react/redux/whatever and SAM is reeaaaaallly high.
This is what I felt.
Daniel Neveux
@dagatsoin
May 24 2017 16:14
It is very hard to explain simple things. Especially when it appears obvious to a high skilled person.
Frameworks are learned with code examples.
Pattern are learned with stories of projects.
For me, Gang of Four made it with their book in a brillant way (biased here) and the magic did the trick. Now, I can't look at a project without thinking through their patterns.
Jean-Jacques Dubray
@jdubray
May 24 2017 16:20
I think it's a good suggestion, I should have different learning paths depending on what people are most comfortable with. I've had some serious health issues in the last three months and I have not been able to contribute much other than answering questions in this forum. Things seem to be turning around now, I hope I can make more videos and code samples soon.
Marcus Feitoza
@mfeitoza
May 24 2017 16:38
@dagatsoin I understand.
I have the same issue with my first contact with SAM, so start to learn more about state machines and so on, and things become more clear.
In SAM you can wiring in many ways and the wiring will depend on your context (libs, your skills and taste).
Like I said people will think in terms of examples instead of really understand the concepts of SAM and I did this mistake.
In Redux you learn the concepts and how exactly you need to wiring everything like every other libs.
And a I still a lot to learn and try not only about SAM.
@jdubray Hi JJ, if you have interest to writing a Code Cartoon I can help with drawings. :)
Jean-Jacques Dubray
@jdubray
May 24 2017 16:48
Sure, my drawing skills are as good as my coding ones :-) Happy to publish them or any code sample!
I am a first principles guy, I like to understand how things work at the lowest level possible. That's why I went down to state machines, with clear understanding that you never code like a state machine, but if you can't grasp what's going on a that level, then you can't be sure your programming model is sound. It has to work at every level.
That's why I am troubled when people don't want to discuss what is the nature of an action. They hear that term repeatedly throughout their career and yet, they can't point to "the" definition. Worse, anyone can show up with a definition and nobody seems to be bother.
Please understand that I am not asking to use SAM's definition of an action, I am just asking to have the conversation to have a unified definition. We can then go back and articulate frameworks, libraries, patterns,... around that definition.
Jean-Jacques Dubray
@jdubray
May 24 2017 16:54
For instance if we decide that an action IS-A data structure, it still fits SAM, I'll replace proposal by action and call action something else. We are just creating a lot of friction in the industry with fuzzy semantics and ever changing programming models.
Jean-Jacques Dubray
@jdubray
May 24 2017 17:09
As I said before, that post was the "click" to get to SAM.
Programming languages need to be action-oriented, that will never change, but action cannot always decide what is the end-state of a system. Intuitively that's clear to a lot of people, but most people would not be able to factor it in their code.
Jean-Jacques Dubray
@jdubray
May 24 2017 17:15
From there, you ask, in my current programming model (OOP, FP, RFP, ...) where does that materializes. Where are the actions, the states (and the overall model from which the states are computed). Unfortunately we have all been trained with the wrong model of state machines. So we have all dismissed their utility and lost any connection to the programming languages every day. TLA+, and hence SAM, allows us to realign programming languages and (non classical) state machines. IMHO, when you do that everything becomes super clear, at least for me. I can write very large amounts of code without ever getting lost.