The SAM Pattern

SAM (State-Action-Model) is a software engineering pattern that helps manage and reason about the application state.
SAM's founding principle is that State Mutation must be a first class citizen of the programming model.

Having mashed up our own implementation of the SAM Pattern made it even more interesting, as we’ve won significant flexibility and speed in development, allowing us to gain more on what capitalize on the most at the engineering team, Developer Time.
This has allowed us to focus more on our business needs and less on bugs, but more importantly, It has enabled us to have the necessary time to craft our software with care and smoothness, so that we can deliver maximum value to our clients.

Here is a 10 min introduction:

Here is an in depth presentation of the pattern in the context of Angular2

You want to see some code? Take a look at the Fishing Game (index.html) here which you can run here.

How does SAM work?

SAM is built on one of the most robust foundation of computer science (TLA+).
SAM recommends factoring application state management along three building blocks: actions, model and state

Actions are triggered by events, their role is to translate events into proposals to mutate the model

The Model is solely responsible for the decision of accepting (or rejecting, or partially rejecting) these values

Once accepted, the State function computes the State Representation from the Model property values and makes sure that everyone who needs to "learn" about the new application state is notified, such as the view which will display the “state representation”

Finally, the State function computes the next-action-predicate which will invoke any automatic action, given the current application state

Every event is processed as “step” which involves this reactive propose/accept/learn flow.That's it! That's all there is to SAM.

The pattern is best implemented with the model as a single state tree and a unidirectional data flow. In the case of Front-End applications, SAM is best implemented when the view is a pure function of the State Representation. Two-way data binding is strictly prohibited as it would entail uncontrolled model mutations.

The pattern forms a reactive loop: events trigger actions which present data to the model, which computes the state representation. The reactive flow forms a natural step and after every step a new "state representation" is created (as a pure function of the model).

As we show in many samples below, the view can be implemented as a series of stateless components which have no knowledge of the model or even the actions.

When learning SAM, we recommend that you make a clear distinction between the programming model (State, Actions, Model), the wiring (how the elements of the pattern communicate) and the Architecture (where the elements of the pattern are physically running). SAM supports different wiring approaches and allows you to write code that can easily be migrated from the client to the server or vice versa (isomorphic javascript).

The State-Action-Model (SAM) Pattern

The View as a Function of the Model

When learning SAM in the context of Front-End applications, the best starting point is to understand the functional relationship between the view and the model.
SAM suggests decomposing the view as a series of pure functions that are fed with the properties of the State Representation.

This concept is extremely simple to implement. I generally implement the front-end components as part of "theme" singleton (because themes are interchangeable):

With SAM, front-end developers can focus on building the view directly from the State Representation, unencumbered from the underpinning APIs. How the we got to the current State Representation is irrelevant. This is the paradigm shift that React introduced in Front-End architectures.
SAM does not always eliminate the need for interactions (request/responses), but it tends to keep a good balance between reactive and interactive modes.

We get a fair amount of questions asking "why not use templates"? The reason is simple: templates are interpreters while functions are mini-code generators. Interpreters are limited in what they enable you to express (not to mention you often have to learn a specific syntax that does not translate at all to another template interpreter).
On the other hand, code generators are infinitely flexible with hardly any drawback. I would personally choose functions over templates any day.

A couple of promising libraries have appeared recently (hyperHTML, lit-html and yalla.js) that offer support a "Functional HTML" approach. They, of course, are particularly good fit for the SAM Pattern.

Business Logic

Not only SAM supports a functional structure for the View, but SAM enables a complete decoupling of the application logic from the View components. If you are not convinced you can look at this vanilla.js TODO sample and the "theme" section.

TLA+ is based on the idea that the best way to describe things formally is with simple mathematics, and that a specification language should contain as little as possible beyond what is needed to write simple mathematics precisely. TLA+ is especially well suited for writing high-level specifications of concurrent and distributed systems. - Dr. Leslie Lamport

If you are interested in learning about TLA+, I found Stephan Merz's course the most approachable introduction to TLA+.

TLA+ is a formal specification which can be used describe, analyze and reason about systems, such as:

sequential algorithms

interactive systems

reactive & distributed systems

real-time & hybrid systems

security-sensitive systems

