These are chat archives for jdubray/sam

24th
Oct 2016
Fred Daoud
@foxdonut
Oct 24 2016 01:55
@chuckrector : that is a very cool example! Thanks for sharing :thumbsup: If you're interested, here is the Meiosis+React version based on the v5 codepen that you posted.
The two main differences are 1) How Meiosis wires the SAM pattern for you; and 2) how using a VDOM library (React in this case, but similarly Snabbdom, Inferno, etc.) combined with Meiosis actions make it easier to wire up events to actions.
Fred Daoud
@foxdonut
Oct 24 2016 02:01
Performance with VDOM might be better, but honestly I did not see any performance problems with your example.
Just for fun, you can play with the Meiosis Tracer on the right-hand side of the screen too. :)
Charles Rector
@chuckrector
Oct 24 2016 02:09
@foxdonut whoa, cool!
i will take a close look at this
yeah, the main benefit of VDOM for this scene editor, imo, is two things:
  1. animations are uninterrupted when state changes
  2. you can actually inspect DOM in browser (before, would always reset & collapse what you were inspecting)
hmm, looks like hovering to highlight is broken in your example
in the viewport rather -- it works in the rhs list
holy crap, that timeline is awesome :^o
Charles Rector
@chuckrector
Oct 24 2016 02:19
it is interesting how you always propose dragSprite in mousemove, but then reject in the model if dragging flag is not activated
is that more "in the spirit" of SAM? the only downside i can think of is if constructing a given action is costly, then you might want to avoid constructing & proposing it at all. though if it is costly to create your actions, you maybe have bigger problems to deal with :^)
Charles Rector
@chuckrector
Oct 24 2016 02:25
oh, i just realized the event handlers now live inside view.sprite, nice! so i can fix the highlight by also firing actions.highlightSprite({id: s.id}) alongside the dragSprite
looks like React intelligently handles px versus raw numbers just fine too, so toPx can die
Jean-Jacques Dubray
@metapgmr_twitter
Oct 24 2016 02:39
100 stars it is: https://github.com/jdubray/sam-samples, thank you to everyone who contributed.
Charles Rector
@chuckrector
Oct 24 2016 02:40
👏💯✨
Fred Daoud
@foxdonut
Oct 24 2016 03:29
@chuckrector you are correct on all points :) also notice that you no longer need the code to handle the cursor position.
Zach Dahl
@schtauffen
Oct 24 2016 05:33
I'm slightly confused: can anyone provide clarity? @metapgmr_twitter commented on the "Why I no longer use MVC" article: I suggest people who use Redux switch to SAM, they'll avoid this unnecessary coupling between the actions and the model in the reducer. Yet, examples using the action "intent" mechanism are basically doing the same thing Redux does. (for example, http://codepen.io/msolovyov/pen/qbvYpv?editors=1010 flips multiple flags depending on things like data.cancelEdit and the meiosis example above is basically redux-lite with { intent, payload } actions). Are these not idiomatic SAM implementations or am I missing what the drawback of redux is proposed to be?
Charles Rector
@chuckrector
Oct 24 2016 06:49
I am still learning SAM myself, but one observation is that by directly returning a new model, or a piece of it, Redux reducers are rigid in the sense that an action is locked into performing a "dumb" data update. When you need to do more interesting things, such as async behavior and other "side effects", you may spend a while struggling to reconcile how to fit that sort of behavior into the Redux "mental model". But Redux is extremely low-level and does not provide affordances for that. Instead, you must enhance redux (or workaround it, depending on your point of view) to allow such a thing, such as with redux-thunk.
Edward Mulraney
@edmulraney
Oct 24 2016 09:03
@jdubray " there is no decoupling between the view and the model." there definitely is seperation in at least one of those architectures; redux. tbh, this is a standard practice no matter what framework or architecture you're using. "view model" etc.
Fred Daoud
@foxdonut
Oct 24 2016 12:31
@schtauffen the Meiosis example above was to show how @chuckrector 's example would look like using Meiosis to implement the SAM pattern. It is not redux-lite. The fact that it uses { intent, payload } actions is not a restriction - I just wanted to as much as possible keep Charles' code the same. Redux requires a type in actions. Meiosis does not. So, for example, you can use things like union-type with nice results. If you're using TypeScript, you can use "stronger" types for actions as well. Other key differences between Meiosis/SAM and Redux include not requiring immutable models; not requiring middleware to deal with async; having nextAction or nap() to automatically trigger actions; not having reducers being restricted to a "scope" (although it can be done when it's convenient); having a cleaner separation of model and actions - in redux they are bundled together into props; and finally, easier/cleaner wiring - no need for mapStateToProps, connect, Provider...
devin ivy
@devinivy
Oct 24 2016 12:45
also, the idea of "decoupling model and view" is meant more strongly in SAM, i think, than in redux. it really means here that even the shape of the model is not used within the view. many folks who use redux do already separate the model and view in this way (e.g. with selectors and meaningful usage of mapStatetoProps), but it's not a tenet of redux usage.
of course you can implement SAM with redux– it has been done to various degrees.
@edmulraney a great example of where this is not the case is angular v1's ng-model, which is directly exposing the model inside the view.
Jean-Jacques Dubray
@metapgmr_twitter
Oct 24 2016 13:02
@schtauffen sometimes actions are "anemic" (they do not add anything compared to the event), what Redux call an "action" is actually an event. You cannot "make up" the definition of an action like Redux has done. Per TLA+, an action is a function that creates a proposal to update the property values of the model (in general they are not anemic). That code that computes the proposal ends up cobbled together with the model mutation code in the reducer. That's what I mean by "coupling action and model".
Of course SAM being a pattern, you can "factor" your code in a SAM aligned way even when you use Redux. @edmulraney pointed out several times that there are additional libraries (action-creators, redux-selector, redux-sagas...). The problem is that with too many choices you lose sight as to why and when you need to do something. I suggest learning the SAM pattern which I believe provides the correct structure and they use redux addons accordingly.
The mere fact that Dan calls something "action-creator" tells you that a redux action is not an "action" it is an event. One cannot "create an action". Makes no sense at all. If you just replace the word action in redux by event and you separate the code that creates the proposal from the code that mutates the application state (mode) then you are SAM aligned.
Edward Mulraney
@edmulraney
Oct 24 2016 13:08
@devinivy you can make your ng-model bind to a view-model rather than the data model
Jean-Jacques Dubray
@metapgmr_twitter
Oct 24 2016 13:08
Something that would be totally non SAM compliant is two-way data binding in Angular. One cannot "update the model" from the "View" that is absolute nonsense.
@edmulraney @devinivy absolutely, binding directly the view to the application state is an anti-pattern.
devin ivy
@devinivy
Oct 24 2016 13:31
@edmulraney true, but it is not prescribed in any way. just as in redux it isn't prescribed.
Jean-Jacques Dubray
@metapgmr_twitter
Oct 24 2016 13:32
I know (sigh)
Fred Daoud
@foxdonut
Oct 24 2016 13:34
@chuckrector about always presenting the proposal and refusing it (for mouse events in your example), you are right about the tradeoffs. The good news is that you can do it either way, depending on which makes more sense.
Edward Mulraney
@edmulraney
Oct 24 2016 13:34
@metapgmr_twitter re: libraries - i agree with you, we have analysis paralysis in Redux. it's hard to know what parts of the eco system you should use. however, selectors in redux don't require any extra libraries
devin ivy
@devinivy
Oct 24 2016 13:35
i think selectors are great. you don't count reselect as an extra library?
the problem that reselect selectors solve is particular to react and its use of immutability, though.
Edward Mulraney
@edmulraney
Oct 24 2016 13:36
@devinivy mapStateToProps
devin ivy
@devinivy
Oct 24 2016 13:37
sure, but without an extra library you can't pass objects or arrays in good faith
(this isn't redux's fault, aside from their championing of immutability)
Edward Mulraney
@edmulraney
Oct 24 2016 13:39
you cant pass object or arrays in good faith?
devin ivy
@devinivy
Oct 24 2016 14:07
right, because if you generate new objects or arrays then they will fail pointer-comparison (the touted benefit of immutability), and your react component will always re-render.
reselect is usually introduced into projects to avoid that issue.
all in all, i think reselect is a good solution to the problem.
Edward Mulraney
@edmulraney
Oct 24 2016 14:25
i see what you mean :) for generating new objects/arrays
i thought you meant const selector = state => ({newProp: state.arrayType}) was an issue ;)
@devinivy thinking about your idea with mutable model - immutable state - have you experimented with this? i havent paid it much thought but i like the idea
i suppose we still need to safeguard against mutating the model inside state representation
devin ivy
@devinivy
Oct 24 2016 14:41
@edmulraney i've not experimented with it! i think cerebral is on the right track with this, though https://github.com/cerebral/state-tree
they're running into this issue in polymer-redux as well
tur-nr/polymer-redux#13
Zach Dahl
@schtauffen
Oct 24 2016 15:00
Thanks guys, good food for thought.
devin ivy
@devinivy
Oct 24 2016 15:04
:beers:
Jean-Jacques Dubray
@metapgmr_twitter
Oct 24 2016 18:08
:thumbsup:
Jean-Jacques Dubray
@metapgmr_twitter
Oct 24 2016 18:13
In the end, Facebook's UX is pretty crappy. I don't think they have converted their entire app to react, but clearly the benefits of "react.js" don't seem to have materialized there. Not sure what's holding them since it has been a couple of years. Is it legacy? is it React itself? something else?
Zach Dahl
@schtauffen
Oct 24 2016 19:04
would you consider this example to use the SAM pattern appropriately? https://jsbin.com/saqamu/11/edit?js,console,output
Jean-Jacques Dubray
@metapgmr_twitter
Oct 24 2016 19:08
In theory, no one can access the model so something like model.counter() is not allowed.
Anything action that tries to add should create a proposal like { add: 1}
I am not sure what happens when this happens: return model.present({ counter: n }) }
I assume mithril redraws the view? It looks like the view expects actions to return something: increment: actions.add.bind(null, 1, model),
Jean-Jacques Dubray
@metapgmr_twitter
Oct 24 2016 19:14
that's not ideal to implement a reactive loop (there is no response in a reactive loop, you just call forward:
action -> model.present(...)
model -> state.render(...)
view -> view.display( ...)
When you have no other choice, that's ok, request / response will also work, but will generally be less flexible.
otherwise it's pretty close.
Fred Daoud
@foxdonut
Oct 24 2016 19:27
@schtauffen FWIW Meiosis has a Mithril renderer, here is the Todo MVC example.
Zach Dahl
@schtauffen
Oct 24 2016 21:18

