InfoQ Homepage Articles Why I No Longer Use MVC Frameworks

# Why I No Longer Use MVC Frameworks

This item in japanese

Lire ce contenu en français

## Web Development InfoQ Trends Report

Find out what technologies from the web development space you should keep an eye on this year. Be the innovator in your team and learn more about Vue.js, GraphQl and React. Read the report.

The worst part of my job these days is designing APIs for front-end developers. The conversation goes inevitably as:

Dev – So, this screen has data element x,y,z… could you please create an API with the response format {x: , y:, z: }

Me – Ok

I don’t even argue anymore. Projects end up with a gazillion APIs tied to screens that change often, which, by “design” require changes in the API and before you know it, you end up with lots of APIs and for each API many form factors and platform variants. Sam Newman has even started the process of institutionalizing that approach with the BFF pattern that suggests that it’s ok to develop specific APIs per type of device, platform and of course versions of your app. Daniel Jacobson explains that Netflix has been cornered to use a new qualifier for its “Experience APIs”: ephemeral. Sigh…

A couple of months ago, I started a journey to understand why we ended up here and what could be done about it, a journey that lead me to question the strongest dogma in application architecture, MVC, and where I touched the sheer power of reactive and functional programming, a journey focused on simplicity and scraping the bloat that our industry is so good at producing. I believe you might be interested in my findings.

The pattern behind every screen we use is MVC –Model-View-Controller. MVC was invented when there was no Web and software architectures were, at best, thick clients talking directly to a single database on primitive networks. And yet, decades later, MVC is still used, unabated, for building OmniChannel applications.

With the imminent release of Angular2, it might be a good time to re-evaluate the use of the MVC pattern and therefore the value MVC Frameworks bring to Application Architecture.

I first came across MVC in 1990 after NeXT released Interface Builder (It’s amazing to think that this piece of software is still relevant today). At the time, Interface Builder and MVC felt like a major step forward. In the late 90s the MVC pattern was adapted to work over HTTP (remember Struts?) and today MVC is, for all intents and purposes, the keystone of any application architecture.

Even React.js had to use an euphemism when they introduced a framework that, for once, seemed to depart significantly from the MVC dogma: “React is just the View in MVC”.

When I started to use React last year, I felt that there was something very different about it: you change a piece of data somewhere and, in an instant, without an explicit interaction between the view and the model, the entire UI changes (not just the values in fields and tables). That being said, I was just as quickly disappointed by React’s programming model, and apparently I was not alone. I share Andre Medeiros’ opinion:

React turned out to disappoint me in multiple ways, mainly through a poorly designed API which induces the programmer […] to mix multiple concerns in one component.

As a server-side API designer, I came to the conclusion that there was no particular good way to weave API calls into a React front-end, precisely because React focuses just on the view and has no controller in its programming model whatsoever.

Facebook, so far, has resisted fixing that gap at the framework level. The React team first introduced the Flux pattern, which was equally disappointing and these days, Dan Abramov promotes another pattern, Redux, which goes somewhat in the right direction but does not offer the proper factoring to connect APIs to the front-end as I will show below.

You would think that between GWT, Android SDK and Angular, Google engineers would have a strong view (pun intended) as to what could be the best Front-End Architecture but when you read some of the design considerations of Angular2, you don’t necessarily get this warm feeling that, even at Google, people know what they are doing:

Angular 1 wasn’t built around the concept of components. Instead, we’d attach controllers to various [elements] of the page with our custom logic. Scopes would be attached or flow through, based on how our custom directives encapsulated themselves (isolate scope, anyone?).

Does a component-based Angular2 look a lot simpler? Not quite. The core package of Angular 2 alone has 180 semantics, and the entire framework comes close to a cool 500 semantics, and that’s, on top of HTML5 and CSS3. Who has time to learn and master that kind of framework to build a Web app? What happens when Angular3 comes around?

After using React and seeing what was coming in Angular2, I felt depressed: these frameworks systematically force me to use the BFF “Screen Scraping” pattern where every server-side API matches the dataset of a screen, in and out.

That’s when I had my “to hell with it” moment. I’ll just build a Web app without React, without Angular, no MVC framework whatsoever, to see if I could find a better articulation between the View and the underlying APIs.

What I really liked about React was the relationship between the model and the view. The fact that React is not template based and that the view itself has no way to request data felt like a reasonable path to explore (you can only to pass data to the view).

When you look long enough, you realize that the sole purpose of React is to decompose the view in a series of (pure) functions and the JSX syntax:

<V params={M}/>

is nothing different than:

V = f( M )

For instance, the Website of one of the projects I am working on right now, Gliiph, is built with such a function:

(Click on the image to enlarge it)

fig 1. The function responsible for generating the HTML of the site’s Slider component

That function is fed from the model:

(Click on the image to enlarge it)

fig 2. The mode behind the sliders

When you realize that a plain old JavaScript function can do the job just fine, then your next question is why you would use React at all?

The virtual-dom? If you feel like you need one (and I am not sure many people do), there are options and I expect more will be developed.

GraphQL? Not really. Don’t be fooled by the argument that if Facebook uses it profusely, it must be good for you. GraphQL is nothing more than a declarative way to create a view-model. Being forced to shape the model to match the view is the problem, not the solution. How could the React (as in reactive) team possibly think it’s ok to request data with “Client-specified queries”:

GraphQL is unapologetically driven by the requirements of views and the front-end engineers that write them. […] A GraphQL query, on the other hand, returns exactly what a client asks for and no more.

What the GraphQL team seems to have missed is that behind the JSX syntax, the subtle change is that functions isolate the model from the view. Unlike templates or “queries written by front-end engineers”, functions do not require the model to fit the view.

When the view is created from a function (as opposed to a template or a query) you can transform the model as needed to best represent the view without adding artificial constraints on the shape of the model.

For instance, if the view displays a value v and a graphical indicator as to whether this value is great, good or bad, there is no reason to have the indicator’s value in your model: the function should simply compute the value of the indicator from the value v provided by the model.

Now, it’s not a great idea to directly embed these computations in the the view, but it is not difficult to make the view-model a pure function as well, and hence, there is no particular good reason to use GraphQL when you need an explicit view-model:

V = f( vm(M) )

As a veteran MDE practitioner, I can assure you that you are infinitely better off writing code than metadata, be it as a template or a complex query language like GraphQL.