TLA+ offers a uniform language where Mathematics form the basis for description and analysis of reactive and distributed systems. The key paradigm shift is that no programming language today support any "temporal" constructs. Making programming much more difficult and error prone than it ought to be.

TLA+ also includes concepts such as safety (something bad should never happen) and liveness (something good eventually happens).

In SAM, the business logic is decomposed in three elements: Actions, the Model and the State.

Warning I have been told by readers that it is important to emphasize that SAM does not use the word "State" in the traditional sense of computer science (where a state is an assignment of values to all possible variables).
SAM suggests that the Model structure (and property values) are different from the State Representation, which there could be many of (Web, Mobile, Voice...).
The State Representation also includes the Control State of the system.
The State-Action elements, in SAM, specify the behavior of the system (not the Model):

A State-Action behavior is a sequence:

α1 α2
s1 −→ s2 −→ s3 −→ ...

The step <si, αi, si+1> represents a transition from
state si to state si+1 that is performed by action αi

Please refer to Section 2 of this paper from Dr. Lamport for a discussion on State-Action behavior.

If you don't like the State-Action-Model terminology, I could have also used the Paxos protocol terminology (PAL, Proposer, Acceptor and Learner):

In essence the Paxos protocol roles are exactly the roles of the SAM components: Actions propose values to the Model, which accepts them, which the State accesses (the Learner) to create the State Representation (which is displayed by the View).

I personally like SAM because it surfaces the concept of "State-Action" behavior, which is at the core of SAM, and leads naturally to creating the "State Representation" (i.e. the View).

So, for all intent and purposes, please be warned that SAM's Model is the assignment of values to all possible variables of the application state, while SAM's State (representation), which is sometimes contains the "control state" (such as "started" and "stopped" are two control states of a car), refers to a function that computes the current state representation and control state of the system. In general, the "State" of a system controls which actions are allowed at any given point in time.
The decoupling State/Model supports a multiplicity of state functions (such as a car with a beginner or experienced modes).

Actions

Actions are functions which translate an event into a proposal which contains the values
we want the model to accept. There is nothing else to it.
In Redux for instance, "actions" are a data structure, which are a lot closer to an intent or event than an action. This is a fundamental difference between Redux and SAM
because in Redux the reducer creates an unnecessary and unwanted coupling between the model mutations and the logic that translates intents into model property values.

// Reactive loop wiring
function action(event, present) {
// compute the values we want the model to mutate to
const proposal = the_actual_pure_function_implementing_the_action(event) ;
// present these values to the model
present(proposal) ;
// since we are in a reactive loop, the action returns nothing
}

Actions typically implement context specific logic. If we take the example of a "change of address" action, we might
implement some context specific rules, such as when there is no country specified in the input dataset, the default country
is Australia, while the model is responsible for the integrity of a customer address which requires a country value.
Actions play another important role with respect to invoking 3rd party APIs. For instance, we can define an action which
will invoke a 3rd party validation service, which given an address, returns the postal address (or an error). It is then
the postal address which is presented to the model.

Actions are typically highly reusable across models, and we could even imagine some companies starting offering SAM actions following a SaaS model. A "change of address" action, which returns a postal address given user data is highly reusable, across many businesses.

Model

The model is a singleton that contains all the application state and (logically) exposes a single method: present(proposal). The model is responsible for accepting (or rejecting) the effects of an action.
The model is where integrity rules get enforced. In other words, actions are generally triggered with some context specific data, they
do not have access to the application state, for instance, when you implement a "change password" action, the action will check
if the password is valid in the context of the request, but the model might enforce additional integrity rules, such that you
cannot use a password that matches any of your last three passwords.

The model is also solely responsible for the persistence of the application state. As such, the Model's architecture may follow the Event/Command Sourcing Pattern with respect to the data the it accepts:

State

This concept is unique to SAM. Its purpose is to futher decouple the Model from the View. The State function has two roles:

Translate the model property values into a State Representation

Compute the control state and trigger the next-action predicate

Unintuitively, the State is a pure function that does not hold any (application) “state”.
The State function also computes the current "control state" of the system, but SAM does not require the State implementation to be based the semantics of finite state machines. It offers a structure that is compatible with FSMs but for the most part avoids the unecessaries intricaties of FSMs.
In the Rocket Launcher example, to demonstrate the compatibility, we've have implemented the full semantics of a finite state machine where each control state is computed with pure functions such as:

Depending on the number of control states of your application and the size of your model, these functions can become rather tedious to write. Again, there is no requirement to adopt such an approach, it may help in some cases and be a burden in others where a series of if-then-else on some key properties of the model would be good enough.

Once the state representation is rendered, the State function is responsible for invoking the next-action predicate (nap), which is a function of the model. The purpose of the nap() function is to determine if, given the current control state of the model, there are some automatic actions that need to be invoked. For instance in the Rocket Launcher example,
the "decrement()" action is invoked by the next-action predicate while the system is in the counting state. When the counter reaches zero, it invokes the "launch()" action.

When you feel that a full state machine is required for your app, you may use a library such as the STAR library.

Rendering (or Consumming) the State Representation

In Front-End applications, the State Representation is typically rendered as part of the reactive loop, however, in the most general sense, the state representation is published to consumers (i.e. Learners in Paxos). Formulating the View as a series of pure functions of the state representation work well.

One of the key problems that front-end frameworks try to tackle is the wiring between the HTML events and event handlers.
View components can be decoupled from actions via a list of "intents" which map the application's action to the view component's handlers. We have implemented that approch in the TODOSAM sample. All the theme's components accept an intent map:

The concept could also be extended to map the event format to be directly consumable by the action, but this coupling is less important than the coupling of the actions with the view.

Wiring

The SAM pattern can be described as a Mathematical expression (formula):

V = State( Model.present( Action( event ) ) ).then( nap )

However, that expression is only a logical expression that describes the sequence in which the elements of the pattern are invoked. The expression itself is not representative of the Reactive Flow or the different wiring options.

SAM can be implemented in the browser (like React and Redux), but one of SAM's advantages is that the elements of the pattern can be distributed and composed in virtually any topology.
So there is not a single way to wire the pattern.

You should also keep in mind that SAM is a reactive pattern so there is never a response that is expected: The view triggers an action, which presents its proposal to the model, which asks the state to create a state representation, which is rendered by the view and displayed in the browser.
SAM could also be used with an interactive wiring where a request is wired to an action and the state representation becomes the response to the request.

Let's start with a sample where running SAM exclusively in a single process (e.g. the browser, perhaps assuming the model will communicate with a persistent store).

The model can be defined as a singleton, the actions as pure functions of an event payload, the state (stateRepresentation() and nap()) as a pure function of the model:

Wiring is an important concern when implementing the pattern. For instance, the mobx framework wires individual property value changes to the view rendering function, which is not representative of the behavior of the system and the processing of an action as a unit of work.
As you can see in the example tab below, the view renders for state data changes:

Time Travel

Gunar Gessner has implemented a client-side "Time Travel" dev tool that enables you to take snapshots of the model after
every action is processed and then restore the state of the system with a given snapshot.

Micro Container

The SAFE project (State-Action-Fabric-Element) is a micro-container for SAM implementations which can run in the browser or on node.js.
At a minimum SAFE enables you to wire the elements of the pattern. It also comes with Session Management, Logging and Error Handling. The
current version enables global validation and enforcement of actions, including action "hang back". Last but not least, it implements the Time Travel dev tool.

Composition

The SAM pattern offers some generous composition mechanisms.

First Actions, as pure functions, compose naturally to present a single dataset to the model:

C(data) = A(B(data))

This type of composition is a functional composition and the resulting action is considered to be a single action applied to the system from SAM's point of view. Logically you cannot compose Actions, as it would violate, the Action->Model->State step, you can only create "composite" actions.

Similarly, the State Representation (View) can be decomposed in a hierarchy of components:

V = f( M )
f( M ) = f1( g1(M) + g2(M) ) + f2( h1(M) + h2(M) )

The most interesting composition mechanisms are at the pattern level itself. For instance, SAM supports an instance level composition where one instances runs in the browser and one instance runs in the server.

Though it is theoretically possible, it is highly recommended to refrain from invoking client actions from the server.
The role of the server is rather to deliver the SAM client instance as part of its state representation.

Here is a Parent/Child sample using React 15.0.2 with JSX/Babel. It shows how you can implement a complex form of wizard with a child instance and submit the resulting dataset to the parent, once the content of the form is valid.

