From MVC to Flux

Guy Nesher speaking at JS Monthly London in July, 2016
495Views
 
Great talks, fired to your inbox 👌
No junk, no spam, just great talks. Unsubscribe any time.

About this talk

MVC is a well-established design pattern that is currently being challenged by the Facebook Flux architecture. In this talk, Guy Nesher covers the core differences, the reason for the change, and looks at one implementation of Flux using the Redux library.


Transcript


[00:00:04] My name is Guy Nesher. I manage the meetup and I’m also going to give you a talk about why and how we moved from MVC to Flux because I don’t know how many of you are using Flux or Redux and how many of you have watched the Facebook presentation that explains why they dislike MVC. If you have, you may have noticed that there are a couple of gaps in how Facebook explains everything, which I’ll try to fill. We’re going to talk a little about the MVC background, about the pattering itself. We’re going to talk about the problem with MVC and then I’ll give an introduction to Flux and Redux. I wanted to have a few more code examples but I don’t think I have the time, so we’ll have to keep that to a different talk. Let’s get started. Everyone has seen this before, right? MVC is something that I assume everyone is familiar with. We have three components: we have the model, we have the view, we have the controller. This specific example is from Wikipedia, which is fairly reputable source. What happens is that the user interacts with the view of the controller which updates the model which updates the view. We’ve got used to seeing this, except that if you actually try to Google for MVC in Google images, you’ll see quite a few other diagrams, like this one. [00:01:37] This is from the SAP website, again, fairly reputable, you’ll see that we have a new data binding here that didn’t quite exist, which means that the view actually updates the model directly, which didn’t really exist in the previously example. It’s a little bit strange, assuming that we’re talking about the same pattern, but then, of course, you can continue to look at other diagrams. Let’s start from the very beginning. I got this comic today and I had to share it because it fit quite well to the date. The MVC patent was first created in 1979, I think. I was trying to think about how examples of how Pokémon looked back then, but, of course, the Nintendo only came out about four or five years later. The first website came up in the 1990’s, so about more than ten years later. You can only imagine the fact that computer software back then was very different and needed to handle difference challenges than what we see today. It’s more than that, it’s the fact that when MVC was first created, it wasn’t technically called “MVC” it was called MVE because the controller was actually an editor. [00:02:58] You start to realise that things have changed over the years. MVC was designed with a very broad definition in mind, which is a little vague. I’ll take an example that hopefully everyone knows. How many of you have used Scrum before? Raise your hands. Most, everyone, I think. Scrum. Yes. How many of you have used Planning Poker when using Scrum, which is the fake poker cards that help you point up stories. Poker cards that most people use in Scrum isn’t really part of Scrum, it was never really defined as part of Scrum, it’s just the best practice that slipped in and most people are using it. Since most of us actually sat down to read about Scrum, we make an assumption that Planning Poker is part of Scrum. MVC is quite similar, so a lot of the practices that we’ve seen used by different frameworks aren’t necessarily part of MVC but have crept in because this is how we learned to use MVC. It doesn’t also help the fact that there’s quite a few variant of MVC online. MVVN, which is the most popular version for websites which is model view, view model. You also have MVP which is model view presenter and PM, which is Presenter Model. They all talk about the same thing. [00:04:30] We are going to focus on the main thing that is interesting for us and this is that MVC was basically created to ensure that there’s a separation of concern between the three core mechanics of the app: the view layer, the data layer, and the controller which does the thinking. This brings us nicely to the problem that Facebook has raised when they said they’re moving from MVC to Flux. This was showed by a guy named Tim Ochino during, I think, 2014, Facebook F8. They basically said that MVC becomes more complicated and less predictable the bigger the application becomes. To prove their point, they showed this. Now, the biggest problem with this diagram is that a, it talks about a very, very specific implementations of MVC, which isn’t necessarily correct, or at least not part of the core definition of MVC. It does highlight one specific problematic issue that MVC presents. While MVC is very good with a single component, or several components that work independently, as soon as you start to have interconnected components you start to create a cascading effect. Where a single change in a single component may affect multiple other components, and since every component manages itself, you have multiple handles, which makes basically two things that are highlighted. [00:06:13] The first thing is that it’s really hard to debug. If a single action generates ten faulty actions and you need to debug what caused the bug on the fourteenth jump, going back to the original action is nearly impossible. It’s generally bigger than the actual step that most puzzles will actually keep. The bigger problem is the fact that the number of components will affect the size of the chain. The more components you add, you don’t just make your app more complicated by that component’s size, you make it more complicated by the actual chain that’s added to that component. The way Facebook decided to solve this problem is by introducing a fairly new way of managing data, which is called, “The Flux architecture”. Now, the Flux architecture doesn’t look that different from the original MVC example diagram that I’ve shown you from Wikipedia but it does introduce a few key changes that we’re going to talk about. [00:07:30] The first change, sorry, I can’t see my speaker notes which is slightly more challenging. The first thing that the new Flux architecture introduced is a new dispatcher, which doesn’t really exist in the MVC framework. The dispatcher itself is a singleton, it’s a basic pub sub event aggregator that manages the data flow between the view layer and the data layer. It will save the actions from the view or an Ajax call and dispatch it to the store and then it also manages the dependency between stores. Now, there’s a little star there because Flux can be implemented in multiple ways and not all of them have multiple stores, but we’ll talk about that in a couple of minutes. The second concept which looks a lot closer to MVC is what SAP calls “stores”. If MVC has a model layer, Flux has sore layer. It sounds really similar except that with Flux you have singleton as stores, which means that you don’t substantiate one store per one component but instead have a single store that covers generally an entire domain. The sidebar is a store, not every line in your table. The second change, and that’s a big change, which solves a lot of the problems with MVC according to Facebook, is the fact that the stores themselves are in charge of modifying data and not each individual component. That means that the view layer introduces a change and ask the store to update the data. The store sits and calculates what this change will mean to the entire set of data for the entire application, and only when that entire change is done will it tell the view, “We’re okay, you can pull the new variation of the view”. [00:09:45] The last part, really, is the actions. The actions are very simple JavaScript objects. They have the delta, the change of the data that you want to implement, so if I want to change the name of a field, I’ll just pass in a field name and the stream. It also has the name of the action. The way the stores know what to do is based on the name of the action, the type of action that you’ve committed. It’s generally created by either views of object scores or anything else, really. Generally, asks corners. It has no logic, so it’s just a plain object that you pass to the store. Views aren’t really defined properly by Flux but what you’ve seen implemented, generally, with React is something called “a controller view” which means that the view also encompasses the basic logic that requires to operate the controller. This, again, can be implemented in quite a few different ways. Flux can be used with Angular, it can be used with Back Bone to various degrees. The views listens to the store change, so whenever a store is updated, the entire data has been updated. The view will know that an update has occurred and will pull the entire store data again. [00:11:16] We do not pull the delta of the change, we pull the entire data in, this ensures that we always start from scratch, basically. The entire component gets re-rendered and, again, this is why React solved this problem by making the comparison, but this means that you don’t need to actually handle specific deltas within the views. You just need to know that your view will actually know how to react to a completely new set of data. The views are also in charge of emitting actions to the dispatcher. Whenever a user makes an action, you don’t actually change data directly within a view, you just make a request to the dispatcher. Let’s talk about the Flux core concepts before we move to Redux. One-way dataflow is one of the main concepts that Flux tries to introduce. One-way data flow isn’t new to MVC but it is implemented slightly differently here, in the way that the individual components don’t actually access the data, or change the data directly. They have to always request the stores to do the update. [00:12:40] Flux prevents event chaining. If doing an update in the store, you try to trigger another dispatch, another change request, the dispatcher will break and tell you that you’ve committed an error. One of the main things that Facebook has tried to prevent using Flux is these chain actions. Again, the entire state of the applications is resolved within the stores before you fire an update and the data manipulation only happens in a single place, versus having multiple component, each one determining how data is manipulated. Now, the way Facebook decided to launch Flux is a little funny. First, Facebook released React, which was originally created to accommodate a new framework called “Flux” but they released Flux a little while later. I think Flux initially had two pages of documentation and no source code. They slowly added a very small library and gave a talk and a half before abandoning Flux altogether. You have an official Facebook Flux library. It’s really nice to play with it to understand core principles of Flux but it’s also completely unusable in live applications, so I’d avoid it if I were you. Simply because it requires a lot of boil plate. There’s around 20 other implementations that people have created over the years. Quite a few of them are nice. I think the one that’s been dominating the markets for the past year plus is Redux, which has a slightly different take on the original Flux architecture and we’re going to go over the basic components using Redux, simply because it’s probably the best way for you to start experimenting with Flux. [00:14:35] This is the Redux architecture, which is kind of similar to Flux but also has a few changes. If you look, the view and actions are exactly the same as Flux but we can see that the dispatcher has been attached to the store itself, and that the store has something called “reducers” that had not been part of the original Flux implementation. Let’s go over these new components and see how we create them and what they do. The three main changes again, data manipulation moves outside from the stores and inside something called “reducers”. This makes your apps more easily maintainable and makes the store a very simple object that only stores data. The other thing that Redux does is moving the dispatcher within the store, simply because they only have a single store that’s a singleton. The dispatch was a fairly thin component to begin with. Then the view and action remains the same. We’ll start by looking at the Redux store. As I said, there’s a single store, you have one humongous JavaScript object that holds all the data for the application. It looks a little scary when you think about it initially, but since most of the data there is referenced and is kept between changes, it performs quite well. It encompasses the dispatcher and it has three main functions. You have the create store, which accepts the reducers, the functions that actually manipulate the data. It can optionally also accept initial data, which is data you get generally from the server, so if you load the user’s details in advance, you can prepopulate your stores with whatever settings the users chose. Again, this is an optional variable. [00:16:43] We have the store subscribe which actually informs the view layer when they need to render, so multiple views will subscribe through that. You have the store dispatch which basically allows the views to update the store, or request the store to update itself. The reducers are where the actual logic of the entire app resides. If the stores are a very simple JavaScript object with a little bit of event telling and the view is something that you control however you want because Redux doesn’t really care. Reducer is where you actually take the changes and implement the logic. Now, reducers are something that’s called “pure functions” which comes from function programming which is, if you haven’t heart, the best thing about JavaScript and we all need to use it until about a week from now when the new best thing will come out, and we’ll forget about function programming altogether. For now, the idea is that functions don’t mutate state. Instead of using object classes or object prototypes and manipulating the data within an object, you have functions that receive a state and return a new state without actually making any changes to the data. More importantly they have also no external dependencies. The best example I always use is data time. [00:18:20] If your function relies on time which changes between every call, your function isn’t pure because it will give different results based on the time of day we actually made the call. You want the function that will only return the same data when it receives a set of fixed data. If you want to look at a simple example of a reducer, this is from the Redux website and you can see how we get two simple actions and a default. I’ll highlight a few important things. You always need to have a default state. You can see that in the function to do state equals an empty array, so this is a new edition that allows you to prepopulate, giving a default value to variable. If you don’t want to use it, you can have an “if” state is undefined and you can populate it there. The switch is something that people don’t really like but it existed within Flux before Redux. This entire thing used to exist within the Flux store and was simply pulled out and placed within a separate function called a reducer. As you can see, it basically matches the action with the types of action that you support and then triggers whatever computation that you want to do and returns to a new state. This is important. You do not want to modify the existing state that you got with the reducer, you want to return a new one. I see a lot of people make these mistakes because a lot of JavaScript methods that you get with array, like array.push actually manipulates the original set of data and doesn’t actually return a new set of arrays in that case. [00:20:20] To avoid that there is an excellent website, I didn’t add the link, that tells you how to replace all of these functions with your own solutions that are non-destructive. You can also use something like low dash or underscore that does it quite well. It’s also worth noting that even if you modify the data and return the existing store, Redux isn’t really going to break. They don’t enforce it but it hurts performance quite severely, especially if you’re using React. There might be some odd side-effects because Redux and React have a more difficult time to detect that the change happened when you change an object versus return a new one. Finally, you always need to have a default action because if someone forgot to actually implement this new action that you’re sending, you don’t want the app to break, you just want to ignore it and return the same object. We generally have a cancel log or an error being deported here just so we’ll know that there’s a problem. [00:21:36] Having reducers is really amazing because you took the logic out of the stores and you can now have a much more modular application, but having all the logic inside a single humongous reducer isn’t really a great idea. The way that Redux allows you to solve this is by using something they call “combined reducers” which basically creates a new reducer that knows how to send actions to an object of different reducers that you’ve created, based on their keys. If you have data manipulation on something called “to dos” like the previous one, it’ll know how to do the matching and will automatically pass actions that are relevant to that reducer automatically. It makes the app much more manageable and you don’t actually need to do anything to use these combined reducers. It comes automatically with Redux. To show how this all works together, again, I’ve stolen this because it was just so nice. As you can see, a user clicks on a view which creates an action which comes to the dispatchers. The dispatcher passes both the action and a new copy of the state to the reducer and that creates a new state. Happy? Ish. [00:23:23] Let’s talk about a few other things and then wrap it up. The creator of Redux has created 30 amazing videos that explains how to practically use Redux. This is probably the best source of tutorials you can find online. I know quite a few people avoid videos because they take longer but if you have time, however slow it takes, to go through most of them, I highly recommend it. It also goes through how each one of the components within Redux have been created. Redux comes with a built in React integration. I didn’t really cover it because it’s been used much more broadly than just with React and I didn’t think that’s the best way to introduce the framework. While you can use Redux with object scores, there’s nothing that prevents it. Everyone uses a helpful library called, “Redux sunk” that’s making asynchronous calls with Redux much simpler.