Enter Your Email Address to Watch This Lesson

Your link to unlock this lesson will be sent to this email address.

Unlock this lesson and all 833 of the free egghead.io lessons, plus get RxJS content delivered directly to your inbox!



Existing egghead members will not see this. Sign in.

Just one more step!

Check your inbox for an email from us and click link to unlock your lesson.



Model-View-Intent pattern for separation of concerns

3:17 RxJS lesson by

We built the BMI calculator all inside one function: main(). As apps scale, we don't want main() to grow. We need an organized pattern where each function focuses on doing one thing. This lesson shows how we can easily refactor the main() function into three parts: Intent, Model, and View.

Get the Code Now
click to level up

egghead.io comment guidelines

Avatar
egghead.io

We built the BMI calculator all inside one function: main(). As apps scale, we don't want main() to grow. We need an organized pattern where each function focuses on doing one thing. This lesson shows how we can easily refactor the main() function into three parts: Intent, Model, and View.

If we continue to build our applications in the same manner we built the BMI calculator, we will start seeing the main function growing. I prefer usually small functions that do only one thing. Now that we have this rather big main function that does more than one thing, how do we refactor this? Notice that we have three distinct parts, we have the read effects from the DOM, we have state and logic management, and we have the write effect. Plus everything is just class declarations.

So it turns out we can extract each of these parts and put them in functions, like this part can go into a function let's say called part1, and then we can return an object to contain both of these streams. Then we have part2 which will return the state stream, that part. Then we have finally part3 to return the virtual DOM tree of elements as stream, like that. Each of these three functions expect parameters like this one wants sources.dom.

So let's give it there, let's call it DOMSource, it's just an object that we can give and replace these. Part1 seems to need no other parameters, so let's look at part2, it wants changeweight stream and changeheight stream, and part3 needs the statestream. So now we can use those three functions in main, we can remove this old parts, we want an object with changeweight stream and changeheight stream when we call part1 given sources.dom.

Then we get the statestream by calling part2 given changeweight stream and changeheight stream. Then we get a stream of virtual DOM trees that's what you call a vTree stream, we call part3 given statestream. Then we just give the vTree stream as the DOM sync and our app still works. But part1, and part2, and part3 are quite bad names, let's try renaming this starting from the easiest one. While this one takes state and it returns these elements, so this really looks like what we commonly understand as view.

Then part2 is just handling state management, so this is called model because it's not really related to any effects, right it's just state and logic. Part1, well, is handling read effects from the DOM, it's essentially getting raw events from the DOM, and it's interpreting what the user wants to do. I'm going to call this one intent, so we just need to rename down there as intent, model, and view.

Our app still works, and this is what we call the model view intent pattern, which is meant to organize this type of sandwich interaction. Now our main does one thing, it converts from sources to syncs and it does that by calling these three functions in succession.

HEY, QUICK QUESTION!
Joel's Head
Why are we asking?