BT
x Share your thoughts on trends and content!

Why I No Longer Use MVC Frameworks

Posted by Jean-Jacques Dubray on Feb 03, 2016 |

 

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) {

            // perform updates

            …

            // 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:

 { _name : ‘/^[a]$/i’ } // Names that start with A or a
 { _customerId: ‘123’ } // customer with id = 123

The model would perform the necessary operations to match the query, update its content and trigger the rendering of the view. A similar set of conventions could be used for creating, updating or deleting elements of the model. There a number of styles which can be implemented to pass the action outputs to the model (data set, events, actions…). There are pros and cons to each approach and in the end it might come to preferences. I favor the data set approach.

From an exception perspective, just like in React, it is expected that the model will hold the corresponding exception as property values (either presented by the action, or returned by a CRUD operation). These property values will be used while rendering the state representation to display the exception.

From a caching perspective, SAM offers a caching option at the state representation level. Intuitively, caching the results of these state representation functions should lead to a higher hit rate since we are now triggering the cache at the component/state level rather than the action/response level.

The reactive and functional structure of the pattern makes replay and unit testing a breeze.

The SAM pattern changes completely the paradigm of front-end architectures because, on the foundation of TLA+, the business logic can be clearly delineated into:

  • Actions as pure functions
  • CRUD operations in the model
  • States which control automatic Actions

From my perspective as an API designer, the pattern pushes the responsibility of the design of APIs back to the server, with the smallest contract possible between the view and the model.

Actions, as pure functions, can be reused across models as long as a model accepts the corresponding output of the action. We can expect that libraries of actions, themes (state representations), and possibly models will flourish since they now be independently composed.

With SAM, microservices fit naturally behind the model. Frameworks like Hivepod.io can be plugged in, pretty much as-is, at that level.

Most importantly the pattern, like React, does not require any data binding or template.

Over time I expect that SAM will contribute to make the virtual-dom a permanent feature of the browser and new state representations will be directly processed via a dedicated API.

I found this journey to be transformative: decades of Object Orientation seem to be all but gone. I can no longer think in terms other than reactive or functional. The kinds of things I have been building with SAM and the speed at which I can build them has been are unprecedented. One more thing. I can now focus on designing APIs and Services that do not follow the screen scraping pattern.

I wanted to thank and acknowledge the people who kindly accepted to review this article: Prof. Jean Bezivin, Prof. Joëlle Coutaz, Braulio Diez, Adron Hall, Edwin Khodabackchian, Guillaume Laforge, Pedro Molina, Arnon Rotem-Gal-Oz.

About the Author

Jean-Jacques Dubray is the founder of xgen.io and gliiph. He has been building Service Oriented Architectures, and API platforms for the last 15 years. He is a former member of the research staff at HRL and earned his Ph.D. from the University of Provence (Luminy campus), home of the Prolog language. He is the inventor of the BOLT methodology.

Rate this Article

Relevance
Style

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

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

Email me replies to any of my messages in this thread
Community comments

Redux by Sam Havens

Great article! I plan on giving it more attention when I have the chance, but I wanted to point out an error: you imply that Redux is inherently tied to React - this is false. To quote the Redux docs, "Redux is a predictable state container for JavaScript apps... You can use Redux together with React, or with any other view library." Here is a conversation on GH about, and with links to, using it with Angular 2 and Vue.js (which is practically plain JS).

cycle.js by Daniel Campagnoli

From my quick read it sounds similar to cycle.js.org/
Have you looked into that? Would you recommend it?

Re: cycle.js by Jean-Jacques Dubray

Daniel,

so first, SAM is a pattern and Cycle.js is a library. Nothing prevents you to use SAM to structure your Cycle.js code.

Second, Cycle.js seems to operate at the same level as React.js (i.e. the View). As such it takes a big short cut in the way you can express the logic in relation to the effects. SAM is based on the semantics of TLA+ and as such provide a foundation to cleanly separate three types of business logic: Action, Model and State. You just can't arbitrarily slice and dice business logic the way you want, otherwise you will not be able to achieve a reactive loops, there will be times where the actions need to call the model and/or the model needs to call some actions. Incidentally Cycle.js does not seem to have an explicit model, just streams, of which the logic and effects hangs off.

Last, I don't believe "everything" is a stream. Far from it. When you look at this Cycle.js example, you get a bit dizzy. You have to do that much thinking to increment/decrement a counter?

SAM pattern and building tools by Nachi Nachiappan

Given the clear articulation of new pattern and discussing the pros and cons of popular frameworks (like React & Angular2), what is recommendation to start on this pattern? Is there any library/tools to speed up development along SAM pattern? any samples in GitHub that might reduce the learning curve?

Re: SAM pattern and building tools by Jean-Jacques Dubray

Yes, here is a standalone code sample (rocket launcher).

I can also share some node.js code samples privately. The reason for that is that the code embeds copyrighted HTML5 templates what you would need to purchase if you want to use as is.

I really want to emphasize that SAM significantly lowers the barrier to build advanced Web apps such as this e-commerce Website.

Alternate path by Max Ward

Interesting article. I hit some of your same issues a few years ago, with the views tightly coupled to the User workflows. Our controller layers were loaded with front end specific code and business logic, and very difficult to test. So I embraced the idea that the controller is tied to a specific step in a User's workflow. On my team's projects, I introduced the "Workflow" layer. It is basically a stereotyped Service layer. It's job is to be tied to each step in a "User" workflow. A typical Spring controller then is just a protocol translator from HTTP (or REST) to Java, and makes a single Workflow call. Super simple, and super easy to test. Same for an MBean, WebService bean, or Scheduled bean. The Workflow layer knows what the frontend needs and calls services to handle that data. With no HTTP layer, or MBean, or WebService dependencies, the workflow layer is also very easy to test.

I need more time to digest what you have here, but at least we identified the same problems.

Same old data problem... by Jim Nasby

As a data architect, my first reaction to this (especially proliferation of APIs) is "Welcome to my world!"

It seems to me that at least some of the problems you're seeing in MVC are related to the problems I see in ORMs: the idea that data APIs should be transparent, and should follow your logical model.

In my experience, that's the opposite of what you want for a robust system. You want APIs that mirror the *physical* world. Shopping card application? The cart should be a self-contained object (that will ultimately reference many tables). User clicks the "Checkout" button? That should result in a single call to the database to get shipping options. User's finalizing the purchase? Again, a single call to the database with the shopping cart ID and shipping options, then the database creates the invoice records (again, most likely in multiple tables) before returning a complete invoice *object* back to the app.

With this kind of paradigm, you have a *real* API: the web code can do whatever it needs to for display. The database can do whatever it needs to for storage. Neither one needs to know what the other is doing.

I'm oversimplifying a bit here, and certainly there's data related operations that don't belong in the database (your rocket launch countdown is a good example). But in my experience almost every application developer thinks data storage should be a dumb thin layer on top of the filesystem, which creates chaos for everyone else that needs to do reporting or analysis on the data.

I think your SAM pattern is a big step forward, as it pushes state into the model. That at least allows for one place to focus on the API to backend storage (and API that is hopefully more sophisticated than CRUD).

Re: Alternate path by Jean-Jacques Dubray

Max,

yes, I believe we agree, the goal is/should be to decouple the way the UI is constructed and behaves from the underlying APIs that query/update the information model. When you shape your APIs to the view they become "ephemeral" to use Netflix's qualifier. Depending on which technology you use to build these ephemeral APIs, you are hosed. (not surprised they are aggressively moving to Node.js).

The argument I develop with SAM is that it's actually not that hard to decouple the UI construction and behavior from your APIs using a reactive/functional approach.

I'll publish more snippets over the week-end that show that you really don't need an MVC framework at all, because you no longer need to wire your APIs up to the view. That was the only value these frameworks provided, albeit it was the wrong thing to do.

The kids in the React team didn't even thought that was a problem, they were having too much fun with the virtual DOM, that is, until people started to build real things with React and then the question came back front and center. Flux was clearly not the answer, Redux, slightly better, but entangled the model with the actions because the pattern is using the wrong state machine semantics.

Re: Same old data problem... by Jean-Jacques Dubray

Jim,

thank you for your comments, yes, after working with it for a couple of months and building an ecommerce website with it (will share some snippets over the week-end) I share your views that ultimately you want to achieve this:
the web code can do whatever it needs to for display. The database can do whatever it needs to for storage.


The Front-End developers will always push you for a CRUD like APIs (resource oriented?).

The beauty with SAM is that:
a) the "actions" become a conduit to the model, actions are by no means "controlling" how the data model updates, they just authorize for and prepare the data to be presented to the model
b) the functional construction of the view forces the front-end developer to think without any response in mind. V = f(M) is forcing the developer to reason holistically about the relationship between the View and the Model, far, far away from the Req/Resp treadmill.