NOTE: THIS IS JUST SOME INITIAL THOUGHTS, NEED MORE WORK:SAM also offers an interesting alternative composition mechanism which enable to synchronize a client side and server side model, by which you present the same dataset to both the client side and server side model.

State Machines and Automatic Actions

Computation is a major topic of computer science,
and almost every object that computes is naturally viewed as a state machine.
Yet computer scientists are so focused on the languages used to
describe computation that they are largely unaware that those languages
are all describing state machines - Dr. Leslie Lamport

SAM is particularly well aligned with the semantics of State Machines except for one simple, yet fundamental difference.
Classical State Machine semantics (based on Petri Nets) imply that the actions somehow connect two states, so State Machines are described as a series of tuples such as:

initialState = S0
(S0,A01,S1), (S1,A12,S2)...

This definition is somewhat of an approximation: it is not the action that decides the resulting state, it is the model, which, once the action has been applied (its value have been accepted, or not) that decides the resulting state (Aik are the allowed actions in a given state Si) :

The tuples (Si,Aik,Sk) are merely an observation of the behavior of the state machine, rather than a physical representation of its runtime.
This change of perspective (not semantics) is minute, yet fundamental. SAM would not work (as well) if the traditional semantics of State Machine would be structuring the code.
The SAM semantics are inclusive of this traditional structure, and therefore strictly compatible, but SAM by no means require that one uses a graph of State and Actions.

I believe that is why some people have expressed that SAM "feels natural".

I cannot emphasize enough that it is not necessary to adopt a State Machine structure to use SAM and more often than not if-then-else will be adequate. However, sometimes it may become easier to use a strict State Machine structure.
These functions can be used to validate that an action is enabled or not. They can also more naturally break down the hierarchy in from which the view is rendered.

APIs

SAM was originally designed to solve the strong coupling that MVC creates between the Front-End structure and the Back-End APIs. APIs can be composed at a couple levels in SAM:

Actions: for APIs with no side-effect whatsoever on the model

Model: for CRUD APIs that persist/populate the model property values (commonly called the Data Access Layer)

Concurrency issues aside, an action can present its values when after processing an API call, for instance:

Similarly, the model can perform all the persistence operations (which could result in rejecting some proposed values) before passing control of the Reactive Loop to the State object.
That is very different from React because you cannot touch the State without triggering a rendering of the view, which makes very little sense, when you think of it. It only makes sense when you spread the model state into
the various components, and even then it warps the articulation of APIs with the Front-End reactive Flow.

Headless SAM

SAM can also be used without a View, whereby it listens on incoming Action requests and returns a response which can be the model of a fraction of the model. As such SAM offers a new API implementation pattern which is particularly well suited for implementating Stateful APIs.

Concurrency

JavaScript is a concurrent programming language. In SAM, the model is a critical section that must be synchronized. In simple applications, this is usually achieved without any specific considerations.
SAM's structure where actions can invoke APIs prior to presenting their proposal to model helps significantly by isolating the way the proposal is constructed from the application state mutation. In particular, another action executed concurrently would be able to present it's proposal as if the first (long running) action would have never been triggered.

When concurrency is an issue, it's possible to use the "Bakery Algorithm", again using the work of Dr. Lamport.

How can I get started?

First, I would recommend getting familiar with the approach I call "functional HTML" perhaps starting with this article and its samples (which are not SAM based).

If you are up to building something more substantial, you could download an HTML5 template of your choice and start building an application with it. To make this tutorial more realistic, we are going to build a simple Web Site with Blog and a Contact form.

The SB Admin template seems like a great starting point. The list of components are easy to identify, from the index.html file:

----- Structure ------

Navigation Bar

DropDown

Search

Menu

Footer

----- Structure ------

Stats Summary

Graphs

Tables

...

Many developers dislike the code that will follow (let's call it vanilla.js).
Since this is a matter of preferences, there is not much point in arguing about it. I just happen to prefer a raw JavaScript/HTML5/CSS3 style because:

it enables the greatest number of developers to become full stack developers (with Node.js)

Frameworks

André Statlz has written a great paper comparing the different Unidirectional User Interface Architectures.
The pattern closest to SAM is Famous, but unfortunately, they mutate the model directly from the actions (events in Famous' terms) and they do not support a nap() function.

React.js

The SAM pattern spans several libraries of the React.js nebula: React.js itself, but also Flux/Redux, including separate libraries such as Redux-Thunk and Redux-Saga.
This framework (of libraries) has been built rather opportunistically, solving one problem at a time, without a coherent architecture. Further its architecture focuses heavily on the client, without much consideration for the server.

React + Redux + Thunks + Sagas

SAM

Single State Tree

Single Model Tree

State is read-only

Model is presented with new proposed values

Reducers are pure functionsReducers have access to full scope of state when processing actions

Actions are pure functions with respect to the modelActions have no access to the model to compute the values presented to the model

Store is updated with the output of the reducer function
Listeners are notified of the update

State Representation is created after the model has mutatedNext-Action Predicate evaluates whether an automatic action needs to be triggered

The Next Action Predicate is a pure function of the model which computes the current (control) state of the system and derives the next-action.

The main issues I see with this framework (as a set of libraries) are:

Redux combines the logic that computes the values with which you would update the model with the logic that decides whether the model accepts these values or not.

As a corollary it couples the interface of the reducers to the model. One of the key roles of actions is to adapt the View-Model interface in ways that makes the model insensitive to the view semantics. The Reducers' interfaces are directly shapped by the view, which is an anti-pattern.

Anemic actions are the default in Redux, you need to add the "thunk" library to be able to use functions as actions

Sagas are stateful by definition and their imperative style makes it difficult to reason about what is the next action that will occur.

That being said, the deal breaker, for me, is the fact that Reducers cannot run on the server because of React's architecture.
The store would need to be updated with the output of the root reducer, i.e. the entire state, which would create a high bandwidth, chatty interaction with the client.

Angular2

Angular2

SAM

Two-way Data Binding

Functional HTML - V = f(M)

Components as Classes (OOP)

Functional building blocks (View, Action, State, NAP), in SAM only the Model is an Object

Uncontrolled View updates with Change Detection

SAM programming Step and Rendering are fully decoupled

With all its imperfections, boilerplate and template language, Angular makes it easy to implement the SAM pattern, which in turn, I believe, adds a lot of value to Angular with a Single State Tree and the ability to control mutations outside the Angular components. SAM allows you to code your business logic coupletely decoupled from Angular itself.

For complex Angular components, I found it easier to create a local SAM implementation where all the state mutations are groupled in a single method and map event handlers to actions (which compute the proposal to mutate the application state)

Vue.js

Vue.js is an increasingly popular framework for building modern Web applications. Just like React, the basic framework focuses (mostly) on the View and you need to select from another nebula of libraries when you need to build more robust applications. In this brief analysis, I will focus on vue.js only, as well as the vuex.js library which is a Redux-like state management library. Vue is template based and relies on two-way databinding which is a major step back in Front-End architectures.

Vue + Vuex

SAM

Two-way Data Binding

Functional HTML - V = f(M)

Single State Tree

Single Model Tree

Two-Way Data Binding

Model is presented with new proposed values

Computed properties, Watches and Methods are free to assign new values to the modelIn Vuex,

Actions are pure functions with respect to the modelActions have no access to the model to compute the values presented to the model

Store is updated with the output of the reducer function
Listeners are notified of the update

State Representation is created after the model has mutatedNext-Action Predicate evaluates whether an automatic action needs to be triggered

The Next Action Predicate is a pure function of the model which computes the current (control) state of the system and derives the next-action.

Meiosis

Meiosis is a library build by Fred Daoud that is well aligned with the SAM pattern. The library's core focus is to help organize the data flow of web applications. The general idea behind Meiosis is to start with a model and write a function that creates the view. When you want a looser coupling between the view and the model, you can optionally configure an "actions object" which translates view events into model proposals. Once the proposal is accepted by the model, Meiosis calls the view function with the updated model. You can also define a function to determine if another action should be automatically triggered, given the new application state. Meiosis is designed to work with plain JavaScript functions which, it wires together, without tying your code to the library. Last, but not least, you can switch from one Web framework to another and by changing the view code. The remainder of the code (the model, receiving proposals, actions, and so on) remains the same.