Escrevendo o novo iFood para Parceiros – Parte 1: Flutter 2.0

Acompanhe o processo de migração do app iFood para Parceiros: Parte 1: Flutter 2.0.

Olá! Meu nome é Gildásio. Sou engenheiro de software da equipe de iFood para Parceiros, e estou aqui para falar sobre nossa jornada de três partes na reescrita, refatoração e redesign do app. O objetivo é deixar o app num estado onde todos se sintam confortáveis ​​para adicionar novas funcionalidades enquanto gerenciamos as já existentes, sejam eles novos na equipe ou não.

Prólogo

Quando eu cheguei no iFood, em maio de 2021, a equipe estava numa situação difícil depois de perder um integrante – e tínhamos algumas entregas para fazer num curto espaço de tempo. Sabíamos que, em breve, teríamos ajuda externa por alguns meses, mas o app, como estava naquele momento, não estava amigável o suficiente para que uma nova equipe entrasse assim. Decidimos por uma nova arquitetura baseada no bloc para a UI, e arrumamos (mais ou menos) nossa arquitetura atual para o resto. Ainda assim, tínhamos um problema maior pela frente: estávamos usando o Flutter 1.22.6.

A situação era a seguinte: sprint atual/lançamentos para terminar, nova equipe e novas funcionalidades chegando, arquitetura ainda não organizada, plugins antigos e uma versão antiga do Flutter. Não podíamos esperar, considerando que a próxima atualização do Flutter (que anunciou o 2.2) estava pra sair, e isso significaria ainda mais trabalho se ainda não estivéssemos no 2.0.

Ao mesmo tempo, este foi o melhor momento para fazer a migração, considerando que estávamos numa pausa enquanto as próximas funcionalidades ficavam prontas para a etapa de desenvolvimento. Ou seja, o prazo para isso era de duas semanas.

Ficou decidido o seguinte:

– Separar um branch do desenvolvimento chamado develop_2.0 e iniciar a migração por lá, módulo a módulo;

– Continuar desenvolvendo as funcionalidades do sprint atual separadamente, para convertê-los depois, pois precisávamos ainda terminar uma versão;

– Escrever e detalhar uma nova arquitetura para a nova equipe, para já saberem o que precisávamos para o novo módulo, já usando o Flutter 2.0 desde o início.

Um deles definitivamente não deu certo. Imagina qual?

A migração

Tínhamos apenas duas semanas para migrar um aplicativo com 22 módulos antes que a próxima funcionalidade chegasse e, para facilitar as coisas, pensamos: “migrar cada módulo separadamente vai dar bom, né?”.

Não.

Um pouco do contexto: o aplicativo iFood para Parceiros começou há dois anos, com uma equipe que estava aprendendo Flutter enquanto construía o app. Isso nos deixou com padrões e uma arquitetura que tornaria nosso trabalho de migração um pouco difícil – um desses, justamente, relacionado a como os módulos estavam interligados. Não podemos migrar o módulo 1, por exemplo, porque ele depende do 3, 4 e 7. E esses, por sua vez, dependem de outros.

Portanto, a abordagem por módulos não estava funcionando. O que poderíamos fazer depois de garantir que os módulos sem dependências fossem migrados com segurança? Executar dart migrate em cada módulo de uma só vez, certo?

Calma, não fizemos isso – mas quase.

Primeiro, precisávamos ter certeza de que estávamos seguindo as etapas corretas. Felizmente, todos os pacotes que estávamos usando naquela época já tinham uma versão null-safety disponível no canal stable ou no beta.

Em seguida, mapeamos os módulos com menos dependências e começamos por eles, gradualmente para, aos poucos, tornar mais fácil também pegar os módulos maiores.

Aí, sim, executamos dart migrate! Foi o que tornou tudo muito mais fácil e seguro, (considerando que tínhamos apenas duas semanas). A ferramenta teve suas deficiências, mas definitivamente foi o que tornou a façanha possível em tão pouco tempo.

Discutimos um pouco se migraríamos para o 2.0 com o null-safety desativado ou não, e cada artigo e recomendação deixava apenas uma escolha: é melhor fazer isso agora, antes que seja obrigatório e que sobre ainda mais trabalho pra depois. Valeu a pena? Com certeza!

Vindo de Kotlin, senti falta do null-safety nos três anos em que trabalhei com o Flutter. Nos ajuda a nos tornar menos propensos a erros, e deixa os novos plugins e pacotes mais seguros, com recursos como a late initialization (que ainda não temos a versão async que o Kotlin permite). Você pode dar uma olhada na explicação oficial aqui.

Lições aprendidas:

  • Ter uma ferramenta tão boa como o dart migrate ajuda na tarefa “perigosa” de migrar um projeto grande uma vez com poucas ressalvas. A gente realmente parabeniza o trabalho das equipes de Dart and Flutter nesse sentido;
  • É possível fazer muita coisa em duas semanas! Organizamos a equipe de uma maneira que a gente não só conseguiu fazer a migração, mas ainda tivemos tempo de preparar o terreno para que novas pessoas trabalhassem no código assim que migrássemos;
  • O próprio Flutter ajudou nisso também. Tínhamos muitos widgets que temíamos que parassem de funcionar após a migração, devido à complexidade – mas tudo funcionou bem. Só tivemos problemas com campos anuláveis ​​imprevistos, provenientes de APIs que foram mapeadas incorretamente pela ferramenta;
  • A partir de agora, vamos tomar muito mais cuidado com todos os novos módulos que escrevermos. Principalmente, sobre o problema de dependência, que era algo de anos atrás e, finalmente, tivemos a chance de pelo menos evitar que nos atrapalhe ainda mais no futuro.

Esperamos que você tenha gostado desta primeira parte da nossa jornada, e fique atento para a próxima! Falaremos sobre a nova arquitetura que definimos para os módulos: dados, domínio e UI.

Texto original disponível em Writing the new iFood for Partners — Part 1: Flutter 2.0

Esse conteúdo foi útil para você?
SimNão

Publicações relacionadas