Personally I prefer a data set/event-based interaction between the actions and the model because it gives all the power to people like you to decide how to best organize the information model, query and update it, perhaps you can chime in on that point. I was once a co-author of the SDO (Service Data Object) spec, to perhaps I am biased and there are better ways to deal with that question.

Robert "Uncle Bob" Martin - Architecture: The Lost Years by Dariusz Ostolski

I think it's worth to watch following presentation:
www.youtube.com/watch?v=HhNIttd87xs

Which seems to be very related to your conclusions in the begging of the article (sorry it was TLDR)

gitter by Jean-Jacques Dubray

I created a room on Gitter for the SAM pattern. I am going to be building samples (from my current work) over the next couple of days and share the process there. Any questions are welcomed.

Re: gitter by Enguerrand Vidor

Thank you Jean-Jacques for providing this example! The Javascript world is currently boiling and the path you are exploring seems to disrupt a couple of framework. I like it.

SAM Pattern by Hariharan S

Hi JJ,

It's really good to see this post addressing the problems in MVC.

I would love to look at some sample code / application developed using this pattern

Thanks
Hariharan

P.S - I was pleasantly surprised to look at this article :).

Re: cycle.js by Fred Daoud

That was an interesting article, it is great not to blindly use frameworks, and to question whether we sometimes over-engineer solutions.

