If we continue to build our apps in the same manner we built the BMI calculator, we will see the main function growing. It's already quite big. I prefer usually small functions that do only one thing. How do we refactor this? Notice we have three distinct parts.
We have the re-defect state management, and the right effect, and also everything is just a const declaration. We can extract each of these parts and put them in functions. We can make part1 function to keep these change streams, and then we can return both of them under an object here.
ChangeWeight stream and changeHeight stream, and then part2 will return the state stream. We can call this function part2, and it will just return the stream. Then part3 finally will contain the virtualdom stream, and we return that as well. As you can see these functions probably need parameters.
It uses sources.DOM here in part1. Let's give that as domSource, and that's what we use here for defining those streams. Then the state management part will need these two streams. Let's call them actions. That's an action object from which we can get the changeWeight$ and the changeHeight$ from actions parameter.
The third part here needs the state stream obviously. I think those three functions now have all of their arguments. Now we just need to call these functions from the main. First I'm going to call the part1 given sources.DOM, and that should return to us the object that has those two streams.
I'm just going to call that actions just like we had as argument for part2, and then we just call part2 giving those actions, and we know we get out the state stream. Once we have the state stream we call part3 a state stream, and we get out the vdom stream, and then we pass that here.
So we refactor our app, and it still works exactly as before. That's good, but then again part1, part2, and part3 are not good names. They're not descriptive. Let's give better names for them. Let's start from the easy part. This function takes state and basically renders it.
That's usually the case for a view. That's what view does in other frameworks in other languages. State management will usually take the name of the model. That's what a model usually does. It represents our internal app state. So then what is part1?
You can think of it as basically interpreting what the user wants to do, and representing that as a convenient stream for the model to use. I'm going to call this intent, like that. The main will use intent model and view, and this is actually what we call the Model-View-Intent pattern, which is meant to organize this type of sandwich interaction.
Now our main function does just one thing. It converts sources to syncs, and it does that by calling these three functions in succession.