This functional approach has several key benefits. First, just like React, it allows you to decompose your views into components. The natural interface they create allows you to “theme” your Web app or Website or render the view in different technologies (native for instance). The function implementations have the potential to enhance the way we implement responsive design as well.

I would not be surprised, for instance, if in the next few months, people start delivering HTML5 themes as component-based JavaScript functions. These days, that’s how I do all my Website projects, I pick up a template and immediately wrap it in JavaScript functions. I no longer use WordPress. I can get the best of HTML5 and CSS3 with pretty much the same level of effort (or less).

This approach also calls for a new kind of relationship between designers and developers. Anyone can write these JavaScript functions, especially the template designers. There is no “binding” syntax to learn, no JSX, no Angular template, just plain old JavaScript function.

Interestingly, from a reactive flow perspective, these functions can be deployed where it makes the most sense: on the server or on the client.

But most importantly, this approach allows the view to declare the minimum contract with the model and leaves the decision to the model as to what it the best way to bring this data to the view. Aspects like caching, lazy loading, orchestration, consistency are entirely under the control of the model. Unlike templates or GraphQL there is never a need to serve a direct request crafted from the view perspective.

Now that we have a way to decouple the model from the view, the next question is: how do you create a full application model from here? what would a “controller” look like? To answer that question, let’s go back to MVC.

Apple knows a thing or two about MVC since they “stole” the pattern from Xerox PARC in the early 80s and they have implemented it religiously since:

fig.3. the MVC Pattern

The core issue here is, as Andre Medeiros so eloquently puts it, that the MVC pattern is “interactive” (as opposed to Reactive). In traditional MVC, the action (controller) would call an update method on the model and upon success (or error) decide how to update the view. As he points out, it does not have to be that way, there is another equally valid, Reactive, path if you consider that actions should merely pass values to the model, regardless of the outcome, rather than deciding how the model should be updated.

The key question then becomes: how do you integrate actions in the reactive flow? If you want to understand a thing or two about Actions, you may want to take a look at TLA+. TLA stands for “Temporal Logic of Actions”, a formalism invented by Dr. Lamport, who got a Turing award for it. In TLA+, actions are pure functions:

data’ = A (data)

I really like the TLA+ prime notation because it reinforces the fact that functions are mere transformations on a given data set.

With that in mind, a reactive MVC would probably look like:

V = f( M.present( A(data) ) )

This expression stipulates that when an action is triggered, it computes a data set from a set of inputs (such as user inputs), that is presented to the model, which then decides whether and how to update itself. Once the update is complete, the view is rendered from the new model state. The reactive loop is closed. The way the model persists and retrieves its data is irrelevant to the reactive flow, and should certainly never, absolutely never, be “written by front-end engineers”. No apologies.

Actions, again, are pure functions, with no state and no side effect (with respect to the model, not counting logging for instance).

A Reactive MVC pattern is interesting because, except for the model (of course), everything else is a pure function. In all fairness, Redux implements that particular pattern, but with the unnecessary ceremony of React and a tiny bit of coupling between the model and the actions in the reducer. The interface between the actions and the model is pure message passing.

That being said, the Reactive MVC pattern, as it stands, is incomplete, it does not scale to real-world applications as Dan likes to say. Let’s take a simple example to illustrate why.

Let’s say we need to implement an application that controls a rocket launcher: once we start the countdown, the system will decrement the counter and when it reaches zero, pending all properties of the model being at nominal values, the launch of the rocket will be initiated.

This application has a simple state machine:

fig.4. the Rocket Launcher state machine

Both decrement and launch are “automatic” actions, it means that each time we enter (or re-enter) the counting state, the transition guards will be evaluated and if the counter value is greater than zero, the decrement action will be called upon and when the value is zero, the launch action will be called instead. An abort action can be undertaken at any point, which will transition the control system to the aborted state.

In MVC, that kind of logic would be implemented in the controller, perhaps triggered by a timer in the view.

This paragraph is very important, so please read carefully. We have seen that, in TLA+, the actions have no side effects and the resulting state is computed, once the model processed the action outputs and updated itself. That is a fundamental departure from the traditional state-machine semantics where the action specifies the resulting state, i.e. the resulting state is independent of the model. In TLA+, the actions that are enabled and therefore available to be triggered in the state representation (i.e. the view) are not linked directly to the action that triggered the state change. In other words, state machines should not be specified as tuples that connect two states (S1, A, S2) as they traditionally are, they are rather tuples of the form (Sk, Ak1, Ak2,…) that specify all the actions enabled, given a state Sk, with the resulting state being computed after an action has been applied to the system, and the model has processed the updates.

TLA+ semantics provides a superior way to conceptualize a system when you introduce a “state” object, separate from the actions and the view (which is merely a state representation).

The model in our example is as follows:

model = {

counter:  ,

started:  ,

aborted:  ,

launched:   }

The four (control) states of the system are associated to the following values of the model

ready = {counter: 10, started: false, aborted: false, launched: false }

counting = {counter: [0..10], started: true, aborted: false, launched: false }

launched = {counter: 0, started: true, aborted: false, launched: true}

aborted = {counter: [0..10], started: true, aborted: true, launched: false}

The model is specified by all the properties of the system and their potential values, while the state specifies the actions that are enabled, given a set of values. That kind of business logic must be implemented somewhere. We cannot expect the user could be trusted to know which actions are possible or not. There is simply no other way around it. Yet, that kind of business logic is difficult to write, debug and maintain, especially when you have no semantics available to describe it, such as in MVC.

Let’s write some code for our rocket launcher example. From a TLA+ perspective, the next-action predicate logically follows the rendering of the state. Once the current state has been represented, the next step is to execute the next-action predicate, which computes and executes the next action, if any, which in turn will present its data to the model which will initiate the rendering of a new state representation, and so on.

(Click on the image to enlarge it)

fig.5. the rocket launcher implementation

Note that in a client/server architecture we would need to use a protocol like WebSocket (or polling when WebSocket is not available) to render the state representation properly after an automatic action is triggered,

I have written a very thin, open source, library in Java and JavaScript that structures the state object with proper TLA+ semantics and provided samples that are using WebSocket, Polling and Queuing to implement the browser/server interactions. As you can see in the rocket launcher example, you should not feel obligated to use that library. The state implementation is relatively easy to code once you understand how to write it.

