These days, there are just two many combinations of form factors and platforms to support. This combinatory problem forces us to rethink the way we construct the “View”. There is simply no other way around it, one cannot create individual code bases for each form factor and platforms.
Over the last couple of years, frameworks like Angular and React have dominated the Web App construction market, but as we have seen recently with Angular2, the Google and Facebook teams are “still” searching for better ways to build UIs.
I’d like to formally introduce SAM, the State-Action-Model pattern as a replacement for the MVC pattern.
V = f ( M.present( A( data,M ) ) ) )
SAM stipulates that:
- the View is a function of the Model
- the Model is updated by presenting new values computed from Actions
- Actions are pure functions
I prefer calling the View, State or State Representations, hence the SAM Pattern:
There are a couple of key innovations that are worth noticing, the first one was brought by React.js, which showed us the value of expressing the View as a pure function of the Model.
The second one is more of a game changer because it fundamentally rethinks the role of the “controller”: Actions don’t “control” anything, they no longer decide of the resulting View, as it is the case in MVC, or worse, how to update the model, like in Redux. Actions are and must be pure functions:
data’ = A(data)
Each new set of values (data’) is “presented” to the Model, it is the Model that decides whether these values are acceptable or not and how they ought to be inserted into the model. That approach is coming straight from TLA+. Once the model has been updated, the view is itself updated/rendered (React style).
SAM offers a strict separation between the View, the Model and the Business Logic (Actions). There is a bit of model-centric business logic in the model as well, but again, that business logic is completely decoupled from the Action logic.
The React.js team just came up recently with the Redux pattern, which is close to SAM, but exhibits an unnecessary and unwanted coupling between the actions and the model in the Reducer. The decoupling between the Model and the Action is essential and should never be compromised. (Please read also Edwin’s question in the comments below for more details).
An interesting side-effect of the pattern comes from the fact that its flow (trigger, present, update) does not interfere with APIs. API invocations can therefore be positioned naturally where they belong:
- Actions invoke 3rd party APIs
- The Model (exclusively) invokes its CRUD APIs (for instance something like HivePod.io)
For people who thinks in terms of Systems of Record and Systems of Engagement, SAM provides a natural articulation between them Actions sit in the SoE and the model’s operations at the SoR level.
The underlying model is of course structured as a JSON object. The model itself is dynamically constructed (in node.js): the list of blog posts is queried directly from the feed of my WordPress blog and mounted in the model.
There is only one action in that example, the contact form. The view is not not supposed to display contacts (since they are private), but you can easily imagine how the Model gets updated from the function contact (name, email, message).
SAM does not require any framework. The factoring it provides, and the decoupling it achieves makes Frameworks like Angular2 and React.js entirely redundant. While working on SAM, I became convinced that MVC Frameworks were built simply to deal with the horrific coupling between the Controller and the View. MVC is the problem.
In the next few weeks, I’ll come up with precise statistics and more code samples, illustrating the benefits of using SAM in the context of OmniChannel solutions.
You can read more about SAM on my blog: