These are chat archives for jdubray/sam

22nd
Oct 2016
Charles Rector
@chuckrector
Oct 22 2016 04:50
v3 of my scene editor using SAM http://codepen.io/chuckrector/pen/xEaPBO/ now all sprites can be highlighted/selected by hovering over the scene or the line items, and up/down will reorder the selected sprite
animations is one area you can definitely see the effects of rewriting the whole DOM: they are reset with every state change that generates a new state representation, resulting in "jerkiness" due to resetting any currently active animations
some diffing ala virtual-dom would probably solve that. you can see the same effect on the text cursor restoration as well if you look closely
Charles Rector
@chuckrector
Oct 22 2016 04:57
properly restoring text cursor as the app grows more complex continues to throw small curveballs, which is annoying, but still nothing extreme
there is some obvious duplication around highlight vs. select but it is nice to simply produce the code and let it "breathe" a bit first
i remember a great talk by sebastian markbåge where he mentioned spaghetti code was bad, but "fettuccine" code was actually good -- it really changed my outlook on duplication
Charles Rector
@chuckrector
Oct 22 2016 05:06
Charles Rector
@chuckrector
Oct 22 2016 05:32
7/9 of my actions are quite anemic so far, but perhaps that is because they are simple to begin with. i will probably understand better whether that is good or bad once i have dozens of actions
most of them are taking only a single id of a sprite as input
the interesting logic seems to occur either in events (when deciding whether or not to fire action at all) and in the model (when determining if action points out a valid sprite)
Charles Rector
@chuckrector
Oct 22 2016 05:42
hmm, and that logic is a bit of duplication of efforts too currently
for example, i want to highlight sprites as i move the mouse. as i mousemove, the event handler scans the full list of sprites to see which one you are currently hovering over
to prevent firing excessive actions, i check if that sprite is already highlighted, and if so, early out
if it isn't highlighted, i trigger an action to select the sprite by passing its id
many actions are a simple id passing like this
but then in the model, i search for that id a second time, to make sure it is a valid id in the model's list of sprites
and if it is, then i actually set the found sprite to be highlighted
technically, i could just pass the sprite directly to the model so that the model could then immediately set its highlighted status to true. but that seems rather sketchy, since the sprite passed in could have absolutely nothing to do with the model, and i would be modifying state outside the model
so the searching thru the sprites seems important on both "sides" of the action
Jean-Jacques Dubray
@jdubray
Oct 22 2016 07:41
Let look in more details at your questions tomorrow, but at a minimum I can say that you can always use a mechanism like SAFE to decide whether an action can be triggered or not (or if it makes more sense the actions that are explicitly disallowed). In this case they will be action "instances" rather than action type. You can't select the sprite with that id because it's already selected.
Charles Rector
@chuckrector
Oct 22 2016 20:52
i was thinking about coalescing actions for the first time
i'm implementing dragging sprites with the mouse now, and thought what if i wanted to fire both dehighlightAll sprites and endDragging at the same time when mousing outside the viewport
but then realized in every action i am immediately presenting, rather than returning a bundle of action data
if i just call two actions one after another, the state representation will be calculated twice in a row. which maybe isn't a big deal
but if i wanted to coalesce those two actions so they both come along for the ride in a single state representation update, i assume i'd have to... not present() inside each action, and instead return the data. then do something like... present(Object.assign(actions.dehighlightAll(...), actions.endDragging(...)))
Charles Rector
@chuckrector
Oct 22 2016 21:45
v4 of my scene editor using SAM http://codepen.io/chuckrector/pen/RGEdgX/ now you can drag sprites around
interested to hear any feedback on my handling of events->actions->model. my actions are all still very anemic and most interesting things happen in events & model itself. also interested to hear thoughts on how to coalesce actions, since i am firing some back to back rather than as one
devin ivy
@devinivy
Oct 22 2016 22:19
@chuckrector that's a nice piece of work!
i'd watch out for things like delete model.isDraggingSprite. i think it's nice for the model to have at minimum a consistent shape. this helps with debugging and self-documentation.
devin ivy
@devinivy
Oct 22 2016 22:26
its name also alludes to use of the model in the view, with convenient checks like if (model.isDraggingSprite) (though it's not actually a boolean). i do suggest decoupling the view and the model by creating a representation of the model specifically for the view (often called "state"). shaping the model for convenience in the view can make for a hard-to-maintain model.
and perhaps it's a matter of taste, but i prefer explicit action types. for example,
// this
present({ endDraggingSprite: data });

// might become this
present({
    type: 'END_DRAGGING_SPRITE',
    payload: data
});
Charles Rector
@chuckrector
Oct 22 2016 22:31
@devinivy thank you!
i hadn't considered the consistent "shape" of the model -- that's a good point
the explicit action types is interesting -- wouldn't that mean that it is then impossible to coalesce actions?
i.e. you cannot merge two "type" because one would always win or overwrite the other
but again, i suppose firing actions back to back is not necessarily a big deal, unless you are having some delicate/expensive state representation calculations where you want to avoid too many
devin ivy
@devinivy
Oct 22 2016 22:34
interesting. fair point. you could still coalesce, but it would work differently. e.g. you could present an array of actions and your model would process all of them.
i've never played with coalesced actions so i don't have any deep thoughts on that! would be interested to hear your take on it.
Charles Rector
@chuckrector
Oct 22 2016 22:36
i will definitely share what i find in here once i have explored it more. i am using this little app to try and probe all the corners of SAM in order to understand it well
devin ivy
@devinivy
Oct 22 2016 22:40
i think the coalesced actions is a very fair thing to explore. in SAM proposing two actions coalesced into one is semantically different than two separate proposals. you start getting at the atomicity of actions and what @jdubray refers to as "critical sections."
Charles Rector
@chuckrector
Oct 22 2016 22:42
i will need to give some thought on the decoupling of model/view. so you're saying that perhaps the idea of "dragging" is a view-specific thing which the model should have no knowledge of? so the model would only deal in, for example, actions that update the x/y of sprites, rather than a group of actions which work together to describe dragging. i suppose dragging is a very transient thing to begin with, and its states should not live in the model
devin ivy
@devinivy
Oct 22 2016 22:43
no, i think that is fine!
i'm thinking of the use of the model within the view.
Charles Rector
@chuckrector
Oct 22 2016 22:46
ohhh such as in view.main
devin ivy
@devinivy
Oct 22 2016 22:46
for example, in the model i might keep a dictionary of sprites keyed by ID. but in the view you may want to work with an array of sprites.
so you keep an intermediate representation of the model that the view uses when building the display.
rather than storing both an array and a dictionary of the same sprites in the model.
in SAM this intermediate representation is actually part of the "state," which is separate from the "model"
for working with redux and an immutable model (which SAM doesn't advocate for), this has become an important takeaway from SAM for me.
Charles Rector
@chuckrector
Oct 22 2016 22:53
oh, hmm. that sounds similar to the normalization i see the redux folks recommend. in my case, i would still need to store an array of sprites one way or the other in the model -- even if just a list of keys -- since it is an important part of the scene -- currently the array dictates the "z-index" of the sprites in the scene. that would probably speed up finding the appropriate sprite though, esp. for very complex scenes. i'll try it!
hmm, i suppose i could be conflating model vs. persisting an app session tho (?)
devin ivy
@devinivy
Oct 22 2016 22:56

that sounds similar to the normalization i see the redux folks recommend.

it's related to that. but it also encompasses the denormalization that occurs in redux when you use, for example, selectors.

Charles Rector
@chuckrector
Oct 22 2016 22:56
like if this were a standalone app which saved the current editing session to disk, i would want to rehydrate with that order intact. but i suppose when saving to disk, i don't necessarily have to just output the model in JSON or whatnot. saving could be more complex. i suppose i've just always been writing out that single object because it is convenient
devin ivy
@devinivy
Oct 22 2016 22:57
check it out. in the counter example there's a function that takes the model (store) and outputs a representation of that model that's nice for the views to use. https://github.com/sam-js/sam/blob/master/examples/counter/src/state.js
notice that the view doesn't use the model, but instead a representation of the model. https://github.com/sam-js/sam/blob/master/examples/counter/src/containers/App.js
Jean-Jacques Dubray
@metapgmr_twitter
Oct 22 2016 22:59
I am back online, catching up. Just a work on coalescing actions, semantically, action always leads to a new state, you can only apply a new action once you reached the new state
you can functionally compose actions but I don't think that's what you are after.
devin ivy
@devinivy
Oct 22 2016 23:01
@metapgmr_twitter i think what charles is getting at is a hack to generate a critical section by coalescing actions that don't always stand on their own.
Jean-Jacques Dubray
@metapgmr_twitter
Oct 22 2016 23:02
A(x) = present(createProposal(validate(x)) );
yes, I understand, it's more an optimization due to the volume of events
devin ivy
@devinivy
Oct 22 2016 23:03
sometimes propose(a) is okay and sometimes propose(b) is okay, but also sometimes propose(a) then propose(b) is not okay.
Charles Rector
@chuckrector
Oct 22 2016 23:03
@metapgmr_twitter ah, interesting. i may have simply misunderstood the documentation when i read it. i think maybe i misinterpreted "composing actions" as "bundling up multiple actions together for a single state representation call". and then assumed that's how i would use them. but it sounds like composing actions may have simply meant to construct a single action with some "embellishments" or whatnot
devin ivy
@devinivy
Oct 22 2016 23:03
so instead charles does a propose(a + b)
Jean-Jacques Dubray
@metapgmr_twitter
Oct 22 2016 23:04
Nothing prevents you from aggregating the events in a dispatcher and then triggering a single actions that will create a proposal from a series of events.
Charles Rector
@chuckrector
Oct 22 2016 23:04
okay, i think i see now. it is only an implementation detail
devin ivy
@devinivy
Oct 22 2016 23:04
having a standard way to think about that is crucial. i assume SAFE has taken a crack at it.
Jean-Jacques Dubray
@metapgmr_twitter
Oct 22 2016 23:05
Semantically, it is not correct to apply a second action before you computed the application state resulting from the first action.
Charles Rector
@chuckrector
Oct 22 2016 23:05
aha!
that is good to know. so back to back firings is fine as i have them
in my case, it is not even nap() per se, just some things i want to fire together when a certain event comes along
Jean-Jacques Dubray
@metapgmr_twitter
Oct 22 2016 23:07
SAFE is implemented two mechanisms:
  • the state function computes the allowed actions (given the latest application state)
  • for long running actions, SAFE allows a "hang back" mechanism, meaning that you can trigger two or more long running actions and only one of them will be able to present its results, it's kind of a generic cancellation mechanism
devin ivy
@devinivy
Oct 22 2016 23:07
yes, @chuckrector i like it!
Jean-Jacques Dubray
@metapgmr_twitter
Oct 22 2016 23:08
If you maintain a queue of actions somewhere, nap() would be a good place to execute the queued actions, as long as there is an action waiting.
Charles Rector
@chuckrector
Oct 22 2016 23:08
@devinivy re: decoupling model & view, so instead of directly passing model to state representation ala state.representation(model)inside my state.render, you're saying it would be better to compute that intermediate state in render and pass that along ala state.representation(viewModel)
Jean-Jacques Dubray
@metapgmr_twitter
Oct 22 2016 23:10
SAM suggests passing the model to the state function, it is the state function that will translate the model into a state representation (i.e. a set of properties that can be directly consumed by the view components, aka view-model)
Charles Rector
@chuckrector
Oct 22 2016 23:10
@jdubray oh! i had not considered that either. nap() can be as a sort of... global event pump
Jean-Jacques Dubray
@metapgmr_twitter
Oct 22 2016 23:10
yes, it's a good place for that. That's why I call SAFE the State-Action Fabric because there is a need for this kind of global behavior.
devin ivy
@devinivy
Oct 22 2016 23:11
@chuckrector exactly... you know its working if your views feel like they're implemented in a way such that they are generic and don't depend obviously upon your application's model.
Jean-Jacques Dubray
@metapgmr_twitter
Oct 22 2016 23:11
It's not breaking the pattern, just an implementation that deals will complex flows of events
devin ivy
@devinivy
Oct 22 2016 23:11
because your model will and should change over time, and you don't want to update every view as that happens :)
Jean-Jacques Dubray
@metapgmr_twitter
Oct 22 2016 23:11
yes, that's the key, the view components should be focused on the view regardless of the shape of the model
:thumbsup:
Charles Rector
@chuckrector
Oct 22 2016 23:12
very cool. after i have cut my teeth on the little scene editor app for a while longer, i think i will be confident enough to start using SAM in a real app i have been making
and it will replace all my redux/immutable.js shenanigans
Jean-Jacques Dubray
@metapgmr_twitter
Oct 22 2016 23:13
Do you see immutability and the rigid relationship between the store and the view as something difficult to deal with?
devin ivy
@devinivy
Oct 22 2016 23:13
immutability is a pain to deal with, but it really does have value specifically in react if you're not using observers.
and that's only because react needs to know whether to render or not.
beyond that i don't see its immediate value. what i'm interested in is a model that can tell you about the mutations that have been done to it, as in cerebral.
Jean-Jacques Dubray
@metapgmr_twitter
Oct 22 2016 23:14
yes, that's my view too, this is very specific to React's architecture, rather an optimal implementation
devin ivy
@devinivy
Oct 22 2016 23:15
such a model will work in many contexts :) but cerebral's still needs work.
as far as talking "optimality", imagine such a model working with incremental-dom.
that could be so fast...
Charles Rector
@chuckrector
Oct 22 2016 23:17
for me, managing immutability is just annoying because it is strictly more work than direct mutation. but that's probably more about javascript not providing builtin language affordances for such a thing
devin ivy
@devinivy
Oct 22 2016 23:17
i'm not immediately concerned with "fast" though, mostly interoperable models.
Charles Rector
@chuckrector
Oct 22 2016 23:17
i've said before, but i am not a fan of the immutable.js setters/getters once my app got more complex
devin ivy
@devinivy
Oct 22 2016 23:17
agreed ^^
one idea is for "state" to be immutable (for react) but the model to be mutable. this would also be achievable with the model that reports its mutations.
i gotta run– have a nice one!
Charles Rector
@chuckrector
Oct 22 2016 23:19
cheers
devin ivy
@devinivy
Oct 22 2016 23:19
:beers: @chuckrector
Edward Mulraney
@edmulraney
Oct 22 2016 23:19
@devinivy nice idea re state immuatable, model mutable
Jean-Jacques Dubray
@metapgmr_twitter
Oct 22 2016 23:21
In Angular2 you have more flexibility, you can use pub/sub to publish the state representation and the change detection mechanisms will make sure that only the new property values will be rendered
devin ivy
@devinivy
Oct 22 2016 23:21
@edmulraney thank you! @metapgmr_twitter sounds like you're talking about observers?
Jean-Jacques Dubray
@metapgmr_twitter
Oct 22 2016 23:22
no subjects (pure pub/sub)
devin ivy
@devinivy
Oct 22 2016 23:22
ah!