Feature Flags e Parallel Change (Deploy vs Release)
Neste vídeo você vai conhecer Feature Flags e Parallel Change, dois conceitos bem conhecidos do universo DevOps. Se você quiser conhecer mais de DevOps, pode começar pela formação [Primeiros passos em DevOps]( # Transcrição Você sabia que existem diferenças entre *deploy* e *release*? Neste vídeo, falaremos sobre elas, além de comentar práticas aplicáveis em cima dessas distinções. Oi, pessoal. Eu sou Vinicius Dias. Sejam bem-vindos à Alura. Neste Alura+, vamos bater um papo sobre a **diferença entre *deploy* e *release***, bem como discutir certas práticas que podemos aplicar em cima dessas diferenças. Assim, conseguimos obter resultados interessantes na hora de soltar um *release* ou criar um *deploy*. Primeiramente, vamos entender a diferença entre essas duas palavras. ***Deploy*** basicamente é o ato de ter o ambiente e o software já instalados e configurados. Em resumo, é colocar o software em produção — isso é fazer *deploy*. Se você tem o software desenvolvido e testado, já fez o *build*, passou por toda a *pipeline*, mandou para um servidor de homologação e para a produção, então você fez o *deploy*. Já fazer o ***release*** é entregar esse *deploy* para usuários reais. É perfeitamente possível fazer o *deploy* (por exemplo, de um novo *endpoint*) e não o documente, não entregue, não permita acesso pelos usuários. De qualquer forma, esse *endpoint* está em produção, o *deploy* foi feito. Portanto, o *release* é o ato de tornar público e disponível para os usuários. Então, fazer a publicação é gerar uma *release*. Inclusive, é bastante comum ir aumentando o *deploy* por um período para, no final do mês, por exemplo, gerar um só, mandar para a produção e fazer um único *release* de todas as novas funcionalidades. Em outras palavras, se foi gerada uma nova versão, foram escritas notas de versão e foi enviado um e-mail para o cliente expondo as novidades, então fizemos um *release*. Porém, sabemos que, antes disso, já tínhamos feito o *deploy*, pois o ambiente já estava configurado e o software já estava em produção. Então, essa é a diferença entre esses dois termos. Logo, vale notar que, se temos a opção de fazer o *deploy* sem fazer o *release*, ou seja, se é possível ter código em produção que os usuários ainda não vão acessar, podemos adotar algumas práticas interessantes em cima dessa ideia. Por exemplo, **feature toggles** ou **feature flags**. Ao criar uma funcionalidade, ela pode estar em um ponto crítico da aplicação ou modificar diversos trechos do código. Para diminuir os riscos da *release*, faremos o *deploy* adicionando uma expressão condicional if (uma verificação no código) para que a funcionalidade somente seja exibida caso a *feature flag* esteja marcada. Em outras palavras, a *release* será feita apenas se uma checkbox, uma configuração específica esteja ativa. Com as *feature flags*, conseguimos determinar que somente alguns clientes tenham certa funcionalidade ativa; outros clientes, não. É possível que você já tenha lido a respeito dos ***beta testers* ou testadores de novas funcionalidades**. Basicamente, essas pessoas terão as *feature flags* de funcionalidades novas habilitadas antes do resto dos usuários. Já aconteceu de você ter um aplicativo e seu amigo possuir uma funcionalidade nova que você ainda não possui? Isso é feito por meio das *feature flags*. Embora pareça complexo, visto que aplicativos enormes o utilizam, trata-se de um processo relativamente simples de ser implementado. Podemos realmente fazer um único if: se esta *feature flag* estiver ativa para determinado usuário, então libere a funcionalidade. Essa regra de ativação pode ser um simples botão que marcamos e desmarcamos, ou pode seguir outro padrão. Por exemplo, se quisermos liberar a funcionalidade para metade dos clientes, uma opção é habilitar a *feature flag* para os usuários cujo ID é par — se o ID for par, estará habilitada; se for ímpar, desabilitada. Assim, permitimos acesso a 50% dos usuários. Dessa forma, temos o *deploy* de uma funcionalidade, porém o *release* ainda não aconteceu para todos os clientes. Assim, conseguimos **monitorar com mais cuidado, com menos usuários**. Caso exista um problema, ele afetará menos pessoas, de forma que teremos uma *release* mais segura. Já que estamos falando sobre adicionar if e verificar o ID dos usuários, outra técnica bastante interessante e mais relacionada com o código em si é o ***parallel change*** (em português, "mudanças em paralelo"). Esse conceito também pode ser chamado padrão ***expand, migrate and contract***. A seguir, vamos entender o que isso significa. Vamos imaginar que temos uma classe com um método que recebe dois parâmetros de coordenadas, o X e o Y. Então, agimos em cima dessas informações. Por exemplo, em uma planilha no Excel, nas coordenadas X e Y teremos uma célula em que adicionaremos o conteúdo. Em outro par de coordenadas, teremos outra célula e adicionaremos outros dados, e assim em diante. Contudo, ao estudar sobre boas práticas, notamos que em vez de ter dois parâmetros inteiros seria mais adequado ter uma classe nova de coordenadas. Nela, teríamos a validação (se é uma coordenada positiva, por exemplo). Ou seja, queremos modificar a API do nosso código, alterar a interface com a qual lidamos com o código. Para tanto, precisaríamos quebrar o contrato e atualizar diversas partes do código. A ideia de *parallel change* é basicamente inserir novos métodos que recebem um objeto do tipo coordenada por parâmetro em vez desses dois inteiros. No entanto, os métodos que recebem os dois inteiros continuarão existindo. Todo o código que já existia continua funcionando e qualquer código novo que precise chamar esses métodos pode utilizar essa API melhorada. Então, quando adicionamos esses novos métodos, estamos na fase de ***expand*** — expandimos a API, criamos mais código, mais informações. Em seguida, avançamos para a fase de ***migrate***. Vamos migrar o código já existente para passar a utilizar os métodos novos, a nova API. Esse processo pode ser gradual, de forma mais lenta. Por fim, entramos na fase de ***contract***, em que enforçamos o novo contrato. A nível de código, esse procedimento é feito excluindo os métodos antigos que recebem aqueles dois parâmetros inteiros. Com essa abordagem temos algumas **vantagens**. De início, o código já existente não quebrará com essa melhoria do código, tudo continuará funcionando. Ademais, teremos uma API melhorada, com melhores práticas e pronta para ser utilizada por qualquer código novo. Ou seja, há entregas e melhorias contínuas em nosso código. E, por fim, a migração para o código novo pode ser incremental, realizada lentamente, ao longo de várias *releases*. E se fizéssemos *releases* usando o *parallel change*? E se, além de melhorar o código, pudéssemos liberar novas funcionalidades em paralelo? O nome dessa prática pode ser ***blue-green deployment*** ou ***blue-green releases***. Vamos supor que estamos criando um sistema novo ou novas funcionalidades do mesmo sistema. Temos o código atual rodando em um ambiente e faremos o *deploy* dessa nova funcionalidade em outro ambiente. Em seguida, podemos passar a redirecionar usuários para essa versão 2. Caso ocorra algum problema, basta redicioná-los de volta para o código anterior que continua funcionando. Inclusive, temos a opção combinar os conceitos de *blue-green deployment* com *feature toggles*. Por exemplo, podemos direcionar 20% dos usuários para o código novo e 80% para a versão antiga. Conforme o monitoramento, aumentamos o número de usuários na nova versão. Então, esse é o conceito de *blue-green deployment*. De forma incremental, conseguimos fazer com que os usuários utilizem a nova versão. Ou seja, realizamos um *release* incremental, de forma mais lenta. Já a ideia de *feature flag* é mais de baixo nível, no próprio código. Já o *blue-green deployment* refere-se ao sistema inteiro. São duas bases de códigos diferentes. O fato de conseguirmos separar conceitualmente *deploy* e *release* nos fornece ferramentas interessantes para tornar todo nosso ambiente de desenvolvimento e de operações mais seguro e mais tranquilo para se trabalhar.