Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Daniel Neveux
    @dagatsoin
    (looking at it)
    Jean-Jacques Dubray
    @jdubray
    Hang back is a bit more generic than cancel, it allows you to trigger as many action you want and let the first one win.
    of course you can cancel a long running action (like a query) by presenting a cancellation to the model
    Daniel Neveux
    @dagatsoin
    mmmh interesting, I have not implemented a fine way to cancel the action yet (appart from return; )
    Jean-Jacques Dubray
    @jdubray
    SAFE makes it generic, it keeps track of "steps" and assign unique ids to all action instances, so that for any given "step" only action can present data to the model
    It should be very helpful in your scenario
    Daniel Neveux
    @dagatsoin
    yes
    Jean-Jacques Dubray
    @jdubray
    can even make it fun for players to interact with each other without writing too much code
    Daniel Neveux
    @dagatsoin
    when ninjas grind a chest to be the first to get the treasureƧ
    Jean-Jacques Dubray
    @jdubray
    yes, excactly
    Daniel Neveux
    @dagatsoin
    :)
    I have also encapsulated the action to have a dev tool which keep traces of the triggered actions. This way the main loop is complety pure. "If action A is triggered with model state B then next model state will be R"
    Jean-Jacques Dubray
    @jdubray
    Yes, SAFE also implements "time travel", I agree that's generally a good thing.
    In your case, that is essential for debugging/testing
    Daniel Neveux
    @dagatsoin
    Yes, and SAM has implemented a very strong mental model. The decoupling is very clear.
    Great job!
    Jean-Jacques Dubray
    @jdubray
    thank you! but it's really TLA+ and React, I just put two great pieces together, nothing more.
    By the way, Wizar looks like an amazing idea!! I can imagine the potential!
    Jean-Jacques Dubray
    @jdubray
    @dagatsoin One more thing about your question on Action composition. So logically, actions cannot be composed, the flow is propose/accept/learn, you cannot trigger another action before the application state has been mutated. That being said, you can create "composite" actions, this is possible/easier to do because of the dataset signature of the present method. You can create composite actions through functional composition A(B(data)) or even C(A(data), B(data))... but you are not triggering multiple "actions" per se. You merely decompose and recompose a single action.
    Daniel Neveux
    @dagatsoin

    Thx for Wizar, I do my best :)
    I understand the need to not trigger another action when model is still mutating. But I don't see how to compose action. Or maybe I am a bit lost in translation around your explanation. Have you got a simple concrete exemple of action composition ?
    For example, does it fit the requirements?

    const actionGiveMana = (manaPts, model) => {
      //somelogic
      ...
      model.present(data); 
    }
    
    const actionHeal = (healPts, model) => {
      //somelogic
      ...
      model.present(data);
    }
    
    const actionCare = (manaPts, healPts, model) => {
      actionGiveMana(healPts, model);
      actionHeal(healPts, model);
      //somelogic
      ...
      model.present(data3, model);
    }

    In the case of firing actionCarethe model will be mutated twice before the final effect. But in my mind, this is still a pure function because we can reproduce the same effect with the same initial model state.

    Jean-Jacques Dubray
    @jdubray
    An action represents semantically a proposal to update the application state in one "step", as a unit of work if you prefer. It is also a unit of authorization, given a particular state (battling, sleeping...) is an action authorized to be triggered. As such the "actionCare" is not valid, or at least you have to make sure that the actionGiveMana "step" is complete before you trigger actionHeal.
    It's ok to pass the model as an input to the action, with the understanding that no mutation should occur there. The mutation occurs when the action invokes model.present.

    I would prefer see something like this if it makes sense to you:

    var careData = actionHeal_(actionGiveMana_(healPts,model),model)
    mode.present(careData)

    where actionHeal() and actionGiveMana() are the pure function generating the input to the present method

    It would look like:
    const actionHeal = (healPts, model) => {
      model.present(actionHeal_(healPts, model));
    }
    All you can do is decompose/recompose the way the dataset is constructed, but logically only one action can present data to the model.
    Daniel Neveux
    @dagatsoin
    thx, and what should the actionHeal_() look like?
    I mean, does it also mutate the model with model.present? Or simply return a data which will be valid for the model?
    Jean-Jacques Dubray
    @jdubray
    nooo, you can only mutate the model calling the present method with some values you want the model to mutate too.
    the values should be raw, no further calculation should be done in present()
    Daniel Neveux
    @dagatsoin

    Ok, I think I understand. actionHeal() and actionGiveMana() should return respectively something like:

    {
        data: {
            manaPts:10,
        }
    }

    and

    {
        data: {
            healPts:10,
        }
    }
    Jean-Jacques Dubray
    @jdubray
    however, a broader validation could occur, the idea is that the action_() function knows little about the model property values.
    yes, exactly
    they could add their points too
    this is like like a pipeline
    Daniel Neveux
    @dagatsoin
    ookaaaaaay
    Jean-Jacques Dubray
    @jdubray
    so you can add healthpoint along the way
    The idea is that the model has the knowledge to update the application state
    the action has the knowledge to validate events and do some calculation to present values that the model would understand
    the view should have no knowledge of the model
    Actions are like mini adapters between the view and the model
    the view generate an event, the action translate that event into proposed values to mutate the model
    but still the action does not know if the update will succeed
    other conditions might influence the outcome of the intent
    Daniel Neveux
    @dagatsoin
    about the other concitions:
    in my case, a player could have a spell (a debuff) on it which will be decrease the received heal point +3 . (the spell is a property of the model)
    During the present computation, if the model detects some healpoints in the data set, il will minus it of 3.
    As the action does not have to know if the player has a debuff, is it correct that this computation is done in the model?
    Jean-Jacques Dubray
    @jdubray
    exactly, the action / intent should not know about that.
    Daniel Neveux
    @dagatsoin
    (for what it is worth the "pipeline" image is crystal clear for me, in fact it reminds me the way Redux pipes the state computation)
    Jean-Jacques Dubray
    @jdubray
    It's not an absolute rule, it is just about separating the "proposal" from the "acceptance" which I believe has a lot of value.
    Yes, except that Redux does not separate the proposal from the acceptance
    that's one of the two main issue with it
    the second issue is the use of Saga which break its principle: single state tree
    Daniel Neveux
    @dagatsoin
    yes, it is why I switched to sam