These are chat archives for jdubray/sam

19th
Feb 2016
kgranite
@kgranite
Feb 19 2016 18:50
@jdubray - sorry I am just a beginner. How do I start learning SAM? please advise
@jdubray - are Microsoft WebForms (with the ViewState) an example of SAM ?
Jean-Jacques Dubray
@jdubray
Feb 19 2016 19:10
I would argue that this is not an example at all. I am not too familiar with it, but looking at that tutorial.aspx), things like:
if (!IsPostBack)
      {
         myComponent.FillDataSet(myDataSet1);
         DataGrid1.DataBind();      // Add this line
      }
show everything that is currently wrong with the way frameworks are designed. I like the dataset concept because it isolates well the CRUD from the presentation layer, but the code above is basically coupling action with model and view. That's precisely what SAM is trying to solve.
The best way to start is forget all the frameworks, you'll add them later if you need them.
kgranite
@kgranite
Feb 19 2016 19:13
OK, thank you. How do I learn SAM?
I only know C#, HTML5, CSS and JavaScript
Jean-Jacques Dubray
@jdubray
Feb 19 2016 19:14
If you are really a beginner, I would take an HTML template you like and start creating these functions V = f(M) from it
that's where the value is highest, once you see what you can create with just simply changing that paradigm, you'll be driven to learn how to implement actions, model and state.
kgranite
@kgranite
Feb 19 2016 19:15
OK, thank you. I will
Jean-Jacques Dubray
@jdubray
Feb 19 2016 19:15
For instance that is built with SAM: http://www.ebpml.org/about
I built it in a couple hours, completely trivial (with SAM)
kgranite
@kgranite
Feb 19 2016 19:16
you have a PhD :)
Jean-Jacques Dubray
@jdubray
Feb 19 2016 19:16
just a piece of paper
kgranite
@kgranite
Feb 19 2016 19:16
Thank you for your time
Jean-Jacques Dubray
@jdubray
Feb 19 2016 19:17
Then once you happy with that, add a form (e.g. contact form). You'll need a back-end ,C# is good. I like node.js a lot these days
Then on the back-end you just have to follow the pattern: M.present(A(contact data))
then you can wire the model back to the function you created first.
kgranite
@kgranite
Feb 19 2016 19:18
I guess you don't have enough time to create a course a short video on youtube?
Jean-Jacques Dubray
@jdubray
Feb 19 2016 19:18
But the key is to start with V = f(M)
It's a bit hard at the moment, I may have more time next month, but I also need to make a living, I can't share my work on line.
kgranite
@kgranite
Feb 19 2016 19:19
Sure, I understand
Jean-Jacques Dubray
@jdubray
Feb 19 2016 19:20
I don't have an employer who would sponsor producing these samples either (say like Facebook or Google). These guys are just machines.
They produce tutorials, videos, samples,... and they get paid for it.
kgranite
@kgranite
Feb 19 2016 19:20
what about selling a short course on Pluralsight.com?
Jean-Jacques Dubray
@jdubray
Feb 19 2016 19:21
I'll contact them, I know a few people there.
thank you for the suggestion
If you have any question, happy to answer
kgranite
@kgranite
Feb 19 2016 19:21
thank you for your time, I appreciate that
Jean-Jacques Dubray
@jdubray
Feb 19 2016 19:21
sure, any time
Alex Guerra
@heyimalex
Feb 19 2016 20:13

@jdubray

In redux the reducer updates the model as:

state.counter += 1 ;

This... isn't true. You're fundamentally misunderstanding Redux. It actually works exactly as you describe: a reducer takes the current state and an action, and then returns new state. The store manages assignment. There is no mutation. Also it's funny how you're so critical of React, when, and I quote:

[I]... continued with the realization of how significant and innovative the Facebook’s React.js Application Architecture is

Please differentiate SAM from Redux. It looks you just re-invented redux but you switched the names and made an acronym...