That being said, I respectfully counter your "You have to do that much thinking to increment/decrement a counter in Cycle.js?" reaction with the same reaction to your code example (replicated here:codepen.io/foxdonut/pen/MKqXWj) -- you have to churn out that much code to implement a simple launcher?

There is just way too much "how" in your code. I find it so much more expressive of programmer intent to use MVI and event streams in Cycle.js: codepen.io/foxdonut/pen/XXPwRe

Respectfully.

Re: cycle.js by Jean-Jacques Dubray

Fred,

the "state machine" is optional, I felt that was the best way to illustrate a "state" component. You'll notice that it is not present in the other samples.

The SAM pattern is defined by this expression:

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


There is no requirement whatsoever, for an explicit state machine. You are free to write the S, vm, A, present and nap functions the way you want (including using cycle.js). The only constraint is that S, vm, A and nap are pure functions. The structure of the pattern is aligned with the semantics of TLA+, so even if you don't use an explicit state machine, you end up structuring your code in a way that's aligned with TLA+.

That being said, the semantics of cycle.js are incomplete from a TLA+ perspective. When that happens, people end up reifying lots of concepts behind streams and that does not look pretty.

I am certain we'll speak one day about being TLA+ complete, just like we talk about being Turing complete. TLA+ provides a strong foundation to computing that it is difficult to ignore, now mater how cool something looks in a given context.

Business Components as alternative as MVC by Javier Paniza

Business Components are just to solve the problem stated at beginning of the article. MVC is just a way to organize the code, Business Component is just another, but more useful when the data structures change a lot and the technological layers not.

Framework Fatigue by Paul Rogers

SAM looks to be the answer many developers have been looking for, as the list of frameworks grow we all need to take a step back and look at the methods rather than jumping on the bandwagon with yet another Superheroic JS Framework. Joined the gitter channel for more insight gitter.im/jdubray/sam
May the SAM be with you....

Re: cycle.js by Paul Rogers

Great example on codepen, cycle.js is new to me so this is a great starting point.

Re: Framework Fatigue by Jean-Jacques Dubray

Yes, its amazing to be able to write code without a "straightjacket". With SAM you stay 100% in functional JavaScript, no additional syntax to learn, no library. Compare that to Angular2...

Re: Redux by Jean-Jacques Dubray

yes, agreed, that being said, Redux is promoted as an alternative to flux. Not sure where Dan picked the state machine semantics of Redux, but they are not that "predictable". When it comes to state and action, TLA+ offers a much more robust formalism. That's where SAM draws all its power from. I suggest people who use Redux switch to SAM, they'll avoid this unnecessary coupling between the actions and the model in the reducer.

Gitter by Jean-Jacques Dubray

There is an interesting discussion going on Gitter, if you are interested to learn more about SAM. We share code samples and implementation models (e.g. how to implement SAM with Cycle.js / RxJS).

I created several rooms to discuss the different aspects of the pattern and share some code samples.

sam-state-view: discuss V = S(M) how front-end developers write their code
sam-apis: how back-end APIs fit within the pattern (actions and model)
sam-actions: A()
sam-model: M (M.present(), vm(), ...)
sam-examples: general discussions about examples such as the rocket example
sam-archtiecture: general deployment / topology, composition discussions

Another examples using Node.js, Cycle.js and RxJs by Jean-Jacques Dubray

This is another example based on the SAM pattern, this time using node.js

bitbucket.org/snippets/jdubray/jna7B

Some readers have also started creating samples using Cycle.js and RxJS, I will try to collect all the samples in that gitter room.

Easier to use React and GraphQL by Ashley Aitken

Very interesting post, thank you. I haven't had time to take it all in yet but there are a couple of comments I would like to make:

1. Sure React may just be equivalent to a pure function call but then it may be easier to use React / JSX to make components explicit, clear etc. It's more specific to the task at hand rather than a general Javscript function (if you know what I mean).

2. I'm still not convinced about the lack of a need for GraphQL. If all the front-end developers could just write Javascript functions and conceptualise what they were doing that would be great, but perhaps GraphQL is a simpler way to "write the functions."

I'm also not sure about getting away without a VirtualDOM but I haven't had time to follow that link you suggested.

Thanks again, and I hope my comments make sense.

Cheers,
Ashley.

Re: Easier to use React and GraphQL by Jean-Jacques Dubray

Ashley,

these are all great questions, and I can only encourage you to try the pattern for yourself.

They are actually fundamental questions because they have massive implications on the cost of building omnichannel solutions (which is the context in which this post was written).

I have started to share some of the code I write these days, to demonstrate that indeed you do not need React/Angular, GraphQL or even the VirtualDOM. There might be some apps where these technologies could add value, but on a day to day basis, I don't need any of them.

SAM allows the designer and front-end developer to have a much cleaner separation of concerns and consequently a much better working relationship. The semantics of Frameworks like React/JSX or Angular collide with the simplicity and elegance of HTML5/CSS3.

The reason why SAM changes everything is because the view is limited to be a "State Representation", there is never a need to go beyond "rendering the view", all the application logic stays in the SAM loop. That is why SAM is new and different. If there was ever a need to have a slightly more dynamic behavior, SAM's composition (fig 9) would again keep the application logic completely separate from the view.

Template technologies (including JSX, though in React you essentially create functions, so it depends how you use JSX, as a template or as a function) are simply the wrong technology because they severely limit your ability to create meaningful webparts from the model, while requiring the model to match the shape the template. Functions on the other hand deliver all the power of imperative language to render the view properly, without requesting the model to fit the view.

This is also why you don't need the virtual DOM, simply because you know exactly what will change in the view. Again, I don't dispute that there might be a few cases where the virtualDOM add value, but these cases are very limited. SAM gives you the ability to make decisions and optimizations from the model. Trying to optimize at the HTML element level is interesting from an engineering point-of-view, but again, unnecessary.

Last but not least, “Client-specified queries” are an absolute anti-pattern in Reactive architectures. The whole point of SAM is to achieve the best decoupling possible between the view and the way the model is formed (fig 7). By design in SAM, the view cannot request anything. It can only initiate reactive loops. When the loop ends, a new view is produced (figuratively, based on my point about the virtualDOM). Nothing else can happen in the view at all.