I believe that we have now all the elements to formally introduce a new pattern, as an alternative to MVC, the SAM pattern (State-Action-Model), a reactive, functional, pattern with its roots in React.js and TLA+.

The SAM pattern can be represented by the following expression:

V = S( vm( M.present( A(data) ) ), nap(M))

which stipulates that the view V of a system can be computed, after an action A has been applied, as a pure function of the model.

In SAM, A (actions), vm (view-model), nap (next-action predicate) and S (state representation) are and must all be pure functions. With SAM, what we commonly call the “state” (the values of the properties of the system) is entirely confined to the model and the logic that changes these values is not visible outside the model itself.

As a side note, the next-action predicate, nap() is a call-back invoked once the state representation has been created, and, on its way to be rendered to the user.

fig.6. the State-Action-Mode (SAM) Pattern

The pattern itself is independent of any protocol (and can be implemented without difficulty over HTTP) and any client/server topology.

SAM does not imply that you always have to use the semantics of a state machine to derive the content of the view. When actions are solely triggered from the view, the next-action predicate is a null function. It might be a good practice, though, to clearly surface the control states of the underlying state machine because the view might look different from one (control) state to another.

On the other hand, if your state machine involves automatic actions, neither your actions nor your model would be pure without a next-action predicate: either some actions will have to become stateful or the model will have to trigger actions which is not its role. Incidentally, and unintuitively, the state object does not hold any “state”, it is again a pure function which renders the view and computes the next-action predicate, both from the model property values.

The key benefit of this new pattern is that it clearly separates the CRUD operations from the Actions. The Model is responsible for its persistence which will be implemented with CRUD operations, not accessible from the view. In particular, the view will never be in the position to “fetch” data, the only things the view can do are to request the current state representation of the system and initiate a reactive flow by triggering actions.

Actions merely represent an authorized conduit to propose changes to the model. They, themselves, have no side effect (on the model). When necessary, actions may invoke 3rd party APIs (again, with no side effect to the model), for instance, a change of address action would want to call an address validation service and present to the model the address returned by that service.

This is how a “Change of Address” action, calling an address validation API would be implemented:

(Click on the image to enlarge it)

fig.7. the “Change of Address” implementation

The elements of the pattern, actions and models, can be composed liberally:

Function Composition

data’ = A(B(data))

Peer Composition (same data set presented to two models)

M1.present(data’)

M2.present(data’)

Parent-Child Composition (parent model controls data set presented to the child)

M1.present(data’,M2)

function present(data, child) {

…

// synch models

child.present(c(data))

}

Publish/Subscribe Composition

M1.on(“topic”, present )

M2.on(“topic”, present )

Or

M1.on(“data”, present )

M2.on(“data”, present )

For architects who thinks in terms of Systems or Record and Systems of Engagement, the pattern helps clarify the interface between these two layers (fig. 8) with the model being responsible all interactions with the systems of record.

fig 8. SAM Composition model

The entire pattern itself is composable and you could implement a SAM instance running in the browser to support a wizard-like behavior (e.g. a ToDo application) interacting with a SAM instance on the server:

fig. 9 SAM instance composition

Please note that the inner SAM instance is delivered as part of the state representation generated by the outer instance.

Session rehydration should occur prior to triggering the action (fig. 10). SAM enables an interesting composition, where the view could call a third party action providing a token and a call back pointing to a system action that will authorize and validate the call, before presenting the data to the model.

fig. 10 Session Management with SAM

From a CQRS perspective, the pattern does not make a particular distinction between Queries and Commands, though the underlying implementation needs to make that distinction. A search or query “action” is simply passing a set of parameters to the model. We can adopt a convention (e.g. the underscore prefix) to differentiate queries from commands, or we could use two distinct present methods on the model:

• ##### GitHub Pages

Your message is awaiting moderation. Thank you for participating in the discussion.

Following up on some readers' requests, I created a github repository to help people get started with SAM

jdubray.github.io/sam/

• ##### Re: Easier to use React and GraphQL

by Alex Hawkeye /

Your message is awaiting moderation. Thank you for participating in the discussion.

One strong benefit of GraphQL, and in fact the original motivation for it's creation was to fulfill all data needs in a single round trip to the server, where it's often the case that using REST APIs requires subsequent round trips to get all the necessary data if you need multiple types of data for your views. This is critical for performance, especially on mobile devices where network latency can be really large and the penalty for additional round trips is large.

The primary way GraphQL is used with React is through another library called Relay. Relay allows you to write small pieces of a GraphQL query called "fragments" next to your React components. Relay will fold together all fragments relevant in order to make the single GraphQL query network request to load the information necessary to render your views. Relay can do some pretty interesting things with this model as well, like serve you previously fetched data from cache while going to the server for newer information.

GraphQL plays nicely with a node micorservices architecture.You can also use Facebook dataloader to take advantage of caching. Works well with Redis github.com/facebook/dataloader#redis

Like it or not RGR( React GraphQL Relay) is here to stay. It is the future. Everything is moving client side. REST is dead. Front-end engineering is the future. Backend will be pretty basic relative to the complexity of the front-end. You'll just have full stack Java Script engineers. None of this back-end/front-end nonsense. Mainly comes down to economics. JS is just insanely cost effective. You don't have to believe me but it's happening just the same as JavaScript is the universal language of the future. medium.com/@mjackson/universal-javascript-47610... I remember, 3 years ago, when people laughed at the idea of JavaScript taking over the world. Now Node is 3.5 million strong with 100% annual growth and JavaScript is the most popular programming language in the world. Facebook has a lock on the web. It's too big to stop. Anything novel, they'll just acquire, hire the creator or steal.

You make some good points though and I like the idea of SAM but we need to get everyone on the same page.

The only difficult thing about using RGR is the initial setup. After that, it's so easy. Just plug-n-play. Long term maintainability is so easy. it's just hot swapping components. The more siloed everything is, the better. That's how the real world works and there is no reason it shouldn't be exactly the same on the web.

And lastly, you're a JavaScript expert and are able to conceptualize things that others with less experience aren't able to do just yet. A lot of startups like frameworks because a) they can't afford experts like you and b )it gets everyone ( regardless of experience ) on the same page. You may not like the massive influx of novice coders but the demand for programmers is just gnarly...and will only get gnarlier into the future.

• ##### Re: Easier to use React and GraphQL

