So this is all looking really great. We now have better tools for modeling our domains more concisely.
Previously when we wanted to be able to navigate to a new child feature from an existing feature we would just throw an optional into our domain. However, with each additional optional you add to a domain you double the number of invalid states in your feature. For example, we had 4 options representing 4 different destinations, which means there were 16 different states our feature could be in, only 5 of which were valid.
Now we can embrace enums when modeling the destinations for our features, which gives us just one single place to describe all the different places a feature can navigate to. That gives us us more correctness in our code because the compiler is proving for us that only one destination can be activated at a time.
Next let’s address a problem that gets nearly everyone eventually when using our library, especially when composing lots of features together. Because modeling navigation in state requires us to nest child state in parent state, any sufficiently complex application eventually has a very large root app state that could potentially have hundreds of fields. This also means that the amount of memory you are storing on the stack will increase as you integrate more child features together.
This may not matter for awhile, but eventually your state may get too big or you may have too many frames on the stack, and you could accidentally overflow the stack. That crashes the application, and so that of course isn’t great.
Now it’s worth noting a couple of caveats here. Not all of your application’s state is necessary stored on the stack. Arrays, dictionaries, sets, and even most strings are all stored on the heap, and so it doesn’t matter if you have a 100,000 element array in your state, that makes no difference for the stack.
Also we made great strides towards reducing the number of stack frames that are incurred when combining lots of features together, all thanks to the Reducer
protocol. In release mode most of those compositions get inlined away and you are left with very few actual stack frames.
But still, people do run into this limitation, and it’s a real bummer.
However, by far the most common reason for multiple features to be integrated together is because of navigation. You plug “FeatureB” into “FeatureA” when you need to navigate from A to B. As you do this more and more your state becomes bigger and bigger.
And now we are going to be giving everyone more tools to build up state like this for navigation, and so it may start happening a lot more. Perhaps we can directly bake into the tools a more efficient way of storing state so that it plays more nicely with deeply nested, composed features.