(Translated by https://www.hiragana.jp/)
Writing the new iFood for Partners — Part 1: Flutter 2.0 | by Gildásio Filho | iFood Engineering | Medium

Writing the new iFood for Partners — Part 1: Flutter 2.0

Gildásio Filho
iFood Engineering
Published in
5 min readSep 8, 2021

--

Hello, I’m Gildásio, a software engineer from the iFood for Partners app team and I’m here to tell you about our three-part journey on rewriting, refactoring and redesigning our app to get to a place where everyone feels comfortable adding new features while managing the existing ones whether they’re new to the team or not.

Prologue

When I joined back in May/2021, the team was in a rough spot after losing a member and we had quite a few features to get done in a short span of time. We knew we were receiving external help for a few months soon, but the current state of the app wasn’t friendly enough for a new team to join like that. We decided in a new architecture based on bloc for the UI, and tidied-up our Clean-ish current architecture for the rest, but we had a bigger issue in front of us: we still were using Flutter 1.22.6.

So what we had: current sprint/release to finish, new team and new features coming, not-yet-organized architecture, old plugins and an old Flutter version. We couldn’t wait that much more considering the next Flutter event (that announced 2.2) was around the corner, and that would mean even more work for us to do if we weren’t already in 2.0. But at the same time, this was the best time ever to do the migration considering we were in a break while the next feature got development-ready, so we had two weeks available to do it.

The plan decided was the following:

  • Separate a branch from develop called develop_2.0 and start the migration there, module by module;
  • Keep developing the current sprint’s features separately and convert them later since we needed to finish a release;
  • Write about the new architecture for the upcoming team to know what we want for the new module, and let them use Flutter 2.0 from the start.

One of those didn’t work as expected, can you guess what it was?

A Draft Merge Request from GitLab showing the branches develop_2.0 and develop
And so the Merge Request opened as a Draft

The Migration

We only had two weeks to migrate an app with 22 modules before the next batch of development-ready features arrived, and to make things easier we thought “Migrating each module separately would work fine, right?”. It didn’t.

A bit of background: the iFood for Partners app started two years ago by a team that was learning Flutter while building the app, so this left us with patterns and an architecture that would make our job of migrating quite a bit difficult, one of those being the interlocking nature of the modules. We can’t migrate module 1 because it depends on 3, 4 and 7. And those depend on other ones.

So the by-module approach wasn’t going to work. What could we do then after making sure the modules with no dependencies got migrated safely? Run dart migrate on every single module at once, that's what!

Calm down, we didn’t do it like that, but almost.

First, we needed to make sure we were following the correct steps. Fortunately, all the packages we were using back then already had a null-safety version available in either stable or in the beta channel, so after quite a bit of searching and pub gets, we had those ready. Then, we mapped the modules with the least dependencies and started there, moving up the ladder and at the same time making it easier to do the bigger modules later on.

Then we ran dart migrate! It was what made this all so much easier and overall safer to do considering we only had two weeks. The tool had its shortcomings, we had to later remove a few ? and late that just weren't necessary and caused a few issues once we got the app running, but it obviously was what made the feat possible in such a short time.

Screenshot from GitLab showing a Merge Request with 139 commits and more than 839 changes
After 139 commits and 829+ changes, we were ready to merge

We discussed quite a bit if we would just migrate to 2.0 with null-safety turned off or not, and every single article and recommendation let us with only one choice: it’s better to do this now before it’s required and we let even more work for later on. Was it worth it? Absolutely! Coming from Kotlin, I missed null-safety for the three years I’ve been working with Flutter. It helps us make less prone to error code and it makes new plugins and packages safer to use too, along with the new features like late initialization (which we’re still missing the async version that Kotlin allows). You can take a look at the detailed overview from the Dart team here.

Lessons learned

  • Having such a good tool like dart migrate helps those "dangerous" tasks of migrating lots of code at once. We really appreciate the work from the Dart and Flutter team on this one;
  • We can actually do a lot in two weeks! We organized the team in such a way that we didn’t just stop to do the migration, and even had time to prepare the field for new people to work in the code as soon as we migrated;
  • Flutter itself helped this too — we had quite a lot of widgets that we were worried would stop working somehow after the migration due to their complexity, but everything worked just fine on the Flutter side; we only had issues with unforeseen nullable fields coming from APIs that were improperly mapped by the tool;
  • From now on, we’re going to keep the tips and tricks learned from the migration process when making new modules, mainly the dependency issue that was something from years ago and finally had its chance to at least try to halt our progress.
A GitLab Merge Request showing the release 1.5.0 with more than 908 changes
This was the release with the migration and that sprint’s feature set

We hope you liked this first part of our journey, and stay tuned for the next where we’ll talk about the new architecture we defined for our modules, data, domain and UI.

Check the vacancies available on iFood, learn more about the selection process and join the team.

--

--