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
    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
    Felipe Matos
    @imfelipe
    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.
    Felipe Matos
    @imfelipe
    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.
    Felipe Matos
    @imfelipe
    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'
                    }
                  }
                ]
              }
            ]
          }
        ]
      }
    }
    Jean-Jacques Dubray
    @jdubray
    @ddavis914 I am not sure about what syntax library they use. "h.js" (hyperscript) is a popular library in that space but this looks different. It would be best to ask the question on the Inferno forum. (https://github.com/Matt-Esch/virtual-dom/blob/master/virtual-hyperscript/README.md)
    Jean-Jacques Dubray
    @jdubray
    the purpose of having an optional "present" argument is to allow for a functional composition of actions (not a logical composition, because logically actions cannot be composed). You can technically call action1(data,action2) the proposal of action1 will be presented to action2 which should add its own proposal which will then be presented to the model. This is not used in that example, but I try to use a consistent "wiring" of the pattern across all the examples.
    In general actions will validate, enrich and transform an event into a proposal. In that example, the actions are very basic but in a real application that would be very common. IMHO, this is also a very good place to call APIs, and present the result to the model.
    Dennis Davis
    @ddavis914
    Thanks Jj.
    Jean-Jacques Dubray
    @jdubray

    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.

    I know that Feynman said "The first principle is that you must not fool yourself – and you are the easiest person to fool.", but after actively building large scales projects with the SAM pattern, I also believe the same thing. There is no increase in complexity of the lifespan of a project. You can always reason in simple and local terms, regardless of the size of the application. I wish I could articulate that better, and people would give it a try, and understand that the structure of their code is important and Dr. Lamport may have well found a universal structure.

    It seems that the industry is not paying enough attention to that question: "how code should be factored", lots of people come up with a factoring (say MVC) but they are not really looking at connecting it to a formalism to make sure it's correct. One could see, for instance, how naive it is to use a pure function to manage state, even though Lambda-calculus is behind it.
    Dennis Davis
    @ddavis914
    The 'Industry', what can we say about that? Money. I was thinking versions of (enter your framework or library here) that break code = money - that is 'good' for the industry if bad for the customers. It seems that the industry can use tools that slice away the clutter as Mr. Crockford presented and I submit a JavaScript front and back achieves/promises. To this breakthrough, along comes the studied - correct - mathematically based programming pattern (STAR) (You were the first to introduce me to a pattern that has its roots in a mathematical proof - even if that proof needs a CS degree to comprehend - thank goodness for V = f(M)!! ). For that I am thankful - another thing I am thankful for is your review of the industry tool-set v. SAM - Thank you for sharing that wealth of knowledge. It is really important for non-cs degree - yet - folks to rest on something we can prove is correct! I had a prj that I would have used the SAM pattern to help reason about - and build a solution - (multiple warehouse forklift drivers loading a container - off the same model (bill of lading) - mid stream - meaning container half - full - bill of lading could change - prompting the a new model to be broadcast to the active BOL drivers and old model/new model comparison for off-loading) (drowning in state, actions, models and pipes).
    Jean-Jacques Dubray
    @jdubray
    thanks @ddavis914 There is certainly a revenu factor, but really there is a pure lack of "first principle" thinking. After all these years, we could admit that there are four irreducible concepts in Software Engineering: State, Type, Action, Relationship (STAR). Please note there are no "function" here. "Events' are not included in that list because an event is "an occurence of a state". These are the building blocks of any software. Yet we focus a lot of energy in the on the concept du jour (streams, resources, ...). STAR is timeless, as much as Matter, Light, Force and Energy are to physics.
    TLA+ (the temporal logic of actions) provides an essential/fundamental/unbreakable relationship between Types, Actions and States (Relationships are orthogonal here). Compare that to functional programming which, in principle provides a much simpler (perhaps naive) relationship between "states":
    Sj = fij( Si)
    Jean-Jacques Dubray
    @jdubray
    Sure, you can architect your software as a series of states and functions, but the relationship between them becomes conceptual, compare that to SAM (based on TLA+ semantics):
    Sj = State( Model.present( A(Si) )).then( Model => NAP(Model))
    Jean-Jacques Dubray
    @jdubray
    This structure is a lot easier to reason about, because of the temporal foundation (unlike Si, fij which has no temporal semantics).
    Your project, like so many, would gain a lot using STAR/SAM. Any business process involves a strong temporal component, that is poorly represented by any other formalism. That has been a very long quest, and I feel I finally cracked it.
    Jean-Jacques Dubray
    @jdubray
    What I mean by that is that I found a formalism that gives me the structure that I had been loocking for. I didn't do much, to be honest, just translated the incredible work of Dr. Lamport into something I can use every day.
    Karl Page
    @karlpage_gitlab
    Just wanted to say, SAM is awesome. So simple, so succinct, and works beautifully. I also spend most of my time developing back-end solutions. Every now and again I need to create a front-end solution. I have used MVC and similar patterns. Disparate code ends up all over the place. I am new to functional programming, but I got the gist of SAM. Knocked up a simple example (C#, Winforms) as was amazed that I have never spotted this myself. Great work! As seems to be the case with FP, functions are small, one-liners. A bit more experimenting, but so far, I can see me using this in my commercial applications. I mainly develop financial applications. Many thanks for a new insight into UI development.
    Jean-Jacques Dubray
    @jdubray
    Karl, I am truly humbled by your comment! That has been also my experience ever since I stumbled on this idea.
    Not sure if you also explored BOLT, a methodology that I developed prior to SAM, but BOLT + SAM offers a continuum between business strategy, user stories, programming and testing (BDD).