Facebook: MVC Does Not Scale, Use Flux Instead [Updated]
This article has been updated based on community and Jing Chen (Facebook)’s reaction. (See the Update section below.)
Facebook came to the conclusion that MVC does not scale up for their needs and has decided to use a different pattern instead: Flux.
During the recent F8 session Hacker Way: Rethinking Web App Development at Facebook, Tom Occhino, Engineering Manager at Facebook, said that for their “sufficiently” large codebase and large organization, “MVC got really complicated really quickly,” concluding that MVC does not scale. The complexity of the system went exponential every time they attempted to add a new feature making the code “fragile and unpredictable.” This was becoming a serious problem for developers new to a certain codebase because they were afraid to touch the code lest they might break something. The result was MVC was falling apart for Facebook.
Jing Chen, Software Engineer at Facebook, added that MVC is good for small applications, but the complexity explodes when many models and their corresponding views are added to a system, as shown in the following slide:
Such an application would be difficult to understand and debug especially due to the possible bidirectional data flow between models and views, according to Chen, proposing instead the following Flux design:
The Store contains all the application’s data and the Dispatcher replaces the initial Controller, deciding how the Store is to be updated when an Action is triggered. The View is also updated when the Store changes, optionally generating an Action to be processed by the Dispatcher. This ensures a unidirectional flow of data between a system’s components. A system with multiple Stores or Views can be seen as having only one Store and one View since the data is flowing only one way and the different Stores and Views do not directly affect each other.
Facebook’s React page on GitHub explains Flux, Dispatcher and Stores in more detail:
The dispatcher is the central hub that manages all data flow in a Flux application. It is essentially a registry of callbacks into the stores. Each store registers itself and provides a callback. When the dispatcher responds to an action, all stores in the application are sent the data payload provided by the action via the callbacks in the registry.
As an application grows, the dispatcher becomes more vital, as it can manage dependencies between stores by invoking the registered callbacks in a specific order. Stores can declaratively wait for other stores to finish updating, and then update themselves accordingly. …
Stores contain the application state and logic. Their role is somewhat similar to a model in a traditional MVC, but they manage the state of many objects — they are not instances of one object. Nor are they the same as Backbone's collections. More than simply managing a collection of ORM-style objects, stores manage the application state for a particular domain within the application.
What is important, said Chen, is for the data layer to complete its update of the view before any other action is triggered. The Dispatcher can be made to reject actions while it has not finished processing a previous action. This design is especially helpful for actions that have side effects such as updating other views, making the code more clearer, easier to understand and debug by new developers. Flux helped Facebook eliminate a chat bug that informed users they have a new message when it was not the case.
While Facebook can use any design they seem fit, a question remains. Does MVC scale or not? After all, there are many websites out there that scale.
Update. After publishing this article, many developers have commented on Reddit regarding Facebook’s take on MVC. Here are some of the comments, some considering that Facebook is misusing MVC in the first place while others considering they are doing the right thing:
This doesn't make any sense.
For one, their MVC Graphic is insanely flawed. They are depicting a single controller to handle multiple models, when you'd almost certainly want to separate out controllers based on either what model they interact with, or other logical divisions.
Of course a setup like what they described wouldn't work, but it isn't really MVC either.
If you compared their flux diagram to an actual MVC diagram like this you'd get a much clearer picture that there's nothing inherently wrong with MVC for web apps.
And... here's the thing... their diagram for Flux very closely resembles your MVC diagram.
They're re-invented actual MVC, and decided to assign a new name to it. Aaargh!
It seems that this architecture is shifting MVC to something that looks event-based. "Stores" register themselves (and presumably any call-order dependencies) with the dispatcher, and the dispatcher processes actions and ensures that the correct chain of calls are made. This moves the burden of ensuring proper call-order from controllers to the dispatcher and store. This should reduce the necessary comprehension to modifying behavior.
My takeaway from just glancing at this, although I don't think I understand it particularly well yet, I think I understand and agree with the the general idea.
The Reddit user jingc09, who seems to be Jing Chen based on her comments, added some replies:
jingc09: Yeah, that was a tricky slide [the one with multiple models and views and bidirectional data flow], partly because there's not a lot of consensus for what MVC is exactly - lots of people have different ideas about what it is. What we're really arguing against is bi-directional data flow, where one change can loop back and have cascading effects.
She also tries to clarify the fact that Flux’s Dispatcher is not an MVC Controller:
One thing I want to clarify is that the dispatcher doesn't play the same role as controllers. There's no business logic in the dispatcher, and we use the same dispatcher code in multiple applications. It's just a central hub for events to reach interested subscribers (usually stores). But it's important in Flux because that's where the single-directional data flow is enforced. …
In commenting this Wikipedia explanation on MVC Controller:
A controller can send commands to the model to update the model's state (e.g., editing a document). It can also send commands to its associated view to change the view's presentation of the model (e.g., by scrolling through a document).
A dispatcher cannot do any of that, the commands have to start from somewhere else (views, server responses, live updates) and pass through the dispatcher. https://github.com/facebook/react/blob/master/examples/todomvc-flux/js/dispatcher/Dispatcher.js may help illustrate this.
Based on the Reddit comments, there seems to be some confusion on what MVC is and how it should be implemented.
Regarding Facebook’s take on MVC we have two observations:
1) The first slide seems really blown up with too many models and views, making one wonder if there is something like that in the real life. The problem that Facebook addressed with Flux was the chat app which had 3 views.
2) Why is View generating a data flow creating thus the bidirectional flow in their MVC example? And why is View generating an Action in the Flux diagram? A View shouldn’t generate anything. A View is just a "view", nothing else. Is Facebook misusing MVC?
It's no suprise Facebook deems MVC unscalable.
They're on to something
How does Flux scale?
- enabled/(assigned)/disabled (not all tasks can be performed at any time)
MVC offers no relationship to the underlying tasks and their lifecycle. All task boundaries and lifecycle need to be coded within controllers, the views and to a certain extend the models. That's what's not scalable in any way when you use MVC. Your code explodes with task boiler plate code and becomes unmaintainable very quickly because of its stateful nature. Hence, I am not sure Flux solves anything with that regard.
MVC is not for everything
We all may know that a view, once triggered a specific action, may have two major possibilities:
1. To update some UI elements locally, without any interaction to the backend; or
2. To perform necessary interactions to the backend which definitely will go through another typical processing, like controller->model->view, or the equivalent.
We may have found that in the Facebook version of diagram, the view is pointing to the action (controller?) and redirecting to the model (ok, they rename or redefine another misleading concept here, say store). That's exactly the process of abovementioned #2.
In short, Facebook is misleading the readers by a wrong MVC diagram but trying to illustrate why Facebook is right by sharing right MVC diagram with "proprietary" diagrams and concepts.
Is it the right way for a giant company like Facebook should go?
When the code samples came up the immediate problem appeared to be high coupling where a single handler tried to juggle too many views/models.
An event-based de-coupled approach is what large applications require. In that way even highly cohesive, isolated MVC structures (or anything really) would shine.
But the fact that they fixed their coupling and then decided to attribute the success to a 'new' architecture does seem somewhat weird. Change 'dispatcher' to 'controller' and 'store' to 'model' and you have a flavour of MVC.
So what *does* seem to scale is 'experience'.
MVC is an architectural pattern, not an implementation
MVC / OOP is not for the web.