The Software Engineering approach in Cross-Platform Programming with Flutter (Part 2)
Designing and building the Flutter application structure using the Bloc pattern in the micro-service architecture.
This part continues the previous part. If you haven’t read it, go to this link, then come back here.
At this point, we modelized the gallery software product. If you remember, we should turn back to the communication phase and ask the others to comment on your models and improve your models by fixing their problems. For the gallery project, I have to ask for your opinions, so if you’ve read the previous part and have any suggestions, write your comment and tell me how to make these models better.
Construction
Congratulations, we finally reached this phase. OK, before creating the project, make sure you are in the master
channel and enable web and desktop by running these commands:
$ flutter branch master
$ flutter config --enable-web
$ flutter config --enable-linux-desktop
I will use and build for the Linux platform, but you can run the last command for your own platform. Now, you’re ready to create your project. You can choose the name whatever you like:
$ flutter create gallery
Let’s look at the galley project structure with its features:
We decided to use Micro-Service architecture for the gallery application, so I have the services
directory for the gallery services. I use the lib
directory to locate gallery presentation layers and their functionality functions. Let’s explain other routes:
lib/core
: put some functions used for presentations.lib/l10n
: put your localizations, and usel10n.yaml
to generate gallery localization.lib/presentation/widgets
: put reusable widgets here.lib/presentation/screens
: put screens here, and each screen contains itscomponents
. If we need to use small and simple Bloc and data layers for a specific screen, we don’t need to use a separate service. Instead, we can use thecubit
directory for its purpose. Use this link to learn more about Cubit.
As I explained about the Monolithic architecture, if you want to use this one, you should put all Blocs in lib/bloc
directory and all of the data layers models and repositories in lib/data
directory. Then create a new directory for each new feature. It’s not efficient, yes? It’s so ambiguous, and we can find each feature in every directory, and if we face a problem, it will be so difficult to debug that.
Create a new Service
Let’s describe the gallery Micro-Service approach. We have a separate services
directory, and every service inside this directory doesn't concern with each other unless we define it in its own dependency. Let’s make an example for the gallery authentication service. This is the structure of the authentication
directory:
The first thing you should know, I didn’t create all those files by hand. These are the steps for creating a service, I’m going to use the stagehand
package:
- Activate this package by this command:
$ flutter pub global activate stagehand
- Make a directory with your service name like
authentication_service
:
$ mkdir authentication_service
- Change to the new service directory:
$ cd authentication_service
- Run this command to the new package as a service:
$ flutter pub global run stagehand package-simple
It will generate a bunch of files that contain test and example directories. These are optional, and if you want to test your service or make an example for that service, you should keep them.
Program the new service and keep its files under lib/src
directory, and then export those files that you want them to use as public classes. It’s useful for other services to import that file if they need this service. For example, authentication_service.dart
could be like this:
Don’t worry, and I will explain those Bloc and models files in the next part.
└── src
├── bloc
├── models
├── providers
└── repository
Authentication is one of the gallery services that needs Bloc and models. As you can see, I separated its Bloc layer and split the data layer into providers and repository (If you don’t know about them, go back to the previous part).
Let’s see what is inside of its /services/authentication/pubspec.yaml
:
I used bloc_dependency_service
and model_dependency_service
, since I don’t want to use Bloc and model dependencies directly inside of each service. Why? If you want to upgrade your Bloc package and add some new features to your services, you don’t need to upgrade every single service. Instead, you can upgrade its dependency service. The gallery bloc dependencies service looks like this:
And for example, /services/dependencies_service/bloc/pubspec.yaml
of the bloc dependency service looks like this:
Remember that if you want to use an external dependency more than once in your project, make a separate dependency and put it inside the dependencies service.
Supporting New Features
If you have noticed, all of Bloc dependencies support nullsafety
and therefore, we can migrate this service to nullsafety
by increasing the minimum version of Dart SDK to 2.12.0–0
because as the doc says:
package C depends on package B, which depends on package A, then A should be migrated to null safety first, then B, then C.
Although you can migrate before your dependencies support null safety, you might have to change your code when your dependencies migrate. For example, if you predict that a function will take a nullable parameter but the package migrates it to be non-nullable, then passing a nullable argument becomes a compile error.
You can consider this as an advantage of using services, so if some features are added to the Flutter or Dart, it would be much easier to migrate them partially. I don’t want to explain how to migrate to null safety, but you can check the video service as a null safety service. If you want me to explain how to migrate null safety, comment me, and I can make a separate story for that sake.
Final Gallery Pubspec
If you implement all services, you should have pubspec.yaml
in your project root looks like this:
As you can see, I used other presentation dependencies before gallery services dependencies. I don’t use the HTTP service in the gallery presentation layer, so I don’t need to add it here.
Analysis Options
The last thing that your project should contain is the analysis_options.yaml
. It is so useful to make your own dart analyzer rules. The Dart analyzer has some optional warnings that you can consider as errors. Why? Because if you are working as a team, all your team members should code look like each other. It makes your project codes more consistent and more Integrated. Here’s the simple analysis_options.yaml
:
Monolithic Structure
Okay, that’s cool, but I don’t have much time and don’t have a complicated system. What should I do? As I mentioned, we use this architecture to easily understand our system, so there is no must. Make a Monolithic Structure for your application if you can make it. If you want to check this structure, this repository might be helpful.
For example, a Monolithic Structure could look like this:
In this structure, we gather all Blocs, Data Models, Repositories, and Providers in the same directory, and separate them based on each feature and the layers like lob/blocs
, lib/data
, lib/presentation
, and we can use the services
keyword just for our data providers like network and storage.
Final Words
I don’t want to elaborate on other service structures. They so much look like the authentication service. In the next part, I will implement the gallery application requirements that we planned for.
You can check out the gallery repository, but I recommend you not to clone it. Please make your own repository and try to do all steps on your own and then share your repository with me or others in the Flutter community. And make the best community in the technology world for Flutter.
Thank you for reading. I hope you enjoyed it. This article takes me so much time researching and developing in both software engineering and flutter programming, so if you found this article helpful, please clap and share this article. If you have any suggestions to make this article better, don’t hesitate to contact me or write a comment down below and I’d reply to you fast if I weren’t asleep.
You can go to the next part with this link.
Follow Flutter Community on Twitter: https://www.twitter.com/FlutterComm