<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: João Pedro Gonçalves</title>
    <description>The latest articles on DEV Community by João Pedro Gonçalves (@jpgoncalv3s).</description>
    <link>https://dev.to/jpgoncalv3s</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F848521%2F61293156-03d8-4754-bab8-f109d2ec32a5.jpg</url>
      <title>DEV Community: João Pedro Gonçalves</title>
      <link>https://dev.to/jpgoncalv3s</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jpgoncalv3s"/>
    <language>en</language>
    <item>
      <title>Estratégias de Ativação de Features Flags no GitLab - exemplo prático em Flutter</title>
      <dc:creator>João Pedro Gonçalves</dc:creator>
      <pubDate>Tue, 07 Mar 2023 19:13:14 +0000</pubDate>
      <link>https://dev.to/jpgoncalv3s/estrategias-de-ativacao-de-features-flags-no-gitlab-exemplo-pratico-em-flutter-3c9o</link>
      <guid>https://dev.to/jpgoncalv3s/estrategias-de-ativacao-de-features-flags-no-gitlab-exemplo-pratico-em-flutter-3c9o</guid>
      <description>&lt;h3&gt;
  
  
  Para que usamos Feature Flags
&lt;/h3&gt;

&lt;p&gt;Podemos pensar em &lt;em&gt;Feature Flag&lt;/em&gt;(FF) como a sinalização para uma Recurso de um sistema. Essa sinalização vai dizer se essa recurso está acessível ou não.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tecnologias envolvidas
&lt;/h3&gt;

&lt;p&gt;Apesar do caráter booleano das FFs, surgiram implementações e especificações que associam estratégias ao seu uso. &lt;/p&gt;

