Andrea Bizzotto 💙 Profile picture
Mar 22 14 tweets 5 min read
What's the best project structure for medium/large Flutter apps?

Most likely, there's no "right" answer that works for all projects.

So let's explore two popular approaches known as "feature-first" and "layer-first" and learn about their differences.

Thread. 🧵
First of all, it's best to consider project structure in relation to app architecture.

For reference, let's consider this high-level architecture made of four layers:

‣ presentation
‣ application (optional)
‣ domain
‣ data
If your app is complex enough, we'll have multiple features.

And each feature can be represented by a group of classes that belong to the four layers.

In this context, we have two choices in regards to project structure:

- layers inside features
- features inside layers
So what should we choose?

The "features inside layers" approach (layer-first) doesn't work great for big projects with many features.

For any given feature, files that belong to different layers are far away from each other and we have to constantly "jump" across layers.
But with the "layers inside features" approach (feature-first), things are a lot better.

For a given feature, all the files we need are found inside the same top-level folder.

And we still get a good separation between layers.
In practice, things are not always easy.

At the beginning of a project, you may not have a good understanding of the domain model.

And that makes it hard to clearly identify the various features and structure the project accordingy.
At that stage, you may be tempted to create one folder for each screen of your app.

But that's a mistake, because features are *not* screens.

Rather, think of features as *functional requirements* that help the user complete a certain task.
In practice, I found that studying the domain model leads to a much better understanding of the whole system.

This helps us identify the features we need, so that we can "build the right thing" later on.
With this approach, you'll be better equipped to figure out which widgets, controllers, services, and repositores belong to each feature.

And you'll be able to better organize your project as a result.
Of course, large projects have some additional requirements (infrastructure, performance, organizational structure).

Those projects are often split into completely independent modules (packages) that are owned by different teams.
But it's a great idea to apply domain-driven design from the start.

That way, we'll end up with clear boundaries between the different layers and components of our app, making dependencies more easy to manage later on.
This completes my overview of project structure in Flutter. 🏁

I'll publish a separate article that will cover this topic more in depth. ✅

What project structure have you used in your apps? Let me know in the comments. 👇

For more tips like this, just follow me: @biz84
And if you want to learn how to build a full-stack eCommerce app following these principles, you can sign up for my upcoming course and get a big discount when I open the pre-sale next month. 👇

codewithandrea.com/courses/comple…

Happy coding!
As promised, I have now published an article that goes through this (and my decision making process) in more detail:

codewithandrea.com/articles/flutt…

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with Andrea Bizzotto 💙

Andrea Bizzotto 💙 Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @biz84

Mar 16
What are some popular architectures that are suitable for Flutter App Development (and which one to choose)?

It boils down to what level of complexity you need to handle. 👇

Thread. 🧵 Image
(1/2) Model–view–controller (MVC) is a software design pattern made of 3 types of components:

- Model: directly manages the data, logic, and rules of the application
- View: UI components (widgets)
- Controller: Accepts input and converts it to commands for the model or view Image
(2/2) MVC typically overloads the model with too much logic, and an additional service layer is often added: MVC+S

The Model should be reactive (e.g. using ChangeNotifier) so that the widgets rebuild when the model changes.

And user inputs always go through the controller.
Read 14 tweets
Mar 14
What are some rules to follow for good app architecture in Flutter?

Thread. 🧵
RULE: Avoid singletons

If you want your code to be testable, there are various alternatives to singletons:

- constructor arguments (doesn't scale well with deep widget hierarchies)
- InheritedWidget or Provider
- Service locators (e.g. get_it)
RULE: Zero (or very little) business logic in the widgets.

Widgets should be as dumb as possible and only be used to map the state to the UI.

Small exceptions: sometimes I include some simple currency, date, or number formatting code in my widgets if it makes life easier.
Read 8 tweets
Mar 9
When using GoRouter for declarative navigation, you'll often have to choose between:

- GOING to a route
- PUSHING a route

What is the difference between the two?

A thread. 🧵 Image
To start off, let's consider a simple route hierarchy made of one top route with two sub-routes. Image
Let's also define 3 pages for our routes: Image
Read 10 tweets
Mar 1
WidgetsBindingObserver is very handy for listening to changes to:

- routing events
- device orientation
- platform settings (text scale factor, brightness, locale, etc.)
- app lifecycle events

Here's how to use it to hide sensitive info when the app goes to the background. 🧵 Image
How to set it up?

- add the WidgetsBindingObserver *mixin* to one of your classes (generally a State subclass)
- register the observer inside initState (and dispose it when done) Image
Then, just override the methods for the changes you want to keep track of.

In this case, we listen to app lifecycle changes and update a "foreground" flag via setState(). Image
Read 6 tweets
Feb 28
I’ve been watching the events unfolding in #Ukraine with great concern.

And it's clear that many people need humanitarian aid, *right now*.

If you have the means to do so, donate your money (I have).

This thread lists a few non-profits helping people during this crysis. 👇
If you haven't already seen this, here's display of much needed, true leadership from the Ukranian president:

Here's a great article by @GergelyOrosz about the impact of this war on the Tech World:

Read 5 tweets
Feb 23
What are some VSCode extensions you can use to speed-up your Flutter workflow?

Here's a thread with my favourites! 🧵
When creating model classes, you'll often needs methods such as:

• copyWith()
• toString()
• toJson()
• fromJson()
• toMap()
• fromMap()
• == operator
• hashCode

Use the Dart data class generator to create them all in one go!

Link: marketplace.visualstudio.com/items?itemName…
If you use Riverpod, you'll quickly get tired of typing out all your providers and consumers by hand.

The Flutter Riverpod Snippets extension makes this a lot easier!

Link: marketplace.visualstudio.com/items?itemName…
Read 10 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Don't want to be a Premium member but still want to support us?

Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!

Ethereum

0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy

Bitcoin

3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

Follow Us on Twitter!

:(