Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Jean-Jacques Dubray
    @jdubray
    You can also run the sample without a server, you should uncomment the client code and comment the server code
    Bang-Equal
    @Bang-Equal
    I will try
    Jean-Jacques Dubray
    @jdubray
    For instance, in blog.html:
    // client side
                model.present(data) ;
    
                // server side
                //$.post( "http://localhost:5425/app/v1/present", data) 
                //.done(function( representation ) {
                //    $( "#representation" ).html( representation );
                //}        
                //);
    sorry have to go
    Bang-Equal
    @Bang-Equal
    OK, I got it working. The problem was that I was using the wrong url in my browser. Instead of C://crud-blog/blog.html, I was using http://localhost:5425/app/v1/init
    Bang-Equal
    @Bang-Equal
    Also, I opened an issue in sam-safe repo to update the package.json "start" script.
    Thank you for all of your work!
    Jean-Jacques Dubray
    @jdubray
    You are welcome, thank you for giving it a try.
    Bang-Equal
    @Bang-Equal
    @jdubray Hi JJ its me again, I am looking at the code of your website http://www.ebpml.org and I am trying to get an understanding of how SAM can be used in the "real world". Lets say for example, that I published the crud-blog example where a jquery HTTP request is made to the server. Is it safe to expose the server address and file structure to the client? How did you address security in your site?
    Jean-Jacques Dubray
    @jdubray
    In the http://www.ebpml.org/about page, I simply make a request to the feed.xml file so there is security (but that's server side)
    On the Web there is only one security architecture for back-end APIs, either it is safe for anyone to call them (say like feed.xml) or you need users to login and either call the API with a valid session token from the browser or you need to call them safely from the server (say with APIKey)
    You should never bring API credentials on the browser (say like API key), it is 100% unsafe.
    I am a server side guy, I don't believe much in complex browser-based apps. I like the UX of SPA but I prefer when most of the SPA comes from the server rather than making AJAX calls from the browser.
    That's why SAM is 100% isomorphic and I came up with it because I felt that the Front-End driving API signatures was the wrong thing to do.
    Bang-Equal
    @Bang-Equal
    OK so if I were to publish the crud-blog example that we discussed above for example, I would just need to generate a token that the server can validate
    Jean-Jacques Dubray
    @jdubray
    yes, you would want the user to login and if you need to call the API from the browser, I would use a session token. In general API Gateways (such as AWS, Azure, ...) don't implement that pattern, they prefer a server to call the API with an API Key because they implement things like throttling, ... but if you implement your API say with Node.js then it's not hard to manage session tokens.
    Jean-Jacques Dubray
    @jdubray
    Just published an implementation of SAM in AWS Lambda with a DynamoDB session manager
    https://github.com/jdubray/sam-samples/tree/master/crud-blog-lambda
    Kirill Kravchenko
    @kirill-kravchenko
    Hi! I'm trying to build my webapp using sam. So I have the following question: should actions always present data to model
    Jean-Jacques Dubray
    @jdubray
    yes in general, they might decide not to, but they have no other purpose.
    What did you have in mind?
    Kirill Kravchenko
    @kirill-kravchenko
    I want to change color (for example) of my view-component and I would like to select this component from DOM, and set style. In my case (as I understand) we dont have state-representation, so there is nothing to pass to view.display function. Where I should store the function that selects component from DOM and sets new style? Is it state-representation function? Can you provide some small example? Thanks. And sorry for my English.
    Jean-Jacques Dubray
    @jdubray

    I want to change color (for example) of my view-component and I would like to select this component from DOM

    You should not do that, the whole point of V = f(M) is that you (almost) never manipulate the DOM, the color should be part of the model and when you generate the stateRepresentation based on the new application state.

    you can easily adapt this example to draw the rectangle in a different color
    https://github.com/jdubray/sam-samples/blob/master/js-rectangle/rectangle.html
    Jean-Jacques Dubray
    @jdubray
    Add a color to the draw function:
    function draw(x,y, w,h) {
        var x0 = x,
            y0 = y,
            w0 = w,
            h0 = h ;
    
        return function(ctx,canvas,color) {
          ctx.clearRect(0,0,canvas.width,canvas.height);
          color = color || "#000000";
          ctx.fillStyle(color) ;
          ctx.fillRect(x0,y0,w0,h0);
        }
    }
    Jean-Jacques Dubray
    @jdubray
    I have update the example here
    the key to understand is that with V = f(M) and SAM's nap() function, you never need to manipulate the DOM
    The whole point of SAM is to avoid DOM manipulations
    Kirill Kravchenko
    @kirill-kravchenko
    Thanks!
    'The whole point of SAM is to avoid DOM manipulations' - and how about performance? I think element.classList.add much faster then root.innerHTML
    Jean-Jacques Dubray
    @jdubray
    There are many ways you can achieve it, including virtual-dom, I generally don't see any performance issue, even without v-dom.
    you have to try it
    fnzr
    @fnzr
    I'm having trouble understanding how to deal with events that (I think) don't change the model. Say I have a button "Create new user" that displays a dialog to input user data. This action ("display dialog") is somehow managed by the model? There are no data to be evaluated by the model, only fancy visuals, so would I need a flag on the model to identify this click event? Or this event would be outside the SAM cycle?
    Jean-Jacques Dubray
    @jdubray
    @f-matos yes, in general this will be mediated by an action-model-state loop. The action will translate the event/intent into a proposal to the model (displayDialog:true), which the model could accept or reject based on the application state. The state representation will render a dialog. In general you want 100% of the application state to be managed by the model.
    fnzr
    @fnzr
    Doesn't this create a lot of complexity to the model? The more actions you have, the more states you have to deal with and more bloated the model is.
    If for every action all states are evaluated, it'll become troublesome to prevent side effects (as in, one action proposal affects an unintended state), unless you start naming your proposals "SpecificNameThatImSureIsUniqueFlag"
    Why should the model care - or even know - about the view presenting a dialog? Unless the state "dialog open" intentionally changes how other elements behave, I don't understand why would it be beneficial to give this information to the model.
    fnzr
    @fnzr
    When I say "If for every action" I actually mean "If for every UI change".
    Jean-Jacques Dubray
    @jdubray
    Everything is tradeoff. Single State Tree approaches are becoming pretty standard these days. People have tried to decompose the application state in components and that's not pretty.
    Please note that SAM supports parent/child instances so the effect that you are talking about is not given at all. These ancillary aspects of the application states should be implemented that way and the parent model should only be presented with key proposals such as a { newUser: {name, ...}}
    @f-matos For small UX effects, such as a spinner, it's ok to manipulate the DOM onEvent as long as the resulting state does not need to know it happened (it will be automatically cleaned up on the next rendering of the State representation).
    Jean-Jacques Dubray
    @jdubray
    The key to understand the SAM pattern is that with SAM you are/need to be always in the position of associating a "unit of work" to an event. Component publish events, they have no idea what happens next. The unit of work is responsible for changing the application state. The problem is when you think you are better off working locally and ignoring global application state changes. There is a (rather big) mismatch between the view and these units of work, they can't be driven by the view. You need "adapters" that will translate these events into the call that will ultimately be responsible for updating the application state. Coupling events with application state mutation is, IMHO, the worst thing you can do.
    Nadal Gonzalo García Zavala
    @snorkellingcactus

    Hi. In the rocket launcher example, ¿What is the purpose of this line?

    present = present || model.present ;

    When i would want to pass a custom present function? in which cases?

    Another question: It's a bad idea to deal with a model directly from an action instead of passing a associative-array like data to model.present() ?

    For example:

    function actionsLaunch()
    {
        model.start()        //Set model->started member to true
        model.present()
    }

    Instead of:

    actions.launch = function(data, present) {
        present = present || model.present ;
        data.launched = true ;
        present(data) ;
    }

    I'm trying to port it to PHP, and see how it look in an Object-Oriented like style.

    Thanks you

    Jean-Jacques Dubray
    @jdubray
    The actions can be rewired on the spot rather than using the default present method (of the model). It can also be used for unit testing because the action does not return a value, SAM is based on a reactive loop: event->(action->model->state)->view
    I'd say, yes in general it's better to not factor the model around "actions" but rather around "units of work". We are used (as humans and developers) to think in terms of actions, but your code is better factored when the actions sit outside the model and the model is more "data centric", a little bit like a database. You talk to the model in terms of SQL statements. There is a bit of logic in the database but that logic is focused on the data integrity, not knowing why the data got there in the first place. That's the role of the action.
    Nadal Gonzalo García Zavala
    @snorkellingcactus
    So, i made the php code look more like the JS example.
    Now, i have a doubt about the limits of PHP beign non-dynamic.
    My version of the example uses html meta refresh to update the view.
    ¿How should be the reactive loop behavior here?
    I let the model decide when to render or not the state on certain cases, breaking the loop:
    event->(action->model)
    I think i have the alternative option of say to the view the next event, modifying the meta refresh url, so the next refresh an event is trigered.
    Jean-Jacques Dubray
    @metapgmr_twitter
    The request hits the action, but the response to the view comes from the state function which returns the state representation. Alternatively, you can also return the new view, but I think it's best to return the state representation.
    Radosavljevic Slobodan
    @radosavljevic

    Hi I've just started reading on SAM architecture. I like what React has been doing, but everything is actually based on a hunch to be honest, so I'll follow Kyle Simpsons advice and diversify my sources :). It's a long road, but everything begins with a first step.

    I have a question;
    what are your thinkings on redux-logic?
    https://github.com/jeffbski/redux-logic

    Best regards.

    Slađan Ristić
    @sladiri
    Hi, I started an example of SAM in the Cerebral framework. https://github.com/sladiri/sam-cerebral. It does not require a immutable tree, and automatically rerenders components, if a particular part in the state tree changes.
    I started with the small Choo framework at first, but the render notifications would result in something what Cerebral already does.
    Slađan Ristić
    @sladiri
    Cerebral uses Function Tree, which allows for a nice implementation of SAM so far, I think.
      {
          signal: [
            ...ensureSamState,
            guardSamStep,
            {
              true: [warnBlockedAction],
              false: [
                set(state`sam.stepInProgress`, true),
                getProposal(action),
                propose,
                getControlState,
                ensureControlState,
                {
                  false: [throwError("Invalid control state.")],
                  true: [
                    set(state`sam.controlState`, props`controlState`),
                    getNextAction,
                    when(props`nextAction`),
                    {
                      true: [set(state`sam.napInProgress`, true), runNextAction],
                      false: [
                        set(state`sam.napInProgress`, false),
                        set(state`sam.stepInProgress`, false),
                      ],
                    },
                  ],
                },
              ],
            },
          ],
          catch: new Map([[Error, [logError]]]),
        }
    Jean-Jacques Dubray
    @jdubray
    @sladiri I started to look at your sample, but it will take me a few days to wrap my mind around it.
    You should repost it on the main forum, I am sure other people are interested in it.
    Dennis Davis
    @ddavis914
    Hi I'm running the inferno app and I have a couple of questions: does anybody know where I can find out more information on the syntax of the markup language used ie {tag: 'div', children:[{ tag: 'form', events:{onsubmit: () => actions.start({})}} ]...}. I get it is a tokenized version of html, but I am looking for what language this is - I looked at the inferno doc and it does not specifically say what tokens are valid. Second question - the actions.start declaration takes (data , present) parameters but then is called with an object actions.start({}). I thought I'd ask before testing what is actually passed. Thanks alot - btw i'm convinced this is THE way to manage the complexity of multiple actors attempting to modify the model - action - present - accept - model update - view update - very clean with a mathematical proof of correctness to boot - sweet.
    view.ready = function(model) {
      return {
        tag: 'div',
        children: [
          view.counter('Counter: '+model.counter),
          {
            tag: 'form',
            events: {
              onsubmit: () => actions.start({})
            },
            children: [
              {
                tag: 'div',
                className: 'form-group',
                children: [
                  {
                    tag: 'input',
                    attrs: {
                      type: 'submit',
                      value: 'Start'
                    }
                  }
                ]
              }
            ]
          }
        ]
      }
    }