I still have a few points I need clarification on:
"no one can access the model" this statement excludes the state/vm function which is required to know the structure of the model , correct? (otherwise we cannot map what we need to) But the view function, actions etc should not rely on the structure?
I'm slightly confused by what you mean by reactive: isn't explicitly linking action -> model.present() proactive? It was my understanding the idea behind reactive programming is that sources do not care about consumers (and do not reach out to try and touch them) and instead consumers subscribe to streams and react to them (at least according to staltz: https://cycle.js.org/streams.html);

@foxdonut - is meiosis rewrite compatible? I will have to check it out

Jean-Jacques Dubray
@metapgmr_twitter
Oct 24 2016 21:22
so the state function accesses the model in an indirect way, it is the model which invokes: state.render(model), what I been by that, it is not the state which arbitrarily to access the model.
The view (via its properties) will have some elements of the model and the elements should be "planted" in the view so that they can be part of the event (if possible). In any case, accessing the model property values in the actions or the view (say like in Redux, getState()) is an anti-pattern.
Reactive as opposed to "Interactive". Request/Response is interactive, Reactive, as I understand it, means "no response".
There are several definitions of reactive programming, but at the highest level, it simply means "reacting" to events. Streams are an optimization, or a specific domain of, reactive programming.
For me reactive loop means "no response" event->actions->model->state->view and so on.
Fred Daoud
@foxdonut
Oct 24 2016 21:25
@schtauffen pardon me, what do you mean by rewrite compatible?
Zach Dahl
@schtauffen
Oct 24 2016 22:03

@foxdonut I meant to ask whether the meiosis-mithril renderer was https://github.com/lhorie/mithril.js/tree/rewrite compatible. I apologize for the ambiguity
@metapgmr_twitter I really appreciate your responses! I think I am getting a better grasp of SAM and hope to explore it further with some projects :)

Cleanup:
I realize I didn't answer a question regarding the returns: I was returning a stream so my examples at the bottom could explicitly call m.redraw once model.present resolved. Thinking about it now it probably doesn't make sense since (I assume) model present should always resolve synchronously anyway, and we can call state.render(...) at the end of the present function as you suggest. The increment / decrement functions don't actually listen to or respond to the stream returned by the actions.

Jean-Jacques Dubray
@metapgmr_twitter
Oct 24 2016 22:11
Happy to help and glad you like it!