Estratégias de Ativação de Features Flags no GitLab - exemplo prático em Flutter
Tags: flutter, mobile, featureflag, gitlab
Published: 2023-03-07 19:13:14

### Para que usamos Feature Flags

Podemos pensar em *Feature Flag*(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.

### Tecnologias envolvidas

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

O [Unleash](https://docs.getunleash.io/tutorials/unleash-overview) contém a especificação que o *package* dart [Unleash Client SDK](https://pub.dev/packages/unleash), importado pela nossa aplicação, usa para interagir com a alternância de recursos(*feature toggles*).

O repositório do nosso *app* está no `GitLab`, este por sua vez usa o já citado `Unleash` para disponibilizar aos desenvolvedores as [Feature Flags Gitlab](https://docs.gitlab.com/ee/operations/feature_flags.html).

### Rodando a Aplicação exemplo

Neste pr do [unleash multi tenant POC](https://github.com/GeoSales-Evolution/unleash-multi-tenant-flutter-poc/pull/18) temos o estado de código suficiente para trabalhar disponibilidade de recursos usando `userIDs`.

```
git clone https://github.com/GeoSales-Evolution/unleash-multi-tenant-flutter-poc.git
```

Para usar o projeto com sucesso é preciso atribuir corretamente as variáveis de ambiente no arquivo `.env` como descrito neste [post](https://dev.to/uxjp2/managing-feature-flags-with-unleash-flutter-setting-env-vars-6h6).

Em seguida é preciso rodar a aplicação. 

```
flutter run 
```

E finalmente chegar a tela que testa as `Feature Flags`.

![Tela inicial POC unleash multitenant](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cfuaup2wozs8o6rix9jd.png)


![flag tela poc](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/91odj6tuajp9ks16rkeo.png)

### Criando Feature Flag 

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

![Navegação Menu GitLab](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t9nbau9i77mg0evrob6s.png)

Então Vamos criar uma `Feature Flag` clicando no botão `New feature flag`.

![Cabeçalho Feature Flags Gitlab](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4sqggu5bgpu5yhrao4tv.png)

## Estratégias

Vamos abordar 3 estratégias com exemplos

### 1/3 All users

Essa é a estratégia mais simples, pois não filtra(restringe) nenhum usuário.

![All users](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7gq6hwivq9vaow00a75.png)

Mesmo passando um usuário qualquer via `Context`, ou até mesmo sem passar usuário, receberemos positivo caso a flag esteja ativa.


![Feature Flag ativa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5zni9dl2avmexa7lmf4l.png)


Esse trecho está no [PR 18 Unleash multi tenant POC](https://github.com/GeoSales-Evolution/unleash-multi-tenant-flutter-poc/pull/18/files#diff-dd8d160935565b40db44872c86b7fa07b0c8a4247b1abc8bd03ed89aa9850ed7R55), sendo responsável por por *printar* a disponibilidade do recurso no console.

```dart
print('Is feature accessible ? == ${unl.isEnabled(flagText, localContext: Context(userId: "usuarioqualquer"))}');
```

![consulta flag](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ufxv3m677vfpfeotrkfu.png)

### 2/3 Usando *userIDs* diretamente

Podemos digitar as strings correspondentes aos usuários e associas essa estratégia à `Feature Flag`

![userID capivara](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jwyurxx2l1urknr35fqi.png)

Como não estamos passando o *userID* *capivara* no código *Dart* o resultado vai ser negativo.

![False](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zij25mxqsitv2r0dowjh.png)

Assim que passarmos o *userID* pelo contexto, temos resultado positivo.

```dart
print('Is feature accessible ? == ${unl.isEnabled(flagText, localContext: Context(userId: "capivara"))}');
```

![capivara true](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x68zyn03kcv7l3fyotgy.png)

OBS: *hot reload* pode não atualizar o construtor de `Context` causando erros nos seus testes.

### 3/3 Usando Listas de Usuários

Novamente no cabeçalho de *Feature Flags*, vamos escolher a opção "View Users List".

![FF](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mpvp69gbv5nhiwuuoiyf.png)

Depois "New user list"

![New user list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2gypfcrbrgjso15tvmgo.png)

Depois de criada a lista vamos adicionar usuários em "Add Users"

![Add Users](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d5khtvsy38fmxw1mot7w.png)

![users](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bzts5ssvm3cu9ar57inw.png)

![lista pronta](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r61z6a19lgwt1hsq3nok.png)

Lista pronta e contendo usuários podemos usá-la como estratégia para nossa FF.

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

![lista](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/98gqjwvh06jz1z1jx6id.png)

Caso o *userID* passado no contexto esteja contido na lista teremos um resultado positivo.

```dart
print('Is feature accessible ? == ${unl.isEnabled(flagText, localContext: Context(userId: "sabia"))}');
```

![sabia true](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rukvcj26nqfqm4uaevsp.png)

### Demais estratégias 

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

![add strategy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c4v7bmw33r0d9veo430m.png)

### Conclusão

Usando GitLab, Flutter e Unleash vimos que as regras são todas definidas no nosso repositório *GitLab*, enquanto que passamos informações do usuário via `Context` no lado *Dart* para avaliar a disponibilidade do recurso.

Valeu !!