Your message is awaiting moderation. Thank you for participating in the discussion.

Alex,

as a former co-author of the Service Data Object specification (SDO). I believe I understand GraphQL to a reasonable level. All that you are saying is correct, however, in the world I live the front-end very rarely talk to the database with no business logic in between. My world is also filled with all kinds of exceptions such as unavailable systems of record or failed transactions which require compensation.

When you live in that world GraphQL does not apply. Now I understand why Facebook built GraphQL and why it might work well for them, but I would refrain presenting it as a magic bullet. There has been countless products on the market that are GraphQL like (I tried to use MetaMatrix, Composite Software 15 years ago, participated in the SDO spec, ...). When your world is well formed they work like magic (with some edge cases around joins).

>> REST is dead.
you are saying that to please me ;-)

>> Front-end engineering is the future. Backend will be pretty basic
>> relative to the complexity of the front-end.
perhaps, our industry seems to love pendulum swings, personally I am agnostic, SAM unlike most of what React does is composable across tiers so I am totally agnostic to that argument and the composition patterns of SAM (say unlike Redux) allow you to be very smart about dispatching actions wherever they are... that is incredibly powerful.

>> JS is just insanely cost effective. You don't have to believe me but it's happening
>> just the same as JavaScript is the universal language of the future.
You don't have to convince me,I strongly believe that too.

>> you're a JavaScript expert and are able to conceptualize things that
>> others with less experience aren't able to do just yet.
Actually, quite far from it, I don't code for a living. I actually it is the other way around Frameworks stifle innovation because they require super advanced skills to work around their broken semantics and fake optimizations.

With SAM an ordinary developers can start writing very innovative and beautiful Web apps. SAM resets the clocks (sorry a TLA+ joke) on Frameworks and Front-End developer skills, not to mention bringing balance between designers, front-end and back-end developers.

So again, I don't discourage people using GraphQL below the model, sounds like a reasonable technology, but I would not present it as a magic bullet as you are doing, it is not applicable. I have heard so many time the story: "after a long and complex setup everything is easy"

SAM shows that everything can be easy: I can replace React.js+Redux+Thunks+Saga and have no urging need for GraphQL+Relay with a single line of code. Imagine that. I'll defend that claim any day.

• ##### Use RxJS

by Tom Flaherty /

Your message is awaiting moderation. Thank you for participating in the discussion.

Interesting especially with the functional approach, but still too much ceremony with all the View, Model, State and Action nouns. All you need are RxJS Subjects with message driven publish and subscribe.

• ##### Re: Use RxJS

Your message is awaiting moderation. Thank you for participating in the discussion.

With all due respect, you are missing the point and confounding wiring with semantics. SAM is about an extremely precise code factoring, you can wire the pattern any way you want, it's even ideal for "Isomophic JavaScript". Rx is wiring.

SAM's core value proposition is three-fold:
- it enables libraries of View components like never before because the View never contains a single line of business logic (what you would put in the view, you factor it in the State)
- it supports a precise articulation of APIs with respect to the Application business logic
- It is strictly aligned with the semantics of state machines, without requiring a state machine implementation, this means that you can now apply the 80-20 rule (80% of the time simple if-then-else would be enough to decide how to render the view, when you need to better understand the "current state" to decide what to do, the business logic is already factored in such a way that you can bring state machine semantics as needed)

There is no amount of Rx or Pub/Sub (aka wiring) that would give you these semantics. Generally, the Rx wiring lead you to do the wrong thing because you are forced to process actions without the ability to check the "current state".

Hope this is clear

• ##### Wiring and Semantics

by Tom Flaherty /

Your message is awaiting moderation. Thank you for participating in the discussion.

The irony is that I use semantics for my methodology practices. The distinction is that my practices are coupled by design intent.

So then for the general UI components I recommend a decoupled approach with RxJS supplying just the right amount of wiring.

My specific business UI components which are named for their intent contain logic to drive presentation which can be based on semantics if they fit the business domain. I see no need for MVC or any other framework state semantics.

In my RxJS library the current state is published to you. The notion of a current state somewhere else is ill conceived and checking for it introduces unwanted scenarios even when guided by semantics.

To summarize:
1. The components are Views and REST interfaces that pub / sub changes.
2. The Model changes are the pub / sub payloads.
3. The Controller is replaced by a notification driven reactive approach.

• ##### Re: Wiring and Semantics

Your message is awaiting moderation. Thank you for participating in the discussion.

Again, Tom with all due respect you just cannot make up the semantics of computing.

>> the current state is published to you.

The current state of a system is computed from the model after it has accepted the proposed values from the intents/Actions.

In TLA+ the current state (aka control state) is computed from the model property value, I can't "start" a car when the battery is dead. I can issue that intent a million times, and the car will still not start. Sorry, it is as basic as that.

Wiring has nothing to do with this, Views are merely state representations. They do not stand on their own, they do not have interfaces and/or lifecycles. As soon as a view issues an action it's lifecycle ends and it is replaced by a new (logical) view at the end of the reactive loop. Otherwise your architecture is not reactive, it is interactive. There is no amount of Rx or Pub/Sub that will make it Reactive. Reactive means there is never a response (logically), even if physically it looks like a request/response for optimization purposes.

Feel free to continue the discussion on Gitter. gitter.im/jdubray/sam or read more about the pattern at: sam.js.org

• ##### Semantics and State Machine

by Tom Flaherty /

Your message is awaiting moderation. Thank you for participating in the discussion.

SAM's functional formulations are good, but you are over reaching in asserting that without SAM your are making up the semantics of computing. My point is that generalized UI semantics like MVC start prescribing approaches that lead to opinionated frameworks with too much ceremony. This assessment is based on Angular1 projects where I saw my teams creating too much framework mandated boilerplate. So we refactored to RxJS and have not felt the need to add anything else for a year an half.

RxJS like all the ReactiveX streams is reactive that supports life cycles. Sending a "car won't start" or better yet a car status message when the "battery is dead" is easy.

As with any component we would implement a state machine as a set of RxJS subjects and attach them to our streams.

Upon reviewing SAM I see state machine semantics that fits an approach that your passionate about, so go with it.

At this point I need to break of the conversation to engage in some political activism.

• ##### Re: Semantics and State Machine

Your message is awaiting moderation. Thank you for participating in the discussion.

>> without SAM your are making up the semantics of computing

