These are chat archives for jdubray/sam

7th
Jul 2016
Vincent Jo
@chiwoojo
Jul 07 2016 15:25
@mnichols hi Mike, what type of company do you work for? It seems pretty progressive
@jdubray about the animation; are you talking about something like stateRepresentation = { component: ...html string..., animation: function } and the display function would take care of hooking up the animation function to the html string?
Vincent Jo
@chiwoojo
Jul 07 2016 15:31
That would be cool to experiment with..
Jean-Jacques Dubray
@jdubray
Jul 07 2016 15:36
yes, that works already in the rectangle example. It's not an animation per se, but a time based animation (non CSS based) would work the same way.
https://github.com/jdubray/sam-samples/blob/master/js-rectangle/rectangle.html
I guess the big lesson I learned with SAM is that you have to be very careful about your semantics such as what is an "Action" or "State Representation" and in particular the "IS-A" part of the semantics. What IS-An Action? What IS-A state representation? otherwise you start making all kinds of decisions that a broad impact on the code you write. It is not neutral at all, you could end-up having to write lots of boilerplate code for no reason at all.
Mike Nichols
@mnichols
Jul 07 2016 15:41
@chiwoojo LOL...I would definitely not call my company progressive but I am tasked with trying to find patterns that non-front-endy types can grok and help the decision tree of 'where stuff goes' when building front end apps. I have been evaluating a variety of these 'new' patterns and also doing a gut check on my own past approaches to see if others like SAM can help avoid some of the complexity that emerges with long-running SPAs
Jean-Jacques Dubray
@jdubray
Jul 07 2016 15:42
do you have some feedback on SAM thus far?
I accept critics, so I am really looking for your no nonsense opinion.
@chiwoojo for instance Elm does not have the concept of "State Representation" or "Actions" they have signals and the model directly renders in the View.
https://www.youtube.com/watch?v=Agu6jipKfYw
Mike Nichols
@mnichols
Jul 07 2016 15:45
@jdubray I was just writing out some definitions in my code base to help with that 'being careful' part. For example, it is fuzzy to me whether I put a fetch of a dependency inside an Action or whether the Model would accept a kind of affordance (eg initialize: true) to decide if it should fetch that dependency. I know an action is 'within the context of a request (not based on Model state)' so it seems like I could argue that the Model should decide whether to fetch or not based on its own internal state (eg isInitialized: true).
Jean-Jacques Dubray
@jdubray
Jul 07 2016 15:49
@mnichols both are possible, I would say it's better to put it in an action since if would support varying initializations strategies. I know that a lot of people don't like to reuse code (and there is a strong rationale for it). But you may also consider "reuse" as a design factor, I can really see a lot of elements in SAM being reusable (Actions, Model or State) across families of apps (functionally or channel dependent).
Mike Nichols
@mnichols
Jul 07 2016 15:51
I'll post more responses here in a bit...one thing I can see coming up is I think the distinction between control state (learner) and application state (model) needs to be more explicitly articulated for new arrivals. For example, it is confusing why a next action predicate is inside the Learner since the Model could answer that question; eg model.state.render(model).then(()=> { model.nap() } . This is confusing if you conflate Model state with control state in your mind.
Jean-Jacques Dubray
@jdubray
Jul 07 2016 15:51
Here is why, the same model could work with several State functions (just like a car could have several working mode: Teenagers, Valet Parking, ...). I drive a 20 year old car and I park my car, so this is a bit hypothetical, but I can see the benefits of this decoupling
Mike Nichols
@mnichols
Jul 07 2016 15:54
So the same car (model) is being used in a variety of contexts (learner).
Jean-Jacques Dubray
@jdubray
Jul 07 2016 15:54
Each learner could decide on a next-action. There are also implications on "eventual consistency" for the model. Just like you have to distinguish between proposal and acceptance, you have to distinguish between acceptance and access (to the new state). nap() can only be computed when the model says it's done and new application state is availble
Yes exactly what we think as application state is truly Model + State
property values + control state
SAM is all about untangling code
if you are not careful all this code will land in the wrong bucket. SAM Is very simple, offers "natural" constraints, very easy to follow
But when you follow them, really good things start happening (IMHO, but I am biased, so I am happy when people keep me honest)
As I mentioned earlier, Elm does not decouple the view from the model, it does not have a state function
It works, I can build apps that way, but which way would you prefer building them?
if it does not melt your wallet
Elm does not also easily decouple the Signals from the Model (Update). Then you have to think, how do I handle API calls.
Mike Nichols
@mnichols
Jul 07 2016 15:59
I've been avoiding the term 'State' because of criticism I got when my boss read this : "Unintuitively, the State does not hold any “state”,
Now, I know what the purpose of the State is because I heard the term 'learner' and I like the approach, but new arrivals can be impatient with these kinds of terms.
Jean-Jacques Dubray
@jdubray
Jul 07 2016 16:01
You can use "state representation" instead of state. Would that look clearer?
Mike Nichols
@mnichols
Jul 07 2016 16:02
I am actually using PAL terms (Proposal, Accepter, Learner) in my code to avoid the mental map people are trying to make with Redux, etc
Jean-Jacques Dubray
@jdubray
Jul 07 2016 16:02
ok, that's a good feedback
I thought Learner would be even harder to grasp than "State"
but being non native english speaker, it's hard to estimate.
Mike Nichols
@mnichols
Jul 07 2016 16:06
Good point. When I hear "state" i think of something that carries its own set of attributes...it doesn't carry the intention of a computation which, in SAM, it is. "Learner" to me right away indicates it accepts some input and does something in response. "Proposal" carries along the implication of scrutiny (acceptance or rejection) whereas "Action" means DO THIS THING NO QUESTIONS ASKED to me.
Jean-Jacques Dubray
@jdubray
Jul 07 2016 16:07
that's really good feedback, thank you
I have no problem aligning SAM with Paxos,
a) because it's natural
b) that's where SAM/PAL will go, as it provides the ability to build "distributed" applications in a very robust way
my expectation is that this is the next stage of UX, distributed UX where everything around you is "connected", you no longer tethered to a display, just like we were tethered to a network connection
SAM/PAL will be one of the best ways to achieve that, if not the only way (again, based on Paxos, I don't claim I invented anything)
Mike Nichols
@mnichols
Jul 07 2016 16:19
@jdubray is it proper to make a dispatch an action from a model? Inside a child model, I am integrating with a 3rd party lib that emits events. On one of those events I'd like to dispatch an action to the top-level model present call instead of taking a dependency on the parents present method directly. Thots?
Since "actions can come from anywhere" it seems like a more decoupled way to design this
Jean-Jacques Dubray
@jdubray
Jul 07 2016 16:35
So, semantics is that a new action can only be allowed when the application state is known.
so at a minimum you want the dispatch to occur once the unit-of-work is completed
the only reason why nap() is in the "state" is to make "State" interchangeable working of the same property values. I feel that boundary is healthy in the long term, but as long as you do not dispatch in the middle of a unit of work you are ok
that would be very problematic
Actions can indeed come from anywhere
Vincent Jo
@chiwoojo
Jul 07 2016 16:40
hey JJ, is it fair to say that the end of "unit of work" is the end of model.present function?
Jean-Jacques Dubray
@jdubray
Jul 07 2016 16:40
A lot of the current direction (Redux, Elm, Cycle... FRP) is to make sure we have a stable application state. That's really what needs to occur. React/Angular alone cannot achieve that because they fragment the model into components. That does not work
@chiwoojo yes, this is generally where it ends, but the true end, is whenever you are in the absolute position to decide what is the next-action or process a new (queue or incoming) action
As soon as you reached that state you in essence completed the unit-of-work
Vincent Jo
@chiwoojo
Jul 07 2016 16:42
umm I see
Jean-Jacques Dubray
@jdubray
Jul 07 2016 16:43
In general you cannot expect view component boundaries to match the boundaries of the units-of-work
Vincent Jo
@chiwoojo
Jul 07 2016 16:43
because the only thing in SAM right now that comes after the model.present function is the representation function (which has no power to modify the state of the application) that comes before the next action right?
Jean-Jacques Dubray
@jdubray
Jul 07 2016 16:43
that's why React/ng components are an anti-pattern, it is simply the wrong granularity to decompose your system
Vincent Jo
@chiwoojo
Jul 07 2016 16:43
yea, I see
Jean-Jacques Dubray
@jdubray
Jul 07 2016 16:44
yes, the state representation does not have any side effects on the model
it can only dispatch the next-action
which itself can only create a proposal
Vincent Jo
@chiwoojo
Jul 07 2016 16:45
yea, that makes sense..ok thanks. I think I got a better sense of what unit of work is now
Jean-Jacques Dubray
@jdubray
Jul 07 2016 16:46
In the past (MVC) there's been a real tension between view and units-of-work. Now we are down to "components" but still the way the view and the model work together is misaligned and there is simply nothing you can do about it
so you need "adapters" on both directions, hence V->A->M and M->S->V
Vincent Jo
@chiwoojo
Jul 07 2016 16:48
adapters being the actions and the state right?
Jean-Jacques Dubray
@jdubray
Jul 07 2016 17:17
no they are the adapters, they play the role of an adapter
when you think of it, how could someone arbitrarily mutate the application state outside a unit of work? You can't sprinkle that application state mutation across all your code.
Mike Nichols
@mnichols
Jul 07 2016 18:15
Say I am trying to reuse a 'slideshow' across a variety of pages/applications. The 'slideshow component' is a package of the view and theme and a model.
Each app has its own Model that accepts proposals and may delegate to the slideshow model based on the action data.
My question is...who 'owns' the action signatures? The component or the application the component is fitting into? The views for the slideshow component are bound to the intents so it seems like the component owns the actions and the application composing it should merge those actions into its own collection. Is that the right direction for thinking about packaging reusable bits that fit into a SAM app?
Jean-Jacques Dubray
@jdubray
Jul 07 2016 18:22
yes, this is correct, the action's signature (as adapters between component and model) need to be able to be called from the component. That being said the "implementation" of the action can still be generic. It's a bit like a russian doll, but what you have is:
view component -> action(x,y,z)
where:
action(x,y,z) {
    {u,v,w} = transformVC({x,y,z}) ;
    let proposal = the_action_impl({u,v,w}) ;
    present(transformM(proposal)) ;
}
In general the action implementation is highly reusable, and/or, highly variable, you could have ten different actions that result in the same proposal structure.
Mike Nichols
@mnichols
Jul 07 2016 18:29
Hmmm...I wonder if the intent idea could be reused here to accept the slideshow component event data but the application is responsible for mapping the intents to its own action implementation. So 'actions' are owned by the application, but the 'intents' are owned by components being composed. The intents are adapted to the application actions by the application.
Jean-Jacques Dubray
@jdubray
Jul 07 2016 18:34
At a minimum, you want the action implementation to be 100% decoupled from the view component and the model. Any approach to achieve this outcome would work IMHO. After that, I don't think you can reduce complexity that much. Message passing is a well known space and all the patterns have been identified. The answer is really it depends. I like simple.
Mike Nichols
@mnichols
Jul 07 2016 18:36
yeh this started to smell like a wiring concern. i just wanted to clarify who 'owns' actions for an application with an eye for composing many bits that carry their own contracts.
Jean-Jacques Dubray
@jdubray
Jul 07 2016 18:39
it's a hard question, because it's truly an adapter role. I would say it depends, but in general I see action implementations are highly reusable. Validation and Enrichment (which are their core concerns) should be often identical across applications (think changeOfAddress action/proposal).
Mike Nichols
@mnichols
Jul 07 2016 18:43
yes i think i see the adapter role clearly wrt to composition. the 'changeOfAddress' action in the docs helped me see that an action is working within the context of a request, not within the context of application state.
Jean-Jacques Dubray
@jdubray
Jul 07 2016 18:47
yes absolutely, and IMHO, it's also easy to see why the model should not know anything about a getPostalAddress({address}) API, the model should only care that your proposal is the best possible.
Mike Nichols
@mnichols
Jul 07 2016 18:47
For me, it seems pretty simple to subscribe to an intents channel on the bus in my application and adapt to actions/proposals. The contracts (intents) the views presume can just be documented for various applications to implement.
Jean-Jacques Dubray
@jdubray
Jul 07 2016 18:48
yes, as I have mentioned all message passing patterns (including pub/sub) are well documented.
Edward Mulraney
@edmulraney
Jul 07 2016 19:06
@mnichols "Hmmm...I wonder if the intent idea could be reused here to accept the slideshow component event data but the application is responsible for mapping the intents to its own action implementation. So 'actions' are owned by the application, but the 'intents' are owned by components being composed. The intents are adapted to the application actions by the application." I build components in this way - grouped with their intents, units-of-work and control-state
Mike Nichols
@mnichols
Jul 07 2016 19:11
@edmulraney that is great to hear I am not losing my mind (yet)
Jean-Jacques Dubray
@jdubray
Jul 07 2016 19:11
if the view component is what you see as been highly reusable, then you'll adapt the intent (of the component) to the action
if you see the action as being highly reusable you'll design that view component to match the action interface
I am not sure there is one that is better than the other.
It truly depends
Jean-Jacques Dubray
@jdubray
Jul 07 2016 19:43
I continued doing some reading on FRP. I landed on this paper from Czaplicki (Elm). I found interesting the focus on event -> a bunch of stuff happens -> view, I cannot see much discussion on the factoring of what happens between an event and the view.
Maybe someone has more knowledge to share, but it looks like FRP is not generally concerned with it. From what he explains the roots of FRP were in animation (FRAN), not so much "data".
Fred Daoud
@foxdonut
Jul 07 2016 23:01
@mnichols I've been hacking on Riot and got some things working, but I'm having trouble understanding how you can get a V = f(M) function out of a Riot tag.
Mike Nichols
@mnichols
Jul 07 2016 23:38
I keep mean to look at riot/compiler's riot.compile(tag, true) to get a JS object back (V).
In ordinary usage though you really dont unless you think of riot being one-way so when you updateit uses its diff to create the new representation even though you hold onto a kind of proxy (the tag instance). That's the way I have been thinking of it anyhow. If you want to be truly pure you can riot.mount only instead of update but I dont see what is gained by the diff