I can only encourage you to write some SAM-based code yourself, you will see how different it is and why you don't know need any of what React/Angular have to offer (again, in the context of building OmniChannel solutions).

Elm Architecture by Johannes Staffans

This post reminds me a lot of the Elm architecture, which has recently seen a lot of traction in other languages as well (redux as you mentioned and re-frame in ClojureScript).

Do you see any key differences between SAM and the Elm architecture?

Re: Elm Architecture by Jean-Jacques Dubray

Yes, there is a small, albeit important difference.

As André Staltz explains it, I believe there is a general agreement to "separate the logic from the effects". There is also a broad interest in our industry around reactive/functional programming models. React, Cycle.js, ... have showed that there is huge value in that approach.

With that in mind, if you construct a reactive loop such as Model Update View (or MVI), the assertion:
The logic of every Elm program will break up into three cleanly separated parts: model, update, view

That assertion is erroneous. You would be missing a couple of important parts:
- the logic that decides which state you are in so you can properly compute the view and enable the actions associated to the state
- the next action predicate

One can achieve a much better decoupling between the view and the model by introducing the concept of State to hold that kind of logic, otherwise you would have to fit it either in the view or in the model. The concept of "State" is critical to achieve that decoupling. The view then becomes a pure state representation, and hence a pure function of the model.

I didn't make up these semantics, they are coming directly from TLA+. TLA+ is used at Amazon to correct the most complex defects in AWS.

As a side note, some people like to call "control state" what I call state and they prefer using the word "state" to describe the content of the model. For me a model is just a set of property values with rules that decides whether some values are acceptable or not. The Model does not know anything about actions and state. Above the model, there are the (control) State and the Actions. Below is the usual CRUD to data stores. Above the (control) State and the Actions is/are the State Representation(s) (say in the REST sense, but not from a Resource-Oriented point of view).

So, it is not enough to break up the logic in just Model,Update,View. If people like André, Dan, Evan and others could engage in a meaningful conversation, about that very point, I believe our entire industry could make a major step forward.

None of what I am saying would break Elm, Cycle.js or Redux, an alignment with SAM would make them a lot stronger.

Re: Redux by Sam Havens

Hmm, would you help me out? I read the article again, but I am still at a point where I am much more clear on Redux than SAM. What is the coupling between model and action in the reducer - that the reducers and state are both part of the store?

Also, I don't think Flux was a reaction to people building complicated apps with React - I think Flux architecture and the idea of the universal data flow predate React at Facebook. Not certain, but that is the story I heard.

Re: Redux by Jean-Jacques Dubray

Sam,

you are referring to the discussion I had on the ngrx/store list?

The argument I developed there is pretty simple, I tried to boil it down to a simple example: let's say you trigger an action that increments a counter, all I suggest in SAM is that you factor the code in two steps:
a) an action (a pure function) hat given a dataset computes the proposed changes to the model
b) a method that mutates the model

The Redux reducer looks like this:

case INCREMENT:
return state + 1;

All I am saying, you need to write an action increment:

function increment(data) {
data.counter = data.counter || 0 ;
data.counter += 1 ;
return data ;
}

and then present the new value to the model which will choose to accept the proposed values:

model.present = function(data) {
if (data.counter !== undefined) {
// can have some validation rules that decides whether
// that value is acceptable or not
model.counter = data.counter ;
}
}

In SAM the actions and the model updates are strictly decoupled, unlike Redux which encourages people to create a big ball of mud, for no particular reason, other than Dan using a naive interpretation of state machine semantics.

With SAM, actions are external to the model and as such can be reused across models and even implemented by third parties. In Redux, actions are merely intents. The implementation of the action is in the model (reducer). That is wrong.

Please note that the way Actions are structured in SAM (expressed as a transformation) make them composable as a pipeline:

model.present(A(B(C(data))))


All I am suggesting is to move the action logic outside the reducer, the reducer keeping its role to mutate state. The same "reducer" logic would then work just as well with different actions (incrementByN).

We will not get out of MVC as long as the controller will update the state. Redux is a big step back.

About Flux, my comment was just regarding the fact that React is considered to be "just the view" and something was needed for M and C. Flux has some great ideas but completely missed the model part. Redux came around but completely missed the action parts. Both of them are however missing the "state".

For SAM, I am not claiming anything other than I applied battle tested, Turing award winning, decades old TLA+ semantics to front-end construction.

Thank you by Michael Terry

Truly brilliant. This simple formalization is precisely what I've been searching for. I need to concretize it by doing some code studies, but the broad strokes excite me.

Re: Thank you by Jean-Jacques Dubray

Michael, thank you so much for your comment but I didn't do much, I just slapped React and TLA+ together, which are both *truly* brilliant.

Once you start coding that way you'll be amazed at what you can accomplish. Feel free to join us on Gitter, there are some great discussion going on.

I started to produce some public code samples as well to show how it compares to React/Redux and Angular/Rx, and why most people don't need either.

Several readers already came forward to create some samples with their favorite framework (cycle.js, vue.js,...). Cycle.js looks promising and shares some of the same goals: separating the logic from the effects.

Re: Thank you by Michael Terry

This is being discussed here:

news.ycombinator.com/item?id=11104356

...by the way.

Native UI by Michael Donkhin

First of all, thanks for the great summary. It is a long time since I've started thinking about state localization in UI. Most of the frameworks we have to deal today spread the state among the components which results in endless bugs and virtual inability to introduce sane multitasking.
I believe, your approach could solve many of these problems.
However, I would like to ask you about how do you see implementation of SAM using native technologies (Android, WPF, Cocoa, etc.) and not WEB-based ones. You extensively use generating the View part using HTML templates, but in most of the native frameworks generating the view is either impossible or very expensive; and in those which do support such a thing (WPF data templates) the usage does not exactly align with proposed paradigm.

This is because MVC is misunderstood by Andreas Söderlund

It happens time and again, another pattern from the programmers perspective, when MVC really is much more than a pattern, and it includes the users perspective. I've made an attempt to clarify what MVC is really about. I appreciate if you read it: github.com/ciscoheat/mithril-hx/wiki/Rediscover...

Re: Native UI by Jean-Jacques Dubray

Michael,

thank you for your comment. We fully agree, state is the problem (and React is one of the worst offenders)
Most of the frameworks we have to deal today spread the state among the components which results in endless bugs and virtual inability to introduce sane multitasking


and, yes, I also believe that SAM can completely change the game in Front-End construction, by bring back some sanity in that space. When you watch this video detailing the best way to build a React app, you understand very quickly that you are much better off staying away from it, and my guess is that it's true of Angular2 as well. It took me nearly 10 minutes on my mac to run npm install of the ngrx/core Item management sample (add/change/delete items to a list).

Just a few words about the work I have done in the mobile space, five years ago I built a model driven cross platform (iOS, Android) development platform called Canappi. So I know a thing or two about code generation. (the project is now open source, but not worth using, it's just too far behind).

As I mentioned in prior comments, one of the key benefits (and focus) of SAM is to clearly separate the logic from the effects as André Staltz puts it when he describes Cycle.js. That means that in theory (because I have not written some native code yet) the function V = f(M) can run in the native mobile client. You'd have to optimize how the reactive loop returns parts or all of the model. Not every application has the footprint of Facebook, so it's not such a burden do to return the whole model each time and let the view function pick up what it needs.

I don't know about the Swift programming model, but in Objective-C, that function would be equivalent to instantiating a view controller from the model (my preference would be to keep the model as parsed JSON rather than strongly typed classes):

MyViewControllerClass *vcInstance = [MyViewControllerClass newFromModel:model]
[self.navigationController pushViewController:vcInstance animated:YES];


The core of the implementation would be in the viewDidLoad method.

I do disagree with your statement:
the native frameworks generating the view is either impossible or very expensive


Again, I wrote Canappi, so I know a thing or two about code generation. In any case, you don't really need to "generate" anything, this is more parameterization of the view. You don't have to completely change the paradigm to start implementing SAM.

I used to be 100% native guy 3-5 years ago but because of the number of variants of form factors, I no longer think that Native is a viable model moving forward. I am doing some tests with Cordova + SAM now and so far so good.

Do you think that's a reasonable answer? Happy to review some code if you want to share a sample. Feel free to join us on Gitter.

Re: Thank you by Jean-Jacques Dubray

and here too... gitter.im/jdubray/sam

JJ-

Re: This is because MVC is misunderstood by Jean-Jacques Dubray

Andreas,

I appreciate that a number of people are emotionally attached to MVC and the work of Prof. Reenskaug. I met him briefly in 1999 at OOPSLA.

With that in mind, I believe that if no one understands MVC after 40 years, I believe that if Google engineers have been flip-flopping on Front-End architecture for the good part of the last 15 years, it is because, MVC, in essence, does not exist, its semantics are so weak that it leads to code that no one can write, no one can debug and no one can maintain. MVC creates "run away" systems where the only answer to system construction is always to create more views, controllers and models.

I understand how much of a breakthrough MVC was in 1978, but we are in 2016, things have changed and taking the perspective of the user into account is no longer enough, you also need to include his/her friends, his/her smart watch and the uber driver approaching to pick him/her up when designing a "user" interface. SAM takes into account all these point of views.

Again, Apologies to Prof. Reenskaug, but MVC needs to go. There is no point in keep it, everyone understands that but there has never been a viable alternative. If SAM is not the answer, then another one will come.

String literals are our worst anemy by Remo Jansen

I can see that being straight away being not better than React for multiple reasons (all of them caused by string literals):

• Strings cannot be compressed by JS compressors so an application like that would be much heavier than one done with Virtual DOM
• Strings cannot be parsed by a compiler (like TypeScript) or the JS runtime so if we forget to close one of those </div> elements we will not have fun trying to find where is the error.

Re: String literals are our worst anemy by Jean-Jacques Dubray

SAM is a pattern not a library.

I can choose to implement the pattern as I wish. I personally prefer a "raw" style of implementation, I tend to be see no particular value in all these frameworks. I would, again, as a personal preference, trade any day the ability for a framework to tell me I forgot to close a div to an npm install that takes 10 min to run on my Mac.

I am a server side guy, so compression means gzip/deflate not min.js.

Re: String literals are our worst anemy by Jean-Jacques Dubray

Apologies, the link was not correct, here is the link to the sample that took me 10 min to install on my mac.

Re: SAM pattern and building tools by jiten oswal

Hi, Great article. Some of the stuff you explain here do convince me to try it out. Can you share the node.js code sample with me as well ? I would also like to check them out and give it a shot :)

Thanks

Re: Another examples using Node.js, Cycle.js and RxJs by jiten oswal

Jean, I guess someone might have already suggested it but it would be great to start a blog with more articles and code examples along with stuff you try to assemble from and to different gitter rooms :)

PS: I just added myself to 3 different rooms of yours related to SAM and information there looks hard to parse and catch all that's important :)

Re: Another examples using Node.js, Cycle.js and RxJs by Jean-Jacques Dubray

Yes, ... I also have to make a living... but yes, you can expect that I will produce more code samples, and as far as I am concerned there is no turning back.

With respect to node.js there quite a few samples available:
- bitbucket.org/snippets/jdubray/jna7B/sam-sample...
- www.ebpml.org/blog15/2015/06/designing-a-reliab...
with the code available here:
bitbucket.org/jdubray/star-javascript/src/58062...

STAR is a small library that implements the pattern, but is not required for the implementing the pattern.

Virtual DOM & React Native by Rob Tweed

VERY interesting article. I shall be digging into your code and ideas for sure. The one thing I'd flag up about the virtual DOM in React.js is that it has made mobile app development in JavaScript possible using the exact same techniques via React Native. To me, this is the real killer benefit of React. Do you think a JavaScript-based SAM Native would be do-able?

Re: Virtual DOM & React Native by Jean-Jacques Dubray

Rob,

thank you for your comment. I would say it depends the type of application your are building. I didn't say you'll never need it. I understand it's value and respect the engineering behind it, but I would argue that today React is out-of-control (and Angular too). Facebook has taken a great idea and completely wrecked it. Is this really what it takes to write a Web app? One of my goals in the article was to reset the clock and show that you can build great web apps with raw JavaScript, HTML5 and CSS3. I am sorry that it came across as "you shall never use these frameworks again".

