When starting with Flutter I was looking for recommendations for App architecture and most of the time I found references to the Redux pattern.
I'm really honest, Redux never appealed to me. I understand the idea behind the unidirectional data flow but it just seemed too much overhead.
But I wanted to take it to a test and try to create App that is identical to one created with Redux but with the RxVAMS pattern (which I proposed in my last blog post) .
I asked Iiro if it would be ok if I take his App and refactor it to RxVAMS and he is looking forward to the outcome.
Trying to find out how an Redux app works turned out to be more difficult than expected. Normally when inspecting source code of an app someone else wrote I start with the UI trying to follow the program flow that is triggered by an user action. Trying to do that by using the IDE's "Go to definition" and "Find all references" didn't really help because of the way Redux decouples classes. I can only agree with Paul Betts on this:
Comparing the project structure
The Redux version needs 24 classes for its state management where the Rx version only uses one:
I wrote a small analysis tool DartStatistics to count code lines, characters and number of classes:
|Version||Code Lines||Code characters||classes|
This means Redux needs about 30% more lines and characters of code than RxVAMS to achieve the same functionality.
But what if the App gets more complex?
As this App only has one real Page with user interaction I use only one class the
AppModel to hold all state of the App. If the App would consists of more complex pages the AppModel would provide a PageModel for each of this Pages that would relay data to the AppModel or directly to the service layer.
The Redux version stores all app state inside one store class so not so much difference here but it needs a lot more code to access and modify it.
But, but Redux will prevent a lot of errors!
True, the fact that views cannot modify state directly but only over dispatching actions might beware you of potential errors but for the price that your code gets much harder to understand and you have to create much more code to reach that goal.
More code also means more places to make mistakes.
Using Streams and RxCommands to communicate between model and view you get an easier to understandable architecture that works without side effects too and you always can follow your code using your IDE's search commands.
Readability before everything else
If you ever came back to one of your own project after a year you know the feeling to have the feeling someone else must have written this code. Same for any developer that gets the task of continuing the development of a project because the original creator has left the company. So easy to understand and to follow code is paramount.
Why do we use complex patterns?
- Reusability of code: I really would like to know how many of you have really reused bigger parts of an App in completely different one that wouldn't be better placed in a independent library from the begin.
- Exchangeability of components: Often be introduce additional abstraction layers. But who of you have really changed the database after an app was finished?
- Extensibility: I think it was Kent Beck the creator of Extreme Programming how made the point that using modern IDEs it's pretty easy to make big refactorings even in large code bases. Having automated tests implemented make sure that you don't accidentally break something.
- Error prevention: State management is one of the most difficult areas of any App so using patterns that preventing side effects are a good idea. If one pattern will save you at the end of the day will only show time. Choose a pattern that doesn't compromise understandability of your code.
- Testability: This is actual the one that has shown its benefits in daily use. But even here I always will prefer manual Dependency injection before automagically working IOC containers.
I don't say that these goals are not important and may be helpful from time to time but I want to encourage you to question existing development trends and hypes. Trying to strive for simplicity is a good goal overall.
Try it on your own
O.K. you got it, I don't like Redux 🙂 You don't have to believe me so give it a try yourself. Clone both repositories and try to understand how the apps work and share your experiences with us in the comments. I'm really curious to hear them.
Here are the repositories:
I'm still exploring how to refine the use of RxCommands with Flutter and there are still some points where I'm not completely satisfied but I will continue this exploration and hope some of you will join me.Contact me: