These are chat archives for jdubray/sam

26th
May 2016
Jean-Jacques Dubray
@jdubray
May 26 2016 00:09
(for me)
Jean-Jacques Dubray
@jdubray
May 26 2016 00:25

@509dave16 so I think I see how the code works now. Because you are using Redux, your present method does not do much, what would otherwise happen in present actually happens in the reducer (which makes sense).

So when you implement an action:

const localMarkGridAction = (model, present) => {
    const { move, turn, grid } = model;
    const updatedGrid = markGrid(grid, move, turn);
    present(intents.markGrid(updatedGrid));
  };
you actually prepared the mutation in intents.markGrid(updatedGrid)
and the present implement simply ratifies what the reducer is telling it to mutate to.
(again this makes perfect sense)
This means that you can invoke side effects in your actions, prior to the reducer being invoked (which again makes perfect sense and is exactly how SAM would do it):
const joinSessionAction = (model, present) => {
    const session = model.submittedSession;
    firebase.child('sessions').child(session).once('value', (snapshot) => {
      if (snapshot.exists()) {
        firebaseSession = firebase.child('sessions').child(session);
        setupFirebaseHandlers(session,present);
        present(intents.joinSession(session));
      } else {
        present(intents.wrongSession());
      }
    });
  };
Jean-Jacques Dubray
@jdubray
May 26 2016 00:31
As I mentioned before, the persistence layer can be called within the model, rather than nap, but you may prefer using nap to go through a reducer, to mutate the store properties in case the result diverge from the expected value (proposed by the action's output)
David Fall
@509dave16
May 26 2016 04:25
Thanks for all of the feedback. I have even realized that my project is poorly structured. I need to come up with some comments/documentation that will clarify what's going on in addition to naming and organizing files properly.
Alexey Shamrin
@shamrin
May 26 2016 14:17
@jdubray I don't understand how is your safe.newStep example is related to @jsdw Elm example. May be it's because I understand Elm architecture with its update/view/model/effects concepts (and I couldn't understand SAM architecture - I've tried and have failed so far). Or maybe it was not your intention to provide a direct alternative to @jsdw example. Could you please show SAM alternative to Elm example? Maybe there's a place where you've talked about it previously? Thank you!
Jean-Jacques Dubray
@jdubray
May 26 2016 14:48

@shamrin It was not a direct response to @jsdw, I was just arguing that it looks a bit cumbersome to have to model the state machine, just to execute a single effect (CancelLongRequest/PerformLongRequest/Results...). For instance with SAM, cancellations can be generic because of the concept of "Step".

I am trying to bring clarity to the question: "What is the value of separating effects from the application logic"? In SAM, even though you could choose to do so, I feel it is unnecessary.

devin ivy
@devinivy
May 26 2016 14:50
it's hard to theorize about this stuff. ultimately it's very practical. the question is, what problems arise when effects are sprinkled throughout a program? is the rigamarole of isolating effects worth it? does the program remain sensible?
this video posted earlier made an interesting case for elm's effects that seemed nice to me. https://www.youtube.com/watch?v=6EdXaWfoslc
Jean-Jacques Dubray
@jdubray
May 26 2016 14:51
Yes exactly, again, I don't want to say one is bad the other is not, this is 100 % neutral with respect to SAM, I am just seeking the best answer.
Fred Daoud
@foxdonut
May 26 2016 14:53
Seeking the best answer, yes, but if that answer is it depends on your application/situation/use case/etc., then again the advantage is having the choice vs the framework imposing one approach.
Jean-Jacques Dubray
@jdubray
May 26 2016 14:53
Yes, I watched that very presentation but it looks to me that:
  • ok, he does not have to write stubs to test effects
  • but... the effort invested in doing so looks just as big
@foxdonut yes, very good point
devin ivy
@devinivy
May 26 2016 14:55
well, i think elm did do a lot of the testing for him. elm made sure the wiring of the effects was sensible, which i think is important.
Fred Daoud
@foxdonut
May 26 2016 14:55
ultimately SAM is quite flexible in that respect and does not get in your way if you wish to use one approach or the other.
Jean-Jacques Dubray
@jdubray
May 26 2016 14:55
IMHO, you are much better off using virtualizing your effects with something like MounteBank.js
Fred Daoud
@foxdonut
May 26 2016 14:56
I am hoping to demonstrate both approaches using the same (SAM-compatible) [upcoming] library.
Jean-Jacques Dubray
@jdubray
May 26 2016 14:57
@devinivy I am not sure what you gain on one side you don't lose on the other, when you look @jsdw code:
update msg model = case msg of
  CancelLongRequest ->
    ({ model | performingLongRequest = STOPPED }, Cmd.none)
  PerformLongRequest ->
    ({ model | performingLongRequest = STARTED }, performLongRequestAction)
  ResultsFromLongRequest res ->
    if model.performingLongRequest == STOPPED
      then model
      else { model | results = res
                   , performingLongRequest = STOPPED }
that's a lot of state management that you generally don't have to do in SAM
devin ivy
@devinivy
May 26 2016 14:58
true
Jean-Jacques Dubray
@jdubray
May 26 2016 14:58
For me that's a lot of work, you want your Model to be as lean as it can be.
In SAM, Actions are cheap, Models are expensive
Really all I am saying is that in Frameworks like Elm/Redux/Cycle the actions are anemic and in that choice seems to have a cost that I am not sure we should pay. I don't see the value.
devin ivy
@devinivy
May 26 2016 15:02
yeah, i've always agreed with that general sentiment. but elm/redux's actions are really proposals themselves, which are inherently anemic. in redux, at least, there's nothing stopping you from making an action creator.
i like the union-type style proposals.
Jean-Jacques Dubray
@jdubray
May 26 2016 15:05
Yes, of course a proposal always results to a simple data structure, but the question is: should be view make the proposal? my answer is clearly no. There is something between the view and the model.
Alexey Shamrin
@shamrin
May 26 2016 15:06

@jdubray Do you have a complete example implementing what you've talked earlier?

…the case where another action has presented its data and the application state is such that we can no longer present data from an older instance (not to mention things like retries). By keeping track of which action are in flight and allowing actions to present data based on the application state you are in a much better position to implement the logic of complex UIs.

I've looked at sam.js.org and at some of your blog posts, but I have failed to find a good example so far.
devin ivy
@devinivy
May 26 2016 15:07
@jdubray completely on the same page there.
Jean-Jacques Dubray
@jdubray
May 26 2016 15:09
@devinivy What I don't like about Redux is that the Store must be anemic by design (for React to render). I understand that you can use action generators but I would prefer seeing that mechanism available by default, there is always some app specific validation that you would want to do, and that kind of validation would not be best implemented in the model.
I feel that Redux is opinionated in the wrong places (sagas for instance).
@shamrin yes, there is one example
devin ivy
@devinivy
May 26 2016 15:11
what do you think of a view being able to subscribe to state in a way such that the actual mutations were described to the view layer?
Jean-Jacques Dubray
@jdubray
May 26 2016 15:12
@shamrin one of the actions has been implemented to be artificially long running (edit a blog post):
actions.save = (data,next) => {
    data.item = {title: data.title, description: data.description, id: data.id || ''} ;
    if (data.item.id !== '') {
        // simulate a slow save after
        // editing an item
        setTimeout(function() { 
            actions.present(data,next) ;
        }, 9000);
    }
    else {
        // proceed as normal when created a new item
        actions.present(data,next) ;
    }
    return false ;
} ;
If you run the sample, you should see that you can "cancel" before the action presents its data and of course, when it tries to do so, nothing happen.
I am not saying that the notion of "step" solves all possible problems, but I feel it brings some interesting possibilities when you use it properly, which otherwise would require to manage subscriptions of observables or like Elm implement mini state machines to keep track of all these "long running" activities.
@devinivy well, that sounds a lot like data binding... I feel the decoupling on the way back to the view is just as important
For me the view should be made up of stateless components with no app logic whatsoever
I should be able to take my State/Actions/Model and plug a new theme on top and everything should just work
devin ivy
@devinivy
May 26 2016 15:17
why would the view have to be immutable if the state doesn't have to be?
Jean-Jacques Dubray
@jdubray
May 26 2016 15:17
Factoring all the app logic out of the view is a major goal (and I believe accomplishment) of SAM
devin ivy
@devinivy
May 26 2016 15:18
ultimately whether you're using vdom or not, the view is mutating based upon state changes.
truly rerendering the entire view naturally isn't very practical.
so, you can hide those state changes from the view and use vdom to conceptually sweep under the rug what is actually happening (this has its usefulness!) or you can allow the view to mutate by exposing state mutations to it.
this is essentially how polymer annotations work under the hood, which is why i'm curious.
Jean-Jacques Dubray
@jdubray
May 26 2016 15:22
Yes, I am not recommending to render the whole view, the State function can optimize that or you can leave it to a virtual dom library
Then I would prefer a React like mutation. I still feel that it's better to have some component/rendering logic in the view otherwise you would put that logic in the State or worse, the Model
That's the part I don't like about Data Binding is that it makes the assumption that the view is anemic, which I don't believe is true
It is stateless for sure
but not anemic, each component, on average would have some logic to render whatever data is presented to it
Alexey Shamrin
@shamrin
May 26 2016 15:25

@jdubray How to run sam-safe example? I did manage to run the server (had to fix package.json first):

https://gist.github.com/shamrin/4c36c2e7541bd2b65570e9e66ee7dd6e

How do I run the web app? I've tried opening blog.html in Safari (through file:///), but nothing interesting happens.

Jean-Jacques Dubray
@jdubray
May 26 2016 15:25
It's a node app
node server-model.js
Then localhost: 5425
sorry, I'll fix the doc
There is a short video on TimeTravel: https://www.youtube.com/watch?v=o7ZIG4jT0xM
which is part of this sample
Alexey Shamrin
@shamrin
May 26 2016 15:29
GETting from / doesn't work:
$ curl localhost:5425
Cannot GET /
Jean-Jacques Dubray
@jdubray
May 26 2016 15:31
Let me try it
Alexey Shamrin
@shamrin
May 26 2016 15:32
I found the reason why opening blog.html didn't work for me: Safari doesn't yet implement ES6 stuff like arrow functions. The example does work on my Chrome :)
Jean-Jacques Dubray
@jdubray
May 26 2016 15:36
Sorry, yes I have the same problem
Actually it worked for me on Chrome when I open the blog.html file:
~/Downloads/sam-safe-master/blog.html
Jean-Jacques Dubray
@jdubray
May 26 2016 15:41
I'll update the package.json, add a warning about not using node v6 and chrome. Sorry about that.
Alexey Shamrin
@shamrin
May 26 2016 15:44
Thanks!
Jean-Jacques Dubray
@jdubray
May 26 2016 15:47
Thank you! I just updated package.json and README
I am going to be off for a few hours, let me know if you have any question.
Jean-Jacques Dubray
@jdubray
May 26 2016 23:13
"Why I no longer use MVC Frameworks" made it to the 10 year list of articles on InfoQ (ok, this maybe unfair since 2016 is not done yet, but still)