From what I can tell, I would say it's doable to use Cordova + SAM, I actually built a PoC last week for client. Looked great. When the "diff" is on the order of the content of a div element, I am not sure you need it. SAM creates the state representation at the end of the reactive loop (like React), so you are not touching the DOM several times. Is the virtual-dom working so well because of the diff algorithm? or because you apply all the changes at once?

Re: Virtual DOM & React Native by Rob Tweed

Actually I agree with you - I've been working with web apps since the mid-90s and even then despaired at how there seemed to be an overwhelming desire to make it all a lot more complicated than it actually was or needed to be. So I really like your approach and the thinking behind its concepts, and I'll definitely be digging into it in more detail over the coming days.

The thing I do like about what Facebook did with React Native was realising that mapping the virtual DOM to the native iOS UI components was possible, allowing a truly native app to be created just using JavaScript (as opposed to a hybrid app using Cordova). Otherwise we're on the same page! :-)

Re: Virtual DOM & React Native by Jean-Jacques Dubray

Rob,

I don't dispute the fact that this is possible and it works well/better than Cordova, as I mentioned in an earlier comment, I built Canappi a few years back which generated iOS and Android code for up to 5 form factors, so I can imagine Facebook can do a much better job than myself.

That being said, what you need to consider is that developers and architects have a tendency to ignore state (as in SAM state, not Redux state with is SAM's model). The reason is because they are used to build monolithic architectures where the server-side code always acts as a safety net for whatever the client is trying do, this is a recipe for disaster when building composite/omnichannel applications where the APIs’ state machines cannot easily be aligned with the solution’s state machine, since they are built by different teams or even third parties.

That's why "State" needs to be explicit in the Front-End Architecture, and hence SAM, otherwise we'll be heading for a big big mess (I believe we already have). I agree with people that say State Machines are too heavy to write code and that's why SAM provides an interesting compromise, you can reason about State without having to result to a state machine systematically.

React or any MV patterns, especially the ones that start with MV has some inherent difficulty dealing with state because you can only infer the (control) state once the model has been fully mutated as a result to applying an action. Instead of "View" people should start adopting the language of "State Representation", that would change a lot of conversations.

I was reading this article this morning on Angular 1.5 and it shows everything that's currently wrong with Front-End architecture in 10 lines of code (databinding, templates, Google even thinks it's cool to attach the model to the controller? no... state):


// usage: <name-component></namecomponent>
var NameComponent = {
bindings: {
name: '=',
age: '='
},
controller: angular.noop, // or function () {} whatever
controllerAs: '$ctrl',
template: [
'<div>',
'

Name: {{$ctrl.name}}

',
'

Age: {{$ctrl.age}}

',
'</div>'
].join('')
};

angular
.module('app', [])
.component('nameComponent', NameComponent);


SAM, of course, is agnostic when it comes to how the state representation is rendered, so you can use React Native, Angular, or your own...

sigh...
</name-component>

GitHub Pages by Jean-Jacques Dubray

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

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 by Jean-Jacques Dubray

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

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 by Jean-Jacques Dubray

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

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 by Jean-Jacques Dubray

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

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 by Jean-Jacques Dubray

>> 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 by Jean-Jacques Dubray

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 by Tudor Gergely

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 by Jean-Jacques Dubray

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... by Arturo Hernandez

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 by Othon Reyes Sanchez

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 by Jean-Jacques Dubray

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 by stefan houtzager

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 by stefan houtzager

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 by Jean-Jacques Dubray

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'? by Nicolas HUGODOT

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 by stefan houtzager

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'? by Jean-Jacques Dubray

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

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.

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

Email me replies to any of my messages in this thread

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

Email me replies to any of my messages in this thread

68 Discuss
General Feedback
Bugs
Advertising
Editorial
Marketing
InfoQ.com and all content copyright © 2006-2016 C4Media Inc. InfoQ.com hosted at Contegix, the best ISP we've ever worked with.
Privacy policy
BT

We notice you're using an ad blocker

We understand why you use ad blockers. However to keep InfoQ free we need your support. InfoQ will not provide your data to third parties without individual opt-in consent. We only work with advertisers relevant to our readers. Please consider whitelisting us.