4 Ideas To Discuss That Is Better Than State Management
Don’t fall into the beginner trap. There’s more to think about.
There are topics as important, if not more than state management when it comes to building a production Flutter application. In this post, we’ll cover those topics.
These topics will provide a better understanding of a front-end application’s architecture.
Discussing state management ONLY is a waste of time, there are other things we need in order to build a production-ready application.
This post will serve as an introduction to the following ideas and what I usually look for when discussing/researching them:
Your Navigation setup
The code’s file structure
How Dependency Inversion will be applied
Your layers of separation (Software Design Approach)
If you fail to think about this it will show in your code. There will be no boundaries and no clear opinion on how your code should further be expanded on.
Over the next few minutes we’ll look at these concepts, understand them, and define the types of questions to ask when researching or discussing them:
Navigation Implementation
Navigation is the mechanism used to take a user from one view to another. It decides what to show, where the user goes and the transition used to get there. Now you might think, “Flutter has built-in navigation” and yes, that’s correct, but if used in its default state it will violate #3 and #4.
Most navigation solutions require the BuildContext
which means it requires the Flutter engine to be running. In code, this translates to writing Business Logic that is tightly coupled to the Flutter engine. If that’s not bad enough, the other major issue is that your code using that navigation will not be unit-testable.
To avoid this, here are the questions I ask when discussing/researching navigation solutions:
Can I easily apply Dependency Inversion to my Navigation? If your business logic does the navigation then it’s a great idea to invert the dependency on the business logic so you can mock the responses during the unit tests.
Do I have to manually write my navigation routes? A lot of code for navigators, when using default Flutter requires you to write the routing paths manually. In addition, you also have to manually serialize arguments. This becomes problematic as soon as you have more than 7 navigation destinations you can go to.
Can I manage my navigation stack? As users navigate through an application they build up their Navigation History Stack. Often it’s required to clear or add new entries in different positions of the stack. Knowing how easy this is upfront will help you with your decision especially if you have requirements for sections like this in your app.
Support for common patterns and docs? I check to see if there are there examples, documentation, or guidance on how to implement common navigation patterns like nested navigation or bottom navbar.
Code File Structure
The way your files are grouped together, how they are organized, and where new files should be created. This allows you to establish your first form of opinion in your code base and allows you to create something that fits into how you think about your software.
A newly created Flutter project gives you one folder where you can add your code lib
😅 if you add all your files here you’ll end up with a pretty wild code base where it’s not clear to anyone how your system is grouped together and what the purpose of individual files is.
This is something you can implement as your code grows, but as you get there, here are some of the questions I ask to figure out where to place files:
Does the structure match the separation layers? As we implement software design patterns into our code we create different layers in our code which creates a mental model. To try and reduce the cognitive load of keeping that mental model in my memory I often try to mimic, up to where it makes sense, the layers of separation in my code.
Does the structure help my mental model? We all have a mental model of the architecture of our applications, how it fits together, which pieces exist, and which parts interact. When making a decision on where to move files, or how to group them I refer back to this mental architecture model to ensure it makes sense for myself, and the team.
How we’ll apply Dependency Inversion
I wrote an entire post dedicated to Dependency Inversion, what it is, and how to apply it. In short, it’s the process of passing in or retrieving dependent objects from outside the current, in order to make it more testable. This helps you create a robust architecture.
There is no default way of doing this. Since Flutter only operates on the UI layer, when you write your Business Logic or Application Logic in pure Dart there’s no built-in way to apply the Dependency Inversion principle.
There are only 3 ways in Dart to do dependency inversion so choosing your solution depends on what you prefer. The questions I ask myself are:
Do I want to do Constructor Injection?
Do I want to do Method Injection?
Do I want to do Service Location?
This will depend on your programming style and your mental models of software development. There’s no best way, it’s all about what you prefer. To read more about Dependency Inversion here’s a more detailed guide.
Layers of Separation
When you apply a Software Design Pattern you end up with different layers in your code base. If you followed my 4-step framework for introducing a Flutter architecture you’ll end up with UI, State, Business Logic, and Application Logic as your 4 layers.
Because everything in Flutter is code there is no inherent distinction between the code you write for your UI and the code you write for the rest of the application. It’s all Dart so it all looks the same.
It’s good to make a decision early on or at least think about it, this will allow you to know that as the code grows you’ll have to apply some separation frameworks to introduce new layers. Here are some of the questions I ask when discussing or researching this:
What is the intention of the project or code? If it’s for research, or to test something you don’t need to separate anything. If it’s for a client or a serious project, then you should.
What is the time commitment of this project? Knowing how long you expect to be working on this project can help you ensure you don’t over-engineer something that will be out of commission in a few weeks.
What stage is the project or code in? If it’s a fresh new project then you have a good chance to organise things well if you know it’ll be a bigger and longer project. If you’re in MVP, Alpha, beta and you haven’t separated your code well then you should start the process as soon as you can to ensure you’re not growing a spaghetti monster.
How many developers will work on the project? If this is a project that no-one will see, or work with and only you will be expanding on it then build it as you see fit. You can skip thinking about your separation layers until something shows you that you have to take it a bit more serious.
You don’t have to apply these software engineering principles. It sounds counter-intuitive to say that, but I say it because delivering a solution is more important than your code.
Eventually, you will have problems in your code and you’ll slow down, at which point you can apply enough structure to move forward at a good pace. Write code to solve the problem at hand, refactoring should always be the last step in the process.
Announcement 🚀
From next week our newsletter will be changing 🤗 you’ll be getting more content!
We’ve completed our course and we now have more time back to focus on technical content.
We’ll be writing 3 technical pieces a week, you’ll get the summary of all of them and exclusive links to the full guides.
What you can expect?
A weekly Flutter Web Discussion / Tutorial
As we build Stacked and its documentation we will send out summaries of all interesting discussions, new tutorials, or releases.
There are many features upcoming and already released in Flutter. As a Flutter insider, I will write technical guides and tutorials on new, old, and upcoming features.