It is actually TLA+, not SAM. I would never dare to say that SAM is even remotely close to be the foundation of computing.

>> MVC start prescribing approaches that lead to opinionated frameworks with too much ceremony
When you take a look at the architecture behind React+JSX+Redux+Thunks+Sagas+GraphQL+Play you realize that they slightly, almost imperceptibly ignored these semantics and before you know it you create "opinionated frameworks with too much ceremony" to correct what was simply a poor code factoring from the beginning. When the factoring is the problem, the framework is not the solution.

Let me take a simple example. A developer just asked the question on Gitter: is seneca.js a good fit for SAM? Seneca allows invoking actions based on some pattern matching technique. One would think cool, why not? That solves the problem everybody hates which is wiring the view to the problem actions. You have a number of ways to do that, including Rx. Wiring technologies come a dime a dozen (async or RPC).

How about we change our perspective on the problem? The problems stems from the fact that the View is perceived to be this statically defined object (especially in Angular). But in SAM V = S(M), the function S() acts as a mini code generator, the view components are "generated" on the fly (thank you React, that is such a paradigm shift). With SAM you can wire the view as needed. The State function knows everything about the current state, the allowed actions and can generate correctly wired View components.

You can take a look at the Theme functions in the TODO(notMVC) sample App

Looking at ReactiveX and subjects it looks awfully complicated for something that a mini code generators solves trivially.

V = S(M) (courtesy of React) is a major step forward for Software Engineering once you start measuring how different it is from templates + data bindings. Unfortunately for the Facebook team, they took again the wrong turn and made the React View "interactive" with GraphQL which is a particularly bad way to bind data to the View.

• ##### Re: Semantics and State Machine

Your message is awaiting moderation. Thank you for participating in the discussion.

It you have an hour or so, I would recommend this article from Dr. Lamport on Computation and State Machines. I believe every single developer should read it. It would lead to much less opinionated framework and ceremony.

• ##### redux saga

Your message is awaiting moderation. Thank you for participating in the discussion.

What do you thing of redux saga?github.com/yelouafi/redux-saga and how do you think it compares to SAM when combined with redux itself.

• ##### Re: redux saga

Your message is awaiting moderation. Thank you for participating in the discussion.

Sagas break the principle #1 of both Redux and SAM which is to manage the application state in a single state tree. So this is is a non starter for me. That is simply the wrong thing to do.

Once the application state/model has mutated, you compute the next action, the concept of Saga (as imperative code) is very rigid and does not represent reality well (Sagas were created for trans-actions, not re-actions). State machines (SAM) provide a far easier way to compute the next action as a if (in state S) then A(...).

Dan has simply misunderstood the complexity of dealing with actions in relation to model mutations and he has conceded to patch his approach with Thunks on one side and Sagas on the other without measuring the implications on the overall architecture. When you combine that with the fact the Reducer:
- does not scale since you have to mutate the entire application state
- cannot be isomorphically run on the server or client
- cannot invoke APIs (CRUD or 3rd Parties like SAM)

I am not quite sure why you would consider using Redux at all. If you want to use React but you are not sold on the React nebula (Redus, Sagas, Thunks, GraphQL, Relay...) , SAM offers a far simpler, isomorphic, architecture.

Dan is focused on one thing: tools (Time Travel, Hot Reloading) not on architecting front-end/back-end. We have Time Travel with SAM: github.com/sam-js/sam-devtools

Feel free to join us on gitter: gitter.im/jdubray/sam

• ##### Re: Same old data problem...

Your message is awaiting moderation. Thank you for participating in the discussion.

Jim, I think you are correct. The real issue in my world, is that we don't have good tools to write applications in terms of data. SQL does not compose well. And since computer languages are increasingly sophisticated, we look for solution in the language itself. But we don't fix the data aspect of it. We are fighting SQL instead of really fixing it. There are some attempts at fixing SQL composition but they address the issue of creating SQL. Not of building up a functional data model that can be partially translated to SQL and partially executed in the language runtime. I am working on this problem and hopefully I can get a demo out that better exposes the issue. And BTW, this solution being a language solution is way simpler than most frameworks that I've seen. And it does not substitute the framework, but is relives it from the responsibility of transforming data.

• ##### Great Article

Your message is awaiting moderation. Thank you for participating in the discussion.

I really appreciate this article and how the SAM Architecture can be implemented with the Ports and Adapters architecture for the backend

• ##### Re: Great Article

Your message is awaiting moderation. Thank you for participating in the discussion.

thank you! Feel free to stop by our discussion forum: gitter.im/jdubray/sam

Here is the pattern's home: sam.js.org which contains links to many samples produced by the community.

One of the most recent samples is an AWS Lambda implementation with a dynamoDB session manager: github.com/jdubray/sam-samples/tree/master/crud...

• ##### sam as an isomorphic architecture

Your message is awaiting moderation. Thank you for participating in the discussion.

There may be some ideas of value in your article. But if there is something proven flawed than it is this "isomorphic" architecture (js for front + backend) you advocate. Node.js' heart of async I/O is built on a horrible concurrency model + you will experience why js is not a language to build business logic in that you can trust (error handling etc). See www.youtube.com/watch?v=q8wueg2hswA
Javascript for developing node was just a poor choice. Read here bostinno.streetwise.co/2011/01/31/node-js-inter... why Ryan Dahl choose javascript. What you can trust (and it is proven to be very reliable) is the actor-based concurrency model. Here about the model diffs: joearms.github.io/2013/04/02/Red-and-Green-Call...

• ##### isomorpic

Your message is awaiting moderation. Thank you for participating in the discussion.

If something has been proven flawed than it is this "isomorpic" architecture (js for front + backend) you advocate. Node.js' heart of async I/O is built on a horrible concurrency model + you will experience why js is not a language to build business logic that you can trust (error handling etc). See this presentation www.youtube.com/watch?v=q8wueg2hswA .
To use javascript for such a thing was just a poor choice.
Read here bostinno.streetwise.co/2011/01/31/node-js-inter... why Ryan Dahl choose javascript to develop node in.
What you *can* trust (and the model *is* proven to be very reliable) is the actor-based concurrency model. Here about the model diffs: joearms.github.io/2013/04/02/Red-and-Green-Call....

• ##### Re: isomorpic

Your message is awaiting moderation. Thank you for participating in the discussion.

Stefan,

I appreciate your insistence on making your point, you are entitled to your opinions. Node being good for I/O and nothing else is a well known fact. I am pretty sure every InfoQ reader knows about it. I would argue, however, that SAM is Node's best friend since instead of writing the business logic in one big blob, SAM encourages people to use three buckets (Actions, Model and State) which helps a bit. Perhaps we could ask Netflix what they think about Node.js?

I don't know any other approach where Isomorphism between Server and Client is so seamless (SAM+Node). You can move as little as a single action, to any combination of actions and model, model and state, ... after writing all you code... on the client. I have even shown that the same code runs unchanged ... on AWS lambda.

SAM being a patten, I certainly encourage people using it everywhere they want and do not seeing tied to any given technology. What is clear though is that FRP is not going to crack the front-end/back-end architecture. We have confounded assignments with mutation for decades. Trying to put a big box (function, actor,...) around some poorly written code is not going to solve that problem. It is only by implementing mutation correctly that we will solve that problem. SAM is based on TLA+ / Paxos, I certainly encourage everyone to learn more about them and make mutation a first class concept of their programming model. Immutability is the wrong way to think about... mutation.

PS: I am at t=26min of the presentation you referenced and I have learned nothing new/of value. Just the usual stock photography and trivial code samples, so I'll stop here.

• ##### ERP en 'SAM'?

Your message is awaiting moderation. Thank you for participating in the discussion.

Bonjour JJ
Nous sommes une petite équipe qui essayons de créer un ERP Web communautaire, mix de airbnb Uber et Odoo Facebook etc.
Serveur en Python car aucun framework FP n'est encore aussi mur que Django par exemple, mais j'ai encore de gros doutes quant au front: Angular 2, Elm qui m'a séduit et que nous investigons, ou... Pur JS grâce à l'approche SAM ? Regardez Facebook et Odoo, à votre avis ces deux UX et Ui sont elles faisables, avec le maximum de productivité en création puis évolution maintenance, en Elm ou SAM JS ?
Un très très grand merci pour cet article passionnant (mes ingénieurs n'ont pas encore tout décortiqué) et vos conseils.

• ##### Re: isomorpic

Your message is awaiting moderation. Thank you for participating in the discussion.

Jean-Jacques,

How entitled are you yourself on selling your isomorphic ideas? I think you try to sell your ideas very aggressively, whereever you can. A bit of googling reveals discussions in at least elm and react groups (more will be simple to find). F.e. your comments in github.com/reactjs/redux/issues/1528 are remarkable. They are often not very considerate; you're sitting high on your horse and you hide behind your jargon.
The goal of my reaction is a warning to others reading your articles to be very carefull. Some of your ideas might not be such a good idea to realize. Waving with a netflix article is not convincing. I'd rather trust my own ears and senses than the big names and jargon you hide behind "TLA+ ! Lamport! Do you think you're smarter than Lamport?". You can easy find articles from / about companies switching from node to f.e. go. For the rest the links I already sent are convincing, to me at least. To me you're a friars latern. Interesting lights leading nowhere.

• ##### Re: ERP en 'SAM'?

Your message is awaiting moderation. Thank you for participating in the discussion.

Bonjour Nicolas,

merci pour le feedback, n'hesitez pas a nous rejoindre sur Gitter pour continuer la discussion.

J'ai développé tres tot une allergie aux frameworks, mais SAM marche quand meme tres bien avec Angular2 ou meme Elm. SAM exprime simplement qu'il ne faut pas confondre "assignments" avec "mutation" et que par consequent il vaut mieux partitionner sa logique metier en trois "buckets": Actions, Model et State.

Les UX d'Odoo ou Facebook sont totalement faisables avec SAM. En fait SAM permet d'utiliser toutes les possibilités d'HTML5/CSS3 sans la lourdeur des frameworks qui tendent a les limiter.

Si vous avez des questions specifiques n'hesitez, toujours heureux d'y repondre.

JJ-

• ##### Re: Thank you

by Wing Cheng /

Your message is awaiting moderation. Thank you for participating in the discussion.

It is a delightful idea which solves the model-view coupling problem.
I am busy rereading sam.js.org and Leslie Lamport's book 'Specifying Systems' in past 2 weeks. You remind me what I have studied in hardware. The circuits don't work as design/desire if the math is wrong.
It is different in programming UIs; usually, they mostly works as desire but leave some difficult to fix and highly coupled mixed concepts in the system.

• ##### Plan-Tree execution.

Your message is awaiting moderation. Thank you for participating in the discussion.

To decouple my server-side logic, I use an agent I call "Scribe" that translates user UI gestures into user-intent statements. A "Dialog" agent then matches that user-intent statement to a vignette that choreographs the dialog -- gathering more information and/or initiating a work-plan tree whose branches may be executed in parallel. Thus my server-side API is defined in business-model terms. There may be multiple Scribe implementations to translate to and from multiple UI frameworks. The dialog does not need to know what the UI framework looks like. Plan frames are defined as post-condition (goal) a set to pre-conditions, and a transitional action. Actions are basically defined as a procedure to be executed by an actor that knows a role. Actors check-in at run-time and are assigned role-related tasks by a dispatcher. --- I know this is a dense description. I can provide links to better documentation on request.

• ##### Re: Plan-Tree execution.

Your message is awaiting moderation. Thank you for participating in the discussion.

Richard,

I'd be happy if you share the links. You can also join our community on Gitter: gitter.im/jdubray/sam

JJ-

• ##### Re: cycle.js

Your message is awaiting moderation. Thank you for participating in the discussion.

Hi Jean
sorry if I correct your message, cycle can be written in many different ways, one of this is with MVI (model - view - intent).
If you check in the official examples and in the documentation you can see how the pattern works.
it's a unidirectional pattern where model, view and intent are pure functions that are linked together by observables.
With Cycle you can also work with a state management like onionify that leverage the concept of fractal architecture (github.com/staltz/cycle-onionify)
Last but not least, you can also create a plugin architecture using MVI for the components and the grid driver as communication bus: medium.com/@domagojk/creating-a-scalable-javasc...

• ##### Re: cycle.js

Your message is awaiting moderation. Thank you for participating in the discussion.

Luca,

thank you for the pointers, I am glad that since this article was published, Andre finally came to his senses and drove Cycle.js towards a single-state-tree architecture (though an "onion" may not be the best moniker to label this major breakthrough). When you look at the way people build "large apps" with Cycle.js, that doesn't sound very convincing. The ToDo app diagram shows an overly complicated, and dedicated flow that contrasts quite a bit with the electricity metaphor that the author is trying to convey.

Since I wrote this article I realized three things that I'd like to share:
1/ you need to reason clearly about the programming model, the wiring and the architecture of your system, Frameworks tend to "sell" you a bundle that is not optimal. I don't sell anything, SAM is just a programming model that you can use with any framework, any wiring and any architecture. However, I would greatly encourage people to think thoroughly their choices.

2/ SAM and Functional Reactive Programming (Elm/Redux/Onionized-cycle) overlay quite well. SAM simply states that:
- what redux calls actions or elm calls messages are events
- the "reducer" or "update" function need to be factored in three buckets: actions, model and state. There are real benefits behind that factoring

3/ last but not least, we have been writing software for decades using 3 approximations
- actions can change the application state
- assignments are equivalent to mutation (I assign therefore I mutate)
- there is no need to define clearly what is a "programming step", so when we write a = b+c, we don't need to ask if that's the right programming step or if, for instance, we need to distinguish: read b,c ; compute b+c; assign a with b+c;

Using these approximations is not wrong, but they are nevertheless approximations which do not apply to modern distributed systems.

SAM addresses these three approximations: actions cannot mutate the application state, mutation is clearly defined, independent of assignments and action->model->state is "the" programming step.

So we can continue opposing shiny hammers, mixing up programming model, wiring, and architecture in the process, or we can discuss, as grown-ups, the underlying structure of our work. I'll choose the latter.

• ##### MVC is misunderstood

Your message is awaiting moderation. Thank you for participating in the discussion.

I recommend the following article, since it focuses on what purpose MVC originally had, before the engineers changed it into something that only they would understand: github.com/ciscoheat/mithril-hx/wiki/Rediscover...

• ##### Re: MVC is misunderstood

Your message is awaiting moderation. Thank you for participating in the discussion.

Andreas,

I appreciate when people are trying to perpetuate the legacy of Prof. Reenskaug, but it is now counter productive. MVC was designed in an other era (that I would qualify as "disconnected") and it no longer makes sense, either as a Design Pattern or, even worse, as a Software Engineering pattern. I agree that it has been used and generally misused in the last 40 years or so but it simply cannot account for an "activity-oriented" world where the a graphical user interface is just a node in a complex distributed system. There is no bridge that can connect a user to the underlying "model", even Facebook has lost control of the state-machine behind their client(s). At best a users can think in terms of events it is allowed to produce, they have no possible clue as to what will happen next. It's even hard for product managers and developers to keep enough control on "what happens next".

The idea that "views are created and coordinated by a Controller." is corny at best, mostly deadly. That, as a software engineering pattern, needs to go entirely.

Your idea about "reuse" is deeply flawed, if you have no clue as to factor your code for reuse, you obviously will not achieve reuse. SAM, for instance, breaks the mold of a "reusable" component into reusable building blocks. I have shown repeatedly that SAM's view components (organized as themes) are reusable across applications, so are actions, so are model acceptors. I can even easily wire 3rd party actions into my application. The non-reusable code is limited to state function that wires the application logic to the view components. It literally sickens me to read this kind of statement:

This means that we can couple MVC objects because they aren't on the actual level of being reusable.

You are sending generations of developers to jump of the MVC cliff for no other reason that you cannot think out of the (controller) box. It is actually this outrageous coupling that lead us to the concept of "templates" that is the worst drug our industry has ever invented. Scores of developers got hooked on it which lead to "runaway" code, where it was always easier to add another view than try to build reusable building blocks. In the last decade that poison spread to the back-end as APIs were designed to fit templates one-at-a-time. Before you knew it any medium size projects were tied to hundreds if not thousands of APIs. It was so bad that we had to invent a new pattern, the "vertical slice pattern", to at least make sure that we could keep some sanity in each of the hundreds of slices that were created.

And I could continue on and on, no the model should not know anything about the views, it is the state function who should managed the relationship between the model and the consumers of the model, which happen to be sometimes views (as view components in SAM). You may not have noticed that there is a static aspect to the model and a dynamic one and you get tremendous benefits when you keep both separate (decoupled as you might say).

No one "Can ask a Model for the current value of data it presents to the user", because as you might understand in a distributed system, the model is busy updating itself from another event. Thinking that there is no concurrency possible in a modern user interface is at best naive.

In SAM there is no "controller" (central coordinator) that for instance "Creates and manages Views", this is ludicrous. When an action is triggered, the action should only be responsible for converting the event into a proposal that the application logic can understand and process (another great decoupling between the view components which emit events and the model which processes proposals created from these events).

• ##### Re: MVC is misunderstood

Your message is awaiting moderation. Thank you for participating in the discussion.

MVC is a pattern language, not a pattern. Together with DCI it gives a complete and completely different view than the "counter productive" one you try to purvey. But you seem convinced of your own nerd-centric ideas, so I see no point arguing further.

• ##### Re: MVC is misunderstood

Your message is awaiting moderation. Thank you for participating in the discussion.

These "nerd-centric" ideas are founded on the most robust theory ever invented in Computer Science: TLA+. I am happy to discuss point by point what you stated in your post, but you have to take a stance on what "true" MVC is. A lot of what you write in your post is plain old application architecture and code factoring.

Again apologies for repeating myself but "align[ing] the computer and the programmer (that sounds pretty nerdy to me?) with the mental model of the end user" no longer makes sense in modern application architectures.

MVC has shown repeatedly that it creates runaway systems where it's always cheaper to create yet-another-view (and now set of APIs to support that additional view) than creating application reusable building blocks. You even state clearly that any form of reuse is not only, a non goal, but it is impossible. Really?

In 2009 I joined a big bank that nearly failed because of a massive MVC-based CRM system they had built. That system required a team of 120 modelers (not even developers, modelers) just to keep track of the API interfaces that supported the views of the system.

• ##### Re: MVC is misunderstood

Your message is awaiting moderation. Thank you for participating in the discussion.

Aligning the computer with the end user always makes sense. Not doing that is what led us to the current situation, where a company have cushions on the walls so people won't hurt themselves when banging their heads because the system is a complete mess. But hey, there are probably some nice diagrams on how well-structured it is under the hood! I bet all unit tests pass too.

You, and of course many others as I state in my article, have clearly misunderstood MVC. There is no "true" MVC, that's another wishful engineering thinking. It's a pattern language. There is no "true" language either, see the difference?

A "set of APIs" for each view? What do you mean, a way of communicating between objects? Then every method is an API! That is surely taking that concept too far. (I notice you like to use the acronym though.) Also, you don't see a certain dichotomy here, there is a U-I and an AP-I?

MVC hasn't shown that it creates runaway systems. The massive "MVC-based" (sic) system you talked about was probably overengineered, overly abstracted and severely lacking in conceptual integrity. That's not MVC's fault. As usual, structure replaces architecture when the engineers gets to decide. Or, the project really needed 120 modelers. ;)

• ##### Re: MVC is misunderstood

Your message is awaiting moderation. Thank you for participating in the discussion.

Andreas, you are contradicting yourself, not sure what point you are trying to make. You argue on one hand that the artefacts of MVC are not reusable (looks like that is by construction) then you argue that when you end up building a runaway system, it's because you don't know how to use MVC. The very definition of a runaway system is when reuse is close to nil, your only choice is to build another view and the entire vertical slice that goes with it, that is exactly what happens with MVC, precisely because it only focuses on the User mental model.

• ##### Re: MVC is misunderstood

Your message is awaiting moderation. Thank you for participating in the discussion.

When you start to think of M, V and C as roles instead of separate reusable objects that can be put in neat square boxes, maybe you will understand the point I'm trying to make. Until then, good day, but lastly I need to correct another misconception of yours: MVC does not only focus on the User mental model. Quote from Reenskaug:

The fundamental idea for the programmer's mental model was to separate the computer representation of the user's mental information model (the Model) from the parts of the program that facilitate the user observing and editing selected aspects of it, the Views.

• ##### Re: MVC is misunderstood

Your message is awaiting moderation. Thank you for participating in the discussion.

Andreas, again, MVC is from another time where there could actually express and formalize a good enough connection (~isomorphic) between the user mental model and the computer information model. We are way passed that time, users can only think in terms of events they can emit and/or actions they can perform (concepts that are critically missing from MVC itself). There is no longer a "next view" in an app today, again that concept is long gone.
Your attempt to perpetuate the legacy of Prof. Reenskaug is honorable, but these concepts are holding our entire industry back in a time where user/activity experience is key to building successful solutions and deliver experiences that anyone without a deep computer expertise can handle.
So again, today no one (users or developers) can think in terms of "views", or "model" (controller is an arbitrary concept without any tangible existence) but everyone can think in terms of "actions" and "state". State is the representation of the model that has direct physical connection.
The example I take to explain the difference between model and state is the one of an electric car. What does it mean for an electric car to be "started". Everyone would say, it just has to have enough battery, but not quite, it has to have enough battery to go where you need to go, otherwise there is no point in taking the action to "start" your journey. How could a user know all the rules that connect the model to a state? It's impossible even for software engineers.
That is the fundamental flaw of MVC, it's missing two key concepts: Actions and State which model precisely the interaction of a user or system with a information model. Trying to connect a user or even a system directly to an information model is pointless, actually that approach could not have been more flawed. It just took us 40 years and the incredible work of Dr. Lamport to figure it out.

• ##### Model as a class?

by Dennis Davis /

Your message is awaiting moderation. Thank you for participating in the discussion.

Hi Jean-Jacques, Man what a breath of fresh air!! Cleared the table of all the noise and got straight to the bulls eye. Sorry, my point is the last thing you said was "decades of Object Orientation seem to be all but gone. I can no longer think in terms other than reactive or functional". I, for one am not ready to let Bertrand Meyers tome - and the wisdom in at go by the wayside, neither do you - as I see you like the design by contract way of constructing software. So that leads me to ponder since the actions are pure functions why can't those pure functions be methods of an object?

• ##### Re: Model as a class?

Your message is awaiting moderation. Thank you for participating in the discussion.

Dennis,

apologies I just saw your comment. The SAM pattern makes a clear distinction between programming model, wiring, and architecture. There is, of course, no particular reason not to wire the pattern that way, but you would not change its semantics in doing so. The fact that the actions would be structured in a class is not implied, required or otherwise adding any value to the semantics of the pattern.

As a matter of fact I created a basic (but effective) component model where building blocks of the pattern are assembled in a static structure.

It's more important as an industry to agree on the semantics of the pattern:
- what is an action?
- are all assignments mutation?
- what is a programming step? (A-M-S? any line of code?)

FP, OOP, RP, FRP, ... are all missing a precise answer to these questions. TLA+ does, and hence SAM.

• ##### Redux + Thunks

by Michael Ryan /

Your message is awaiting moderation. Thank you for participating in the discussion.

Even without react, I think you'll find that redux + redux-thunks is *VERY* close to the SAM model you're looking for... I've even seen it used server-side across a websocket channel. The library itself isn't that big, and the API is very easy to understand and approachable.

• ##### Re: Redux + Thunks

Your message is awaiting moderation. Thank you for participating in the discussion.

Yes, this is correct, Redux ActionCreators correspond to SAM Actions. That being said, decoupling "actions" from "mutation" are not considered a best practice for Redux. There are several other important aspects missing in Redux, such as the many-to-many relationships between actions and mutations (now called acceptors in SAM). The State function is also not considered a best practice in Redux and NAP (the next action predicate is missing as well). So I would argue they are quite different. The temporal aspects of SAM are more pronounced while Redux tend to stay within the realm of functional programming.

• ##### very good article

by linda lim /

Your message is awaiting moderation. Thank you for participating in the discussion.

I really like the article that you wrote in this blog something very nice to follow

• ##### Hooks

Your message is awaiting moderation. Thank you for participating in the discussion.

Seems a bit outdated now. React hooks and functions component are going the right way.

• ##### Flux for .NET

by Peter Morris /

Your message is awaiting moderation. Thank you for participating in the discussion.

There's a no-boilerplate / UI-agnostic Flux library for .NET -> github.com/mrpmorris/fluxor

Your write-up of the pattern is very comprehensive!

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Is your profile up-to-date? Please take a moment to review and update.

Note: If updating/changing your email, a validation request will be sent

Company name:
Company role:
Company size:
Country/Zone:
State/Province/Region:
You will be sent an email to validate the new email address. This pop-up will close itself in a few moments.