&lt;p&gt;O &lt;a href="https://docs.getunleash.io/tutorials/unleash-overview"&gt;Unleash&lt;/a&gt; contém a especificação que o &lt;em&gt;package&lt;/em&gt; dart &lt;a href="https://pub.dev/packages/unleash"&gt;Unleash Client SDK&lt;/a&gt;, importado pela nossa aplicação, usa para interagir com a alternância de recursos(&lt;em&gt;feature toggles&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;O repositório do nosso &lt;em&gt;app&lt;/em&gt; está no &lt;code&gt;GitLab&lt;/code&gt;, este por sua vez usa o já citado &lt;code&gt;Unleash&lt;/code&gt; para disponibilizar aos desenvolvedores as &lt;a href="https://docs.gitlab.com/ee/operations/feature_flags.html"&gt;Feature Flags Gitlab&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rodando a Aplicação exemplo
&lt;/h3&gt;

&lt;p&gt;Neste pr do &lt;a href="https://github.com/GeoSales-Evolution/unleash-multi-tenant-flutter-poc/pull/18"&gt;unleash multi tenant POC&lt;/a&gt; temos o estado de código suficiente para trabalhar disponibilidade de recursos usando &lt;code&gt;userIDs&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/GeoSales-Evolution/unleash-multi-tenant-flutter-poc.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para usar o projeto com sucesso é preciso atribuir corretamente as variáveis de ambiente no arquivo &lt;code&gt;.env&lt;/code&gt; como descrito neste &lt;a href="https://dev.to/uxjp2/managing-feature-flags-with-unleash-flutter-setting-env-vars-6h6"&gt;post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Em seguida é preciso rodar a aplicação.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter run 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E finalmente chegar a tela que testa as &lt;code&gt;Feature Flags&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RZQgbpSy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cfuaup2wozs8o6rix9jd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RZQgbpSy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cfuaup2wozs8o6rix9jd.png" alt="Tela inicial POC unleash multitenant" width="269" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xLRL6-lC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/91odj6tuajp9ks16rkeo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xLRL6-lC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/91odj6tuajp9ks16rkeo.png" alt="flag tela poc" width="269" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Criando Feature Flag
&lt;/h3&gt;

&lt;p&gt;Usaremos estratégias baseadas em &lt;code&gt;userIDs&lt;/code&gt;. Como estamos trabalhando como GitLab é preciso ter acesso à um projeto nessa plataforma, e então acessar a tela de features flags.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1fMgz0Jw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t9nbau9i77mg0evrob6s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1fMgz0Jw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t9nbau9i77mg0evrob6s.png" alt="Navegação Menu GitLab" width="351" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Então Vamos criar uma &lt;code&gt;Feature Flag&lt;/code&gt; clicando no botão &lt;code&gt;New feature flag&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SWNm-S2c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4sqggu5bgpu5yhrao4tv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SWNm-S2c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4sqggu5bgpu5yhrao4tv.png" alt="Cabeçalho Feature Flags Gitlab" width="880" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Estratégias
&lt;/h2&gt;

&lt;p&gt;Vamos abordar 3 estratégias com exemplos&lt;/p&gt;

&lt;h3&gt;
  
  
  1/3 All users
&lt;/h3&gt;

&lt;p&gt;Essa é a estratégia mais simples, pois não filtra(restringe) nenhum usuário.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EbczJdZw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7gq6hwivq9vaow00a75.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EbczJdZw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7gq6hwivq9vaow00a75.png" alt="All users" width="880" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mesmo passando um usuário qualquer via &lt;code&gt;Context&lt;/code&gt;, ou até mesmo sem passar usuário, receberemos positivo caso a flag esteja ativa.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_nwJWPDZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5zni9dl2avmexa7lmf4l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_nwJWPDZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5zni9dl2avmexa7lmf4l.png" alt="Feature Flag ativa" width="880" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esse trecho está no &lt;a href="https://github.com/GeoSales-Evolution/unleash-multi-tenant-flutter-poc/pull/18/files#diff-dd8d160935565b40db44872c86b7fa07b0c8a4247b1abc8bd03ed89aa9850ed7R55"&gt;PR 18 Unleash multi tenant POC&lt;/a&gt;, sendo responsável por por &lt;em&gt;printar&lt;/em&gt; a disponibilidade do recurso no console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Is feature accessible ? == &lt;/span&gt;&lt;span class="si"&gt;${unl.isEnabled(flagText, localContext: Context(userId: "usuarioqualquer"))}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9LBgktJk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ufxv3m677vfpfeotrkfu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9LBgktJk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ufxv3m677vfpfeotrkfu.png" alt="consulta flag" width="458" height="667"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2/3 Usando &lt;em&gt;userIDs&lt;/em&gt; diretamente
&lt;/h3&gt;

&lt;p&gt;Podemos digitar as strings correspondentes aos usuários e associas essa estratégia à &lt;code&gt;Feature Flag&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JZnhLZOO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jwyurxx2l1urknr35fqi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JZnhLZOO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jwyurxx2l1urknr35fqi.png" alt="userID capivara" width="566" height="619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como não estamos passando o &lt;em&gt;userID&lt;/em&gt; &lt;em&gt;capivara&lt;/em&gt; no código &lt;em&gt;Dart&lt;/em&gt; o resultado vai ser negativo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1FLuV9wt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zij25mxqsitv2r0dowjh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1FLuV9wt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zij25mxqsitv2r0dowjh.png" alt="False" width="469" height="675"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Assim que passarmos o &lt;em&gt;userID&lt;/em&gt; pelo contexto, temos resultado positivo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Is feature accessible ? == &lt;/span&gt;&lt;span class="si"&gt;${unl.isEnabled(flagText, localContext: Context(userId: "capivara"))}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WefeD4Xk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x68zyn03kcv7l3fyotgy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WefeD4Xk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x68zyn03kcv7l3fyotgy.png" alt="capivara true" width="466" height="681"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OBS: &lt;em&gt;hot reload&lt;/em&gt; pode não atualizar o construtor de &lt;code&gt;Context&lt;/code&gt; causando erros nos seus testes.&lt;/p&gt;

&lt;h3&gt;
  
  
  3/3 Usando Listas de Usuários
&lt;/h3&gt;

&lt;p&gt;Novamente no cabeçalho de &lt;em&gt;Feature Flags&lt;/em&gt;, vamos escolher a opção "View Users List".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uAispj_m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mpvp69gbv5nhiwuuoiyf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uAispj_m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mpvp69gbv5nhiwuuoiyf.png" alt="FF" width="880" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depois "New user list"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PI0809ge--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2gypfcrbrgjso15tvmgo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PI0809ge--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2gypfcrbrgjso15tvmgo.png" alt="New user list" width="880" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depois de criada a lista vamos adicionar usuários em "Add Users"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HyldvcI0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d5khtvsy38fmxw1mot7w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HyldvcI0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d5khtvsy38fmxw1mot7w.png" alt="Add Users" width="880" height="81"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8AD0o33o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bzts5ssvm3cu9ar57inw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8AD0o33o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bzts5ssvm3cu9ar57inw.png" alt="users" width="880" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pqcBaCjQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r61z6a19lgwt1hsq3nok.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pqcBaCjQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r61z6a19lgwt1hsq3nok.png" alt="lista pronta" width="880" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lista pronta e contendo usuários podemos usá-la como estratégia para nossa FF.&lt;/p&gt;

&lt;p&gt;Depois deselecionar a opção "edit", entramos na tela de edição de FFs, muda-se a estratégia e escolhemos a lista.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--isgIwhsX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/98gqjwvh06jz1z1jx6id.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--isgIwhsX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/98gqjwvh06jz1z1jx6id.png" alt="lista" width="880" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Caso o &lt;em&gt;userID&lt;/em&gt; passado no contexto esteja contido na lista teremos um resultado positivo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Is feature accessible ? == &lt;/span&gt;&lt;span class="si"&gt;${unl.isEnabled(flagText, localContext: Context(userId: "sabia"))}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EPXBc2pi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rukvcj26nqfqm4uaevsp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EPXBc2pi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rukvcj26nqfqm4uaevsp.png" alt="sabia true" width="462" height="678"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Demais estratégias
&lt;/h3&gt;

&lt;p&gt;Existem outras estratégias usadas com &lt;em&gt;Feature Flags&lt;/em&gt;, além da opção de adicionar várias estratégias na tela de edição - basta clicar em "Add strategy".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6_7aHtzc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c4v7bmw33r0d9veo430m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6_7aHtzc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c4v7bmw33r0d9veo430m.png" alt="add strategy" width="880" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusão
&lt;/h3&gt;

&lt;p&gt;Usando GitLab, Flutter e Unleash vimos que as regras são todas definidas no nosso repositório &lt;em&gt;GitLab&lt;/em&gt;, enquanto que passamos informações do usuário via &lt;code&gt;Context&lt;/code&gt; no lado &lt;em&gt;Dart&lt;/em&gt; para avaliar a disponibilidade do recurso.&lt;/p&gt;

&lt;p&gt;Valeu !!&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>mobile</category>
      <category>featureflag</category>
      <category>gitlab</category>
    </item>
    <item>
      <title>Atualizando aplicação Flutter para null safe - exemplo prático</title>
      <dc:creator>João Pedro Gonçalves</dc:creator>
      <pubDate>Mon, 06 Mar 2023 19:58:15 +0000</pubDate>
      <link>https://dev.to/jpgoncalv3s/atualizando-aplicacao-flutter-para-null-safe-exemplo-pratico-hai</link>
      <guid>https://dev.to/jpgoncalv3s/atualizando-aplicacao-flutter-para-null-safe-exemplo-pratico-hai</guid>
      <description>&lt;h3&gt;
  
  
  Não comece errado
&lt;/h3&gt;

&lt;p&gt;Antes de tudo tenho que saber que minha aplicação funciona na versão sem &lt;code&gt;null safety&lt;/code&gt; que estou usando, isso no dará tranquilidade para resolver apenas problemas relacionados à atualização do Flutter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Motivação
&lt;/h3&gt;

&lt;p&gt;A aplicação alvo é o POC &lt;a href="https://github.com/GeoSales-Evolution/unleash-multi-tenant-flutter-poc"&gt;https://github.com/GeoSales-Evolution/unleash-multi-tenant-flutter-poc&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
Estávamos usando o Flutter &lt;code&gt;1.22.2&lt;/code&gt; para rodá-la, e agora queremos mudar para &lt;code&gt;2.5.0&lt;/code&gt;. O porquê dessa escolha além do uso do no &lt;code&gt;null safe&lt;/code&gt; está relacionada com outros projetos que se interagem com o POC.&lt;/p&gt;
&lt;h3&gt;
  
  
  Montando o experimento
&lt;/h3&gt;

&lt;p&gt;No caso montamos um fluxo na aplicação funcionando e o esperado é que após a migração para a &lt;code&gt;2.5.0&lt;/code&gt; a aplicação funcione da mesma maneira.&lt;/p&gt;

&lt;p&gt;No fluxo: &lt;br&gt;
Usuário entra com &lt;code&gt;Login&lt;/code&gt; e &lt;code&gt;Tenant&lt;/code&gt; &amp;gt; é levado a tela de sonsulta de flags &amp;gt; digita um flag ativa &amp;gt; recebe a string 'flag ativa? == true' no console do terminal. &lt;br&gt;
Essa flags são &lt;code&gt;Feature Flags&lt;/code&gt; de um projeto no GitLab.  &lt;/p&gt;

&lt;p&gt;Abaixo prints do fluxo funcionando:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1eSke5Zu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/grso4xjfx5fk35llicrf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1eSke5Zu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/grso4xjfx5fk35llicrf.png" alt="Image description" width="271" height="566"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pPFiBrBh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wx5hrrgjn1dp8ynr68zz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pPFiBrBh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wx5hrrgjn1dp8ynr68zz.png" alt="Image description" width="644" height="596"&gt;&lt;/a&gt;  &lt;/p&gt;
&lt;h3&gt;
  
  
  Subindo as dependências
&lt;/h3&gt;

&lt;p&gt;O próprio &lt;a href="https://dart.dev/null-safety/migration-guide#step1-wait"&gt;Flutter&lt;/a&gt; sugere que atualizemos primeiro as dependências em ordem para depois atualizar as aplicações.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XsLMvOjV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u0nz1c26koplduvqkas6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XsLMvOjV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u0nz1c26koplduvqkas6.png" alt="Image description" width="462" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como não temos nenhum subprojeto como dependência do nosso app vamos direto ao seu &lt;code&gt;pubspec.yaml&lt;/code&gt;, observamos as versões dos pacotes(&lt;code&gt;packages&lt;/code&gt;) usados e procuramos no &lt;a href="https://pub.dev/"&gt;https://pub.dev/&lt;/a&gt; quais versões estão disponíveis com o nosso Flutter e Dart SDK almejados.&lt;/p&gt;

&lt;p&gt;Por exemplo: &lt;code&gt;path_provider:&lt;/code&gt; está na versão &lt;code&gt;^1.6.28&lt;/code&gt; e podemos observar na sua página de &lt;a href="https://pub.dev/packages/path_provider/versions"&gt;versões path_provider&lt;/a&gt; que uma versão que tem &lt;code&gt;null safety&lt;/code&gt; e atende no &lt;code&gt;Dart SDK 14&lt;/code&gt;(Flutter 2.5.0) pode ser a &lt;code&gt;2.0.0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PD3y7_RP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l1ylrhhwe4c8e9a8kfjy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PD3y7_RP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l1ylrhhwe4c8e9a8kfjy.png" alt="Image description" width="759" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Além disso, vamos atualizar a versão do Flutter e do Dart SDK no no &lt;code&gt;pubspec.yaml&lt;/code&gt;, no nosso caso 2.5.0 e 2.14.0 respectivamente.&lt;/p&gt;
&lt;h3&gt;
  
  
  Dart pub upgrade
&lt;/h3&gt;

&lt;p&gt;Depois decididas todas as mudanças de versões das dependências usamos uma ferramente altomatizado do dart para resolver as dependências:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dart pub upgrade&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Se houver alguma incompatibilidade entre as dependências o &lt;code&gt;Dart&lt;/code&gt; vai avisar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qcM52BLs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ml5j28a6pk11bvhre0a0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qcM52BLs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ml5j28a6pk11bvhre0a0.png" alt="Image description" width="572" height="649"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dart pub get&lt;/code&gt; funciona também, porém prefiro &lt;code&gt;upgrade&lt;/code&gt; por ser mais verboso.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ii7sc1jG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aw55o97l5un9yyhgxp85.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ii7sc1jG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aw55o97l5un9yyhgxp85.png" alt="Image description" width="572" height="649"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  dart migrate
&lt;/h3&gt;



&lt;p&gt;&lt;code&gt;dart migrate&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;na raiz do projeto vai fornce um relatório de problemas a serem corrigidos.&lt;br&gt;&lt;br&gt;
Nós esperamos dois tipos de erros: adequação ao &lt;code&gt;null safety&lt;/code&gt; e quebra de APIs(causadas por mudanças nas APIs das dependências depois de atualizações).  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FsR9kPkm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7hx5j8npvskcd1udds6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FsR9kPkm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7hx5j8npvskcd1udds6.png" alt="Image description" width="880" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Concertamos os problemas com &lt;code&gt;null safety&lt;/code&gt; e adaptamos o código para as novas APIs das dependências. Conforme o tamanho do seu projeto esse vai ser o passo mais demorado.&lt;br&gt;&lt;br&gt;
Então rodamos &lt;code&gt;dart migrate&lt;/code&gt; novamente e esperamos ver:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YyuvbRPr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b9kj3ud42drz6d0laqg3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YyuvbRPr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b9kj3ud42drz6d0laqg3.png" alt="Image description" width="629" height="225"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Rodar aplicação atualizada
&lt;/h3&gt;



&lt;p&gt;&lt;code&gt;flutter run&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;deve funcionar normalmente depois das alterações e mostrar uma mensagem:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;💪 Running with sound null safety 💪&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Nos resta testar a aplicação. Nesse caso estou considerando o fluxo do experimento que definimos anteriormente, e ele funcionou sem falhas conforme a captura abaixo:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7xXYioBg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8rbsibc9b3w9z4e1tqi6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7xXYioBg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8rbsibc9b3w9z4e1tqi6.png" alt="flutter run" width="880" height="523"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O experimento não encontrou evidências de que a aplicação contém defeito(quem sabe a discussão sobre como usar experimento em outro post), logo abrimos &lt;a href=""&gt;pull request&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Valeu !&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>mobile</category>
      <category>update</category>
    </item>
    <item>
      <title>Atualizando aplicação Flutter para null safe - exemplo prático</title>
      <dc:creator>João Pedro Gonçalves</dc:creator>
      <pubDate>Thu, 02 Mar 2023 01:25:58 +0000</pubDate>
      <link>https://dev.to/jpgoncalv3s/atualizando-aplicacao-flutter-para-null-safe-exemplo-pratico-l59</link>
      <guid>https://dev.to/jpgoncalv3s/atualizando-aplicacao-flutter-para-null-safe-exemplo-pratico-l59</guid>
      <description>&lt;h3&gt;
  
  
  Não comece errado
&lt;/h3&gt;

&lt;p&gt;Antes de tudo tenho que saber que minha aplicação funciona na versão sem &lt;code&gt;null safety&lt;/code&gt; usada, isso nos dará tranquilidade para resolver apenas problemas relacionados à atualização do Flutter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Motivação
&lt;/h3&gt;

&lt;p&gt;A aplicação exemplo é o POC &lt;a href="https://github.com/GeoSales-Evolution/unleash-multi-tenant-flutter-poc" rel="noopener noreferrer"&gt;https://github.com/GeoSales-Evolution/unleash-multi-tenant-flutter-poc&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
Estávamos usando o Flutter &lt;code&gt;1.22.2&lt;/code&gt; para rodá-la, e agora queremos mudar para &lt;code&gt;2.5.0&lt;/code&gt;. O porquê dessa escolha além do uso do &lt;code&gt;null safety&lt;/code&gt; está relacionada com outros projetos que interagem com o POC.&lt;/p&gt;
&lt;h3&gt;
  
  
  Montando o experimento
&lt;/h3&gt;

&lt;p&gt;Montamos um fluxo na aplicação funcionando, esperando que após a migração para a &lt;code&gt;2.5.0&lt;/code&gt; a aplicação funcione da mesma maneira.&lt;/p&gt;

&lt;p&gt;No fluxo: &lt;br&gt;
Usuário entra com &lt;code&gt;Login&lt;/code&gt; e &lt;code&gt;Tenant&lt;/code&gt; &amp;gt; é levado a tela de consulta de flags &amp;gt; digita um flag ativa &amp;gt; recebe a string 'flag ativa? == true' no console do terminal. &lt;br&gt;
Essa flags são &lt;code&gt;Feature Flags&lt;/code&gt; de um projeto no GitLab.  &lt;/p&gt;

&lt;p&gt;Abaixo prints do fluxo funcionando:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgrso4xjfx5fk35llicrf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgrso4xjfx5fk35llicrf.png" alt="Login" width="271" height="566"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwx5hrrgjn1dp8ynr68zz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwx5hrrgjn1dp8ynr68zz.png" alt="Consulta Flag" width="644" height="596"&gt;&lt;/a&gt;  &lt;/p&gt;
&lt;h3&gt;
  
  
  Subindo as dependências
&lt;/h3&gt;

&lt;p&gt;O próprio &lt;a href="https://dart.dev/null-safety/migration-guide#step1-wait" rel="noopener noreferrer"&gt;Flutter&lt;/a&gt; sugere que atualizemos primeiro as dependências em ordem para depois atualizar as aplicações.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0nz1c26koplduvqkas6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0nz1c26koplduvqkas6.png" alt="ordem de atualização de deps" width="462" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como não temos nenhum subprojeto como dependência do nosso app vamos direto ao seu &lt;code&gt;pubspec.yaml&lt;/code&gt;, observamos as versões dos pacotes(&lt;code&gt;packages&lt;/code&gt;) usados e procuramos no &lt;a href="https://pub.dev/" rel="noopener noreferrer"&gt;https://pub.dev/&lt;/a&gt; quais versões estão disponíveis com o nosso Flutter e Dart SDK almejados.&lt;/p&gt;

&lt;p&gt;Por exemplo: &lt;code&gt;path_provider:&lt;/code&gt; está na versão &lt;code&gt;^1.6.28&lt;/code&gt; e podemos observar na sua página de &lt;a href="https://pub.dev/packages/path_provider/versions" rel="noopener noreferrer"&gt;versões path_provider&lt;/a&gt; que uma versão que tem &lt;code&gt;null safety&lt;/code&gt; e atende no &lt;code&gt;Dart SDK 14&lt;/code&gt;(Flutter 2.5.0) pode ser a &lt;code&gt;2.0.0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl1ylrhhwe4c8e9a8kfjy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl1ylrhhwe4c8e9a8kfjy.png" alt="Exemplo de versão de pacote" width="759" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Além disso, vamos atualizar a versão do Flutter e do Dart SDK no &lt;code&gt;pubspec.yaml&lt;/code&gt;, no nosso caso 2.5.0 e 2.14.0 respectivamente.&lt;/p&gt;
&lt;h3&gt;
  
  
  Dart pub upgrade
&lt;/h3&gt;

&lt;p&gt;Depois decididas todas as mudanças de versões das dependências usamos uma ferramenta do dart para resolver as dependências:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dart pub upgrade&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Se houver alguma incompatibilidade entre as dependências o &lt;code&gt;Dart&lt;/code&gt; vai avisar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fml5j28a6pk11bvhre0a0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fml5j28a6pk11bvhre0a0.png" alt="dart pub upgrade" width="572" height="649"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dart pub get&lt;/code&gt; funciona também, porém prefiro &lt;code&gt;upgrade&lt;/code&gt; por ser mais verboso.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faw55o97l5un9yyhgxp85.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faw55o97l5un9yyhgxp85.png" alt="dart pub upgrade" width="572" height="649"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  dart migrate
&lt;/h3&gt;



&lt;p&gt;&lt;code&gt;dart migrate&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;na raiz do projeto vai fornecer um relatório de problemas a serem corrigidos.&lt;br&gt;&lt;br&gt;
Nós esperamos dois tipos de erros: adequação ao &lt;code&gt;null safety&lt;/code&gt; e quebra de APIs(causadas por mudanças nas APIs das dependências depois de atualizações).  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7hx5j8npvskcd1udds6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7hx5j8npvskcd1udds6.png" alt="dart migrate falha" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Concertamos os problemas com &lt;code&gt;null safety&lt;/code&gt; e adaptamos o código para as novas APIs das dependências. Conforme o tamanho do seu projeto esse vai ser o passo mais demorado.&lt;br&gt;&lt;br&gt;
Então rodamos &lt;code&gt;dart migrate&lt;/code&gt; novamente e esperamos ver:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb9kj3ud42drz6d0laqg3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb9kj3ud42drz6d0laqg3.png" alt="dart migrate sucesso" width="629" height="225"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Rodar aplicação atualizada
&lt;/h3&gt;



&lt;p&gt;&lt;code&gt;flutter run&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;deve funcionar normalmente depois das alterações e mostrar uma mensagem:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;💪 Running with sound null safety 💪&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Nos resta testar a aplicação. Nesse caso estou considerando o fluxo do experimento que definimos anteriormente, e ele funcionou sem falhas conforme a captura abaixo:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsao5ibie8nxng856yjsw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsao5ibie8nxng856yjsw.png" alt="flutter run" width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O experimento não encontrou evidências de que a aplicação contém defeito(quem sabe a discussão sobre como usar experimentos em outro post), logo abrimos &lt;a href="https://github.com/GeoSales-Evolution/unleash-multi-tenant-flutter-poc/pull/16" rel="noopener noreferrer"&gt;pull request&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Objetivo alcançado !!&lt;/p&gt;

</description>
      <category>node</category>
      <category>linting</category>
      <category>tooling</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