Jean-Jacques Dubray
@jdubray
Feb 19 2016 20:32
well... it would be true if there was a second step in redux such as model.present, but from a React perspective, you are done, the new state then triggers a view refresh.
again, there is action logic (what are the proposed value for the model)
then there is model logic, knowing what I know about the state, should the model accept these values or not
you can say redux does it already, sure, why not, but philosophically, this is not at all how Redux is presented, it is truly presented as the actions and the model updates are both happening in the Reducer.
I know it's a small point, but actually essential. That's the problem with all these semantics they all look the same, but they are not, they yield a very different factoring of the code. They cannot arbitrarily be defined, such as the one Dan defined.
What redux does is not "stupid", but it is very different from SAM.
I am not quite sure why Dan has not joined the conversation, the article has had 200k views, retweeted hundreds of times. Is he afraid of something? If it was such a slam dunk to show that SAM is in effect Redux, we'd be done.
Jean-Jacques Dubray
@jdubray
Feb 19 2016 20:37
But it's not, again, two very different semantics, whith SAM:
1) actions (proposed values) are fully decoupled from the model (accepting proposed values)
2) there is a next-action-predicate (once the model has mutated, anything we still need to do?)
Redux puts A+M+nap() in a nicely bundled reducer, and no reducer "composition" does not decouple them at all.
For Dan event sourcing happens at the intake of the reducer, when for me event sourcing happens at the intake of the model, the code that computes the proposed value (A() and nap()) is irrelevant to state mutation. This is a fundamental, absolutely fondamental difference, it changes everything actually.
Are we in agreement?
As I explain in the article, the traditional State Machine semantics which Dan uses are what he found in CompSci 101 textbooks: a state machine is described by tuples of the form (S1,A,S2).
That definition is unfortunately based on an approximation. I am sure Dan likes it because it yields a familiar graph :-)
Jean-Jacques Dubray
@jdubray
Feb 19 2016 20:44
A state machine should rather be defined as (Sk, Ak1,Ak2,...) with a separate Model element calculating the resulting state.
Ak1, Ak2... are the actions that enabled when the system is in State Sk
Everything falls apart when you try to tie a priori the resulting state to an action. This does not reflect at all what is happening in a system. It is an approximation. Some systems can be described that way, but it is elusive to try to describe every system that way.
Jean-Jacques Dubray
@jdubray
Feb 19 2016 20:51

I don't see any incompatibility in saying:

how significant and innovative the Facebook’s React.js Application Architecture

and criticizing how the Facebook team made it incredibly complex for anyone to build anything

Jean-Jacques Dubray
@jdubray
Feb 19 2016 21:00
Just for the record, such that we avoid arguments like "it's all the same", in this video Dan details the implementation of a store.
He explains at 1'30 in the video that "the only way to change state is to dispatch an action" there is no mutation possible in the store, other than accepting the entire state computed by the reducer. This is what is wrong with Redux.

This is how Dan translates it in code:

const dispatch = (action) => {
   state = reducer(state,action) ;
}

Of course you can implement SAM in JavaScript so I can tweak the Redux code to implement the semantics of SAM, but I would be violating the semantics that Dan specified.

@HeyImAlex Are we in agreement?
Alex Guerra
@heyimalex
Feb 19 2016 21:05
This seems like a purely academic argument; you haven't shown how SAM does anything better. Pragmatically, how is the separation of action/model/nap different from it being rolled into a reducer? The ability to do multiple actions in a single synchronous step? Is that actually it?
Jean-Jacques Dubray
@jdubray
Feb 19 2016 21:07
Well that's what you think unfortunately it is not true. Code factoring matters. Not all code factoring are equal.
You are free to believe you can just use any kind of factoring, I don't have to spend any time convincing you otherwise.
You asked me what was different, I told you what was different, so please don't propagate the idea it is the same.
or that I don't understand Redux. I studied the semantics of state machines for 20 years until I discovered TLA+
Alex Guerra
@heyimalex
Feb 19 2016 21:09
You could easily implement this in Redux if you wanted...
Jean-Jacques Dubray
@jdubray
Feb 19 2016 21:09
it would be trivial... actually,
SAM is just a factoring
but it will violate everything Dan is saying.
I would actually not implement it in "Redux" it is just called JavaScript
Jean-Jacques Dubray
@jdubray
Feb 19 2016 21:14

The constraints to implement it in Redux is that:
a) Actions cannot use values others than the ones that are passed to them (actions cannot see the entire model) -> in SAM data' = Action(data)
b) in the store: you'd have to write it slightly differently,

const dispatch = (action,data) => {
   state = present(action (data)) ;
}

Actions cannot see the "state"

The view must have enough state (or say a session manager if that data cannot be passed to the view for privacy / security reasons) to pass the correct information to the action
the mutation of the model happens in the present method, not in the reducer.
then you render the state (notify the listeners)
then you call the nap function
const dispatch = (action,data) => {
   state = present(action (data)) ; // assuming it is synchronous
   states.forEach(s => s(state, s.nap(state))) ;
}
Jean-Jacques Dubray
@jdubray
Feb 19 2016 21:20
Again, these semantics are very different from the Redux ones. You are free to believe everything is the same and nothing matters, but in the end you are just handwaving.
Jean-Jacques Dubray
@jdubray
Feb 19 2016 21:28

To sum up in "redux terms":
In Redux:

  • actions are defined as events (no computation)
  • all the state is mutated in the reducer, albeit in a so called functional way
  • no decoupling between the code that compute values vs the code that accepts these values
  • no next-action-predicate

In SAM:

  • events/intents are irrelevant (for the most part), they are just wiring to trigger the action
  • actions compute the values that we want the model to mutate with (without having access to the model), actions are self contained, the reactive loop must make sure enough state is passed by the event to the action
  • model accepts values (based on the entire state of the model)
  • once the model has mutated a new state is computed from which state representations can be calculated
  • next-action-predicate computes if any remaining actions

Both Redux and SAM can be implemented in JavaScript just fine.

The big difference between SAM and Redux is how you handle concurrency questions and how you re-enter the loop outside the view, use cases like that one are trivial in SAM http://stackoverflow.com/questions/35411423/how-to-dispatch-a-redux-action-with-a-timeout
Alex Guerra
@heyimalex
Feb 19 2016 21:34
I just don't understand the issue of coupling code that computes values vs accepts values. On concurrency, I'll say that my biggest gripe with Redux is it makes you cleave application logic into actionCreator and reducer.
Jean-Jacques Dubray
@jdubray
Feb 19 2016 21:35
I am sure one day you will.
It's the difference between writing spaghetti code and less spaghetti code

In the StackOverflow example, look at what Dan is saying:

store.dispatch({ type: 'SHOW_NOTIFICATION', text: 'You logged in.' })
setTimeout(() => {
  store.dispatch({ type: 'HIDE_NOTIFICATION' })
}, 5000)

The redux model breaks instantly, he has now the model call an action!!!!

If that is not spaghetti, then what is??
As I said, in the end, we all have to write that code one way or another, MVC, Redux, no pattern at all, SAM,... will end up with a solution to a given problem.
Alex Guerra
@heyimalex
Feb 19 2016 21:38
Yeah, I'm totally with you there. But what does that have to do with models accepting values? And how can you solve that issue with nap?
Jean-Jacques Dubray
@jdubray
Feb 19 2016 21:39
The only questions are:
  • how much will it cost?
  • what part of the solution are reusable for other solutions?
  • how maintainable is my code?
  • how many defects / 1000 of LOC my factoring produces vs another
Redux does not scale to real-world applications. Not much to add.
Alex Guerra
@heyimalex
Feb 19 2016 21:42
As someone who has actually built a large real world application with Redux... I disagree. But I want to steal anything you have to offer. Just to clarify, the purpose of model-accepting-action-result is what, domain consistency? Like a safeguard?
Jean-Jacques Dubray
@jdubray
Feb 19 2016 21:43
it is just a separation of concern, makes the actions highly reusable. Makes the model mutation code working with multiple actions.
in large real-world applications that code gets quickly out of hand.
that's why you want to factor it properly.
If you understand Redux, switching to SAM is trivial. It's just a matter of factoring the reducer and the store differently.
The reducer becomes a series of actions
The store inherits all the model mutation logic.
Now you have to be careful because something you could view as a model mutation is actually a "next-action"
You can use React on top to render the view, SAM fits nicely under that if you are familiar with React and used Redux to centralize the state, that's easy.
What you will notice is that a lot of the "concurrency" and "re-entry" problems go away with that factoring.
You are free to use any wiring you like, again SAM is just a pattern.
Alex Guerra
@heyimalex
Feb 19 2016 21:47
And what's the symbolic definition of nap again?
nap(???)
Jean-Jacques Dubray
@jdubray
Feb 19 2016 21:48
next-action-predicate: nap(model)
It's important because it happens after the model has fully mutated and you can compute the new state of the system
again no need to use a state machine, simple cases can be dealt with if-then-else
it is just a question of sequence:
  • actions
  • mutation
  • state representation
  • next-action
If you want to deal with concurrency for instance, you'll have to queue actions in the nap()
Maas-Maarten Zeeman
@mmzeeman
Feb 19 2016 21:50
So it is a synchronisation method.
Something which you need anyway with js because it has a broken concurrency model.
Jean-Jacques Dubray
@jdubray
Feb 19 2016 21:51
Well, yes an no, sometimes you have genuine automatic actions that need to be triggered once the model reaches a certain state
@mmzeeman yes, you cannot deal with synchronization questions lightly
and SAM is not just for JavaScript anyway.
All I am trying to say is SAM's factoring is not trivial, it is not even something I came up with (that's why it is working so well :-))
You should not try to tamper with that factoring. It's directly coming from TLA+ and that's why it is robust.
I would argue it is impossible for someone to cook-up such a general factoring, and in the end, there is possibly just one factoring like that.
No matter how smart you are, I'd be surprised if you can come up with an alternative in a few weeks of work, even decades if you ask me.
I have looked at that problem for 20 years and never landed on TLA+ semantics
Maas-Maarten Zeeman
@mmzeeman
Feb 19 2016 21:56
Well I do a quite some erlang coding. You might be surprised what you can do with a language which has a working concurrency model. Callbacks are a sign there is something wrong.
It breaks your nice sequential flow, and you need something to fix that.
Jean-Jacques Dubray
@jdubray
Feb 19 2016 21:59
I am not saying I can deal with all the most complex concurrency problems and in all fairness at the front-end level, you don't have too many...
If you constrain the problem enough you can find optimized solutions, but I you'd have to explain to me why companies like Amazon result to TLA+ to find the most challenging bugs in AWS?
All I am saying is that this "nice sequential flow" is what you have to go back to, when your solution breaks. I am not saying that this "nice sequential flow" is the optimal solution to every problem.
Maas-Maarten Zeeman
@mmzeeman
Feb 19 2016 22:01
TLA+ is for modelling distributed systems.
Jean-Jacques Dubray
@jdubray
Feb 19 2016 22:02
and...
Maas-Maarten Zeeman
@mmzeeman
Feb 19 2016 22:03
Well I mean having callbacks with timeouts and async calls make the flow of your code really complex and unpredictable. Having a pattern like SAM fixes that, which is very nice.
Jean-Jacques Dubray
@jdubray
Feb 19 2016 22:04
I would say "fixes", I'd say it helps write cleaner code and have a clear place when you can put well identified concerns.
after that, real-world solutions are complex no matter what.
Any help you can give to developers here is a big step forward even if it does not solves everything
Maas-Maarten Zeeman
@mmzeeman
Feb 19 2016 22:07
Exactly it creates a sync point from actions from the outside to your state. Indeed, the complexity doesn't go away, but you don't have to invent your own synchronisation mechanism anymore.
That is what the redux guys already have to do when a simple timeout appears.
Jean-Jacques Dubray
@jdubray
Feb 19 2016 22:07
yes, having at least one good sync point is enough for 80-90% of the problems otherwise you'll generate 10x the amount of bugs without it
Maas-Maarten Zeeman
@mmzeeman
Feb 19 2016 22:07
And those bugs are hard bugs.
Jean-Jacques Dubray
@jdubray
Feb 19 2016 22:08
very very hard, inextricable
this is why I am so critical of Redux
this is why I had set out to talk to Dan originally rather than writing a paper
Because Redux was close enough, and with enough traction that I would have preferred working with him to convince him to adopt TLA+ semantics
but, he chose not to respond, not just to me that apparently to anyone that asked him to comment on SAM
Maas-Maarten Zeeman
@mmzeeman
Feb 19 2016 22:10
There is a lot of work being done right now on these things. The discovery of SAM is not an accident.
Jean-Jacques Dubray
@jdubray
Feb 19 2016 22:10
Yes, totally agree,
without React (and struggling to build something with it) I would never thought about SAM
Maas-Maarten Zeeman
@mmzeeman
Feb 19 2016 22:11
React is nice indeed, very similar to how games render their views.
Jean-Jacques Dubray
@jdubray
Feb 19 2016 22:11
I have worked on SAM last year, but in a completely different context
(service orchestration)
Alex Guerra
@heyimalex
Feb 19 2016 22:11
It's been a common concern, and we actually discussed it at length when Redux was being written, but no one could come up with a suitable solution. People were moving forward with Redux, the issue was closed.
Jean-Jacques Dubray
@jdubray
Feb 19 2016 22:12
Yes, I understand, these are very complex questions, that's why I get a bit irritated and condescending when people tell me it is all the same
it is not, it is very very hard questions to deal with, and I would have just been happy to have a chat with Dan, point him to TLA+ and say, look at these semantics, I think they can make Redux better
Now he has to align Redux with SAM and I can claim (and predict) that's what he is going to do.
Alex Guerra
@heyimalex
Feb 19 2016 22:14
But yeah, Redux doesn't handle asynchrony. Very rarely are domains purely synchronous, and forcing all impure interaction into action creators cleaves your logic into two different places...
But there are a lot of things in
Meh, I'll read more I guess
Thanks for engaging, you still don't need to be a dick :v:
Jean-Jacques Dubray
@jdubray
Feb 19 2016 22:20
I am generally not, but I get "sensitive" when people come to me and say "it's all the same"
Note that Dan has started to adopt the language "nextNotification" and he talks also about "call APIs" from the reducer .... in his response to how to deal with async actions in Redux http://stackoverflow.com/questions/35411423/how-to-dispatch-a-redux-action-with-a-timeout
So.. I know he read the paper...
I'd be really surprised if he didn't