APIs, React.js, SOA, STAR

Introducing the SAM pattern as an alternative to MVC




This is a repost of my LinkedIn post.

I have been on a very interesting journey in the last few weeks as I was focusing on finding ways to lower the cost building OmniChannel Digital Assets.

These days, there are just too 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.

SAM is a derivation of both React.js and TLA+ concepts. SAM, as a pattern, can be expressed as a simple formula:

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:

sam

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.

If you want to see the pattern in action, here is a quick example I built last week-end: a simple about.me page. I started with an off the shelf HTML5 template, and simply created a functional wrapper, using plain vanilla JavaScript functions.

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.

Of course, SAM works just as well in the language of your choice: Objective-C, Java, C#, PHP… there is nothing specific to HTML or JSON or JavaScript.

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:

3 Comments

  1. Adnan,

    the pattern does not specify the architecture, it simply specifies the semantics and the (reactive) flow. RxJS would be a perfect mechanism to implement the “present” method on the Model. You could equally implement it over HTTP, as long as you retain the semantics of the pattern.

    With respect to Cycle.js, again it’s pretty close, the View is a function of the model, actions are functions as well, however, it looks like the “present” semantic is absent, not that it could not be added, it would be rather simple to add that semantic.

    Now, you have to be really careful, because from a reactive programming model perspective, SAM is a variation of the traditional approach (http://cycle.js.org/observables.html#reactive-programming) where:

    “[the Model would be] fully responsible for managing its own state by reacting to external events. The [Action would be] unaware of the existence of the arrow originating from its network request event.”

    The SAM reactive loop is intentional: the State is aware of the possible actions (from an HATEOAS perspective) and these actions are aware as to where they need to present their results (the Model).

    Unfortunately the example that is chosen to (inc/dec counters) is not a good one because that action could be interpreted as an internal Model action (CRUD). In SAM terms, there is an action Increment that is defined as:
    x’ => x+ 1

    then x’ is presented to the model which would have some business logic that decides whether x’ is an acceptable value for x. Logically the “increment” action should not be known to the model, practically, unfortunately, this is a perfectly valid CRUD operation.

    Hope that’s clear, because this is a key point to understand the SAM pattern and the slight variant it brings to the reactive programming model.

Leave a Reply

Your email address will not be published. Required fields are marked *

− 2 = 4