ALM Rangers

Desenvolvimento de software com alternadores de recursos

Bill Heys

Baixar o código de exemplo

Os alternadores de recursos como um conceito de desenvolvimento de software permitem que você busque um desenvolvimento simultâneo, paralelo como uma alternativa à ramificação para o desenvolvimento paralelo (também chamada de ramificações recursos). Os alternadores de recursos às vezes são chamados de sinalizadores de recursos, comutadores de recursos, flippers de recursos ou recursos condicionais. Os alternadores de recursos permitem que você integre de forma contínua os recursos enquanto eles estão em desenvolvimento. Você pode usar os alternadores de recursos para ocultar, desabilitar ou habilitar recursos individuais durante o tempo de execução.

Como em todas as técnicas de desenvolvimento de software, você usaria os alternadores de recursos juntamente com o controle de versão (como o Microsoft Team Foundation Server). O uso dos alternadores de recursos por si mesmos não implica eliminar todas as ramificações de um plano de controle de versão abrangente. Uma diferença dos alternadores de recursos é que todas as alterações são verificadas na ramificação principal (via principal) ao invés de uma ramificação de desenvolvimento.

Um recurso é desabilitado ou oculto de todos os usuários até você começar o desenvolvimento do recurso. Durante o desenvolvimento, você pode habilitar o recurso para desenvolvimento e para testes de unidade e desabilitá-lo para todos os outros usuários. Os testadores de controle de qualidade (QA) podem também habilitar os recursos que desejam testar. Até que o recurso esteja concluído e totalmente testado de acordo com a Definição de pronto (DoD) e passe nos testes de qualidade, ele será oculto ou desabilitado no software lançado. Você pode alterar o valor de um alternador de recursos de forma dinâmica sem criar e implementar uma nova compilação.

Começando com uma comparação de ramificações recursos e alternadores de recursos, eu vou sugerir técnicas alternativas para implementar os alternadores de recursos em código. Usando uma aplicativo Calculadora do Windows como exemplo, vou ilustrar como ocultar ou mostrar recursos no tempo de execução, usando os alternadores de recursos.

Integração contínua

Usando os alternadores de recursos, você pode realizar uma integração contínua—todos os trabalhos de desenvolvimento são verificados na ramificação principal e integrados de forma contínua com todos os outros códigos naquela ramificação. Em cada verificação, o código na ramificação principal é compilado e testado em um servidor de compilação, usando testes de verificação de compilação (BVTs).

Como declarado no livro padrão e práticas da Microsoft sobre a entrega contínua ("Building a Release Pipeline with Team Foundation Server 2012" [2013]), "Ao entregar de forma contínua, queremos dizer que por meio de técnicas como controle de versão, integração contínua, automação e gestão ambiental, poderemos diminuir o tempo entre quando você primeiro tem uma ideia e quando a ideia é concretizada como software que está em produção" (bit.ly/1kFV0Kx).

Você pode usar os testes de unidade automatizados para testar seu código antes de verificá-lo na ramificação principal. Se uma verificação quebra uma compilação no servidor de compilação, deverá corrigir o código antes que a verificação seja permitida. Se um recurso na compilação não passa nos testes de controle de qualidade (QA), você pode ocultá-lo do desenvolvimento ou da liberação até que ele passe.

Os alternadores de recursos fornecem a você o isolamento do tempo de execução de um recurso que está sendo desenvolvido até ser concluído, testado e pronto para a liberação. Ao usar os alternadores de recursos com integração contínua, você trabalha diretamente na ramificação principal. O código é verificado na ramificação principal, enquanto mantém sua ramificação estável para compilações e implantações (veja Figura 1).

Feature Toggles Support Continuous Integration of Parallel Development
Figura 1 Os alternadores de recursos oferecem suporte para a integração contínua do desenvolvimento paralelo

Alternadores de recursos em uso

Figura 2 mostra um exemplo de alternadores de recurso no trabalho em um Formulário de Calculadora do Windows como exemplo. Também ilustra os desafios do desenvolvimento do recurso simultâneo paralelo.

Sample Windows Calculator Showing Three New Features
Figura 2 Calculadora do Windows como exemplo mostrando três novos recursos

Este exemplo compara como gerenciar o desenvolvimento paralelo usando as ramificações recursos e os alternadores de recursos. Há três novos recursos (teclado, funções avançadas e funções de memória) sendo desenvolvidos paralelamente quando a calculadora básica foi implantada.

Padrões dos alternadores de recursos

Há vários padrões de uso nos quais você pode usar os alternadores de recursos para permitir a integração contínua de todos os códigos, incluindo o código incompleto ou pendente. Ao usar os alternadores de recursos pode aumentar a velocidade do desenvolvimento da equipe, reduzindo ou eliminando a necessidade de ramificações de desenvolvimento paralelo e de tarefas de mesclagem e ramificações resultantes, que podem ser extremamente demorados e propensos a erros.

Aqui está uma lista de cenários típicos onde você pode considerar os alternadores de recursos:

  • Ocultar e desabilitar novos recursos na interface do usuário
  • Ocultar e desabilitar novos componentes no aplicativo
  • Controle de versão de uma interface
  • Ampliação de uma interface
  • Fornecer suporte à várias versões de um componente
  • Adicionar um novo recurso a um apliciativo existente
  • Aperfeiçoar um recurso existente em um aplicativo existente

Ramificações para o isolamento de recursos

Com uma estratégia de ramificações recursos, a sua equipe pode isolar o desenvolvimento paralelo ou simultâneo de recursos específicos—ou grupos de recursos—em ramificações recursos separadas. As ramificações recursos lhe fornecem uma flexibilidade significativa sobre quando mover um lançamento para a produção. Você não tem de esperar até que todos os recursos estejam prontos para realizar uma implantação completa.

Você pode mesclar facilmente recursos individuais ou grupos de recursos em uma ramificação principal quando estiverem completos de acordo com a DoD (Definição de pronto). Você pode criar novas ramificações recursos conforme necessário, e exclui-las assim que o recurso estiver completo. Os recursos não estão mesclados na ramificação principal até que atendam a DoD. Seguindo o exemplo, a Figura 3 mostra três novas ramificações recursos fornecendo isolamento durante o desenvolvimento paralelo.

Branching for Feature Isolation
Figura 3 Ramificações para o isolamento de recursos

Para mais orientações sobre os vários cenários de ramificações recursos, você pode consultar o livro eletrônico ALM Rangers sobre estratégias de ramificações em aka.ms/vsarsolutions.

Alternadores de recursos vs. Ramificações recursos

O uso dos alternadores de recursos permite que você e sua equipe busquem uma integração contínua, implantação contínua e práticas de lançamento contínuas. Estas práticas permitem uma integração de código de recurso mais frequente na medida em que são desenvolvidas paralelamente quando comparadas às ramificações recursos. Ao mesmo tempo, os alternadores de recursos também oferecem suporte para o isolamento do tempo de execução de recursos em desenvolvimento e que não estão prontos para a liberação.

Com os alternadores de recursos, todas as alterações pendentes são verificadas na ramificação principal. Cada verificação fica pendente até que um processo de compilação automatizado compile todos os códigos na ramificação principal em um servidor de compilação e executa com êxito BVTs automatizados. Este é o processo conhecido como integração contínua.

No tempo de execução, os alternadores de recursos ocultam ou ignoram recursos que estão na compilação, mas não prontos para a liberação. Dependendo de como você planeja implementar um recurso, o esforço para usar os alternadores de recursos pode ser excessivamente complexo. Por outro lado, ocultar recursos da interface do usuário pode ser feito diretamente.

Ao usar as ramificações recursos, todo o desenvolvimento é verificado na ramificação recurso associada e isolada do código na ramificação principal ou em outras ramificações recursos. Você pode mesclar um recurso novo ou aprimorado com a ramificação principal ou com outras ramificações recursos até que o recurso esteja com o código concluído, passe nos testes de qualidade exigidos ou atenda a DoD. Somente neste ponto o recurso está integrado (mesclado) com a ramificação principal. No entanto, o isolamento do código e a integração contínua são de alguma forma extremidades opostas do "espectro da integração".

Habilitar um novo recurso em uma implantação é relativamente fácil e sem riscos. Simplesmente ative os alternadores de recursos associados para visíveis e habilitados. O esforço para lançar um novo recurso usando ramificações recursos é muito mais complicado. Você deve mesclar o recurso na ramificação principal. Esse é geralmente um processo demorado e desafiador.

Como remover um recurso

Em alguns projetos, você deve remover ou reverter recursos incompletos. A reversão individual que altera ambientes para reverter um recurso (alterações escolhidas a dedo) é também complicada, trabalhosa e pode necessitar da reformulação significativa do código.

É imperativo isolar recursos da ramificação principal até você decidir liberar estes recursos. Em qualquer evento, reverter um recurso de uma liberação apenas antes da liberação que está agendada é arriscado e propenso a erros. Ao usar os alternadores de recursos, você verifica todos os códigos para todos os recursos na ramificação principal. Os alternadores de recursos simplesmente ocultam ou desabilitam os recursos selecionados do tempo de execução ou liberação.

Opções de implementação

Há várias abordagens para persistir no estado dos alternadores de recursos de um aplicativo. Aqui estão duas abordagens diretas:

  1. Use as configurações de aplicativos para definir os alteradores de recursos (implantado no arquivo de configuração aplicativo XML quando o aplicativo é compilado).
  2. Armazene os alternadores de recursos em linhas em uma tabela de banco de dados.

Definir os alternadores de recursos Não apenas é mais fácil definir os alternadores de recursos no arquivo de configuração usando o Designer de Configurações, mas também você não precisa fazer nada no seu aplicativo para salvar o estado dos alternadores de recursos quando o aplicativo finaliza. O arquivo de configurações usado como exemplo exibido na Figura 4 define os alternadores de recursos.

This Sample ConfigSettings File Stores Feature Toggle State for the Windows Calculator
Figura 4 Este arquivo ConfigSettings usado como exemplo armazena o estado do alternador de recursos para a Calculadora do Windows

Armazene os alternadores de recursos como linhas do banco de dados Para usar uma tabela de banco de dados do alternador de recursos para armazenar o estado do alternador de recursos, o aplicativo necessitará de dois arquivos de configuração. O arquivo de configurações CommonSettings define opções usadas pelo aplicativo. O arquivo de configurações DatabaseSettings controla se os alternadores de recursos são definidos e mantidos em uma tabela de banco de dados (quando Verdadeiro) ou em um arquivo de configurações (quando Falso). O arquivo FeatureToggleSettings fornece os nomes para cada um dos alternadores de recursos que você armazenará no banco de dados (veja Figura 5).

Feature Toggle Names Stored in the Database Table As Rows
Figura 5 Os nomes dos alternadores de recursos armazenados na tabela de banco de dados como linhas

A abordagem usada na Calculadora do Windows usada como exemplo é criar de forma dinâmica linhas de alternadores de recursos. Quando o aplicativo é executado pela primeira vez, a tabela estará vazia. No tempo de execução, todos os nomes de alternadores de recursos são verificados para ver se estão habilitados. E se algum ainda não está na tabela, o aplicativo os adicionará para a tabela. A tabela FeatureToggle usada como exemplo na Figura 6 mostra todos as linhas do alternador de recursos adicionadas.

FeatureToggle Table After Initial Run
Figura 6 Tabela do alternador de recursos após a execução inicial

Conceitos independentes de implementação

Quando você usa um alternador de recurso para desabilitar um recurso, o código no aplicativo oculta ou desabilita os controles com base no valor do alternador de recursos (Verdadeiro/Falso) associado com aquele recurso. Você pode escolher ocultar o recurso completamente da interface do usuário para recursos em desenvolvimento ou mostrar o recurso como desabilitado. Quando você libera o recurso, ele ficará visível e habilitado.

Figura 7 mostra a Calculadora do Windows com apenas o recurso do teclado visível e habilitado. Os recursos funções de memória e funções avançadas estão visíveis, mas desabilitados.

Windows Calculator with Keypad Feature Visible and Enabled, and the Memory and Advanced Functions Features Visible and Disabled
Figura 7 Calculadora do Windows com o recurso do teclado visível e habilitado e os recursos de memória e funções avançadas visíveis e desabilitados

A primeira etapa neste aplicativo de exemplo cria um novo banco de dados FeatureToggleDemo, após criar uma tabela FeatureToggle simples. Quando você baixa o aplicativo de exemplo, você encontrará três arquivos SQL para: Criar um banco de dados FeatureToggle, criar a tabela FeatureToggle e criar os dois procedimentos armazenados usados pelo aplicativo para carregar valores e salvá-los de volta na tabela FeatureToggle.

Após criar a tabela FeatureToggle, não há necessidade de adicionar nenhuma linha FeatureToggle antes de executar o aplicativo pela primeira vez. O aplicativo usa uma biblioteca de classe FeatureToggle para encapsular toda a lógica do aplicativo para acessar e atualizar os alternadores de recursos.

O código a seguir mostra campos privados usados para manter o estado dos alternadores de recursos:

private Boolean _IsKeyPadFeatureEnabled = false; private Boolean _IsKeyPadFeatureVisible = false; private Boolean _IsMemoryFeatureEnabled = false; private Boolean _IsMemoryFeatureVisible = false; private Boolean _IsAdvancedFeatureVisible = false; private Boolean _IsAdvancedFeatureEnabled = false;

O código na Figura 8 mostra como definir campos privados dos valores do alternador de recurso em um arquivo ConfigSettings.

Figure 8 Valores do alternador de recursos armazenados em um arquivo ConfigSettings

private void GetFeatureTogglesFromSettings() { _IsKeyPadFeatureEnabled = Properties.ConfigSettings.Default.KeyPadFeatureEnabled; _IsKeyPadFeatureVisible = Properties.ConfigSettings.Default.KeyPadFeatureVisible; _IsMemoryFeatureEnabled = Properties.ConfigSettings.Default.MemoryFeatureEnabled; _IsMemoryFeatureVisible = Properties.ConfigSettings.Default.MemoryFeatureVisible; _IsAdvancedFeatureEnabled = Properties.ConfigSettings.Default.AdvancedFeatureEnabled; _IsAdvancedFeatureVisible = Properties.ConfigSettings.Default.AdvancedFeatureVisible; tbMode.Text = Constants.configSettings; }

O código na Figura 9 mostra como definir campos privados dos valores do alternador de recursos armazenados em uma tabela de banco de dados FeatureToggle.

Figura 9 Define campos privados a partir dos valores do alternador de recursos armazenados em uma tabela de banco de dados

private void GetFeatureTogglesFromStore() { _IsKeyPadFeatureEnabled = FeatureToggles.FeatureToggles.IsEnabled( Properties.FeatureToggleSettings.Default.KeyPadFeatureEnabled); _IsKeyPadFeatureVisible = FeatureToggles.FeatureToggles.IsEnabled( Properties.FeatureToggleSettings.Default.KeyPadFeatureVisible); _IsMemoryFeatureEnabled = FeatureToggles.FeatureToggles.IsEnabled( Properties.FeatureToggleSettings.Default.MemoryFeatureEnabled); _IsMemoryFeatureVisible = FeatureToggles.FeatureToggles.IsEnabled( Properties.FeatureToggleSettings.Default.MemoryFeatureVisible); _IsAdvancedFeatureEnabled = FeatureToggles.FeatureToggles.IsEnabled( Properties.FeatureToggleSettings.Default.AdvancedFeatureEnabled); _IsAdvancedFeatureVisible = FeatureToggles.FeatureToggles.IsEnabled( Properties.FeatureToggleSettings.Default.AdvancedFeatureVisible); tbMode.Text = Constants.databaseSettings; }

O código na Figura 10 mostra como o aplicativo avalia os alternadores de recursos e define as propriedades visível e habilitado do recurso da Calculadora do Windows usando os métodos de invólucro.

Figura 10 Usando o método de invólucro para definir as propriedades visível e habilitado da Calculadora do Windows

private void EvaluateFeatureToggles() { this.tbVersion.Text = Properties.CommonSettings.Default.Version; if (Properties.CommonSettings.Default.DatabaseSettings) { GetFeatureTogglesFromStore(); } else { GetFeatureTogglesFeatureToggleFromSettings(); } if (_IsAdvancedFeatureEnabled) { _IsAdvancedFeatureVisible = true; } SetAdvancedFeatureEnabled(_IsAdvancedFeatureEnabled); SetAdvancedFeatureVisible(_IsAdvancedFeatureVisible); }

O código a seguir mostra a função de invólucro para ocultar ou mostrar elementos da interface do usuário associados ao recurso Funções Avançadas:

private void SetAdvancedFeatureVisible(bool state) { this.btnBkspc.Visible = state; this.btnSqrt.Visible = state; this.btnPercent.Visible = state; this.btnReciprocal.Visible = state; this.btnPlusMinus.Visible = state; }

A Calculadora do Windows se beneficia da biblioteca de classe reutilizável para encapsular todos os processamentos associados com a tabela FeatureToggle. Ao usar esta biblioteca de classes, o código que usa o arquivo ConfigSettings é quase idêntico ao código que usa a tabela do banco de dados FeatureToggle.

Conclusão

O benefício dos alternadores de recursos é que recursos novos e aprimorados são verificados para a ramificação principal, para que sejam testados e integrados de forma contínua com a base de códigos existente no momento da compilação. Anteriormente, o código de recursos novos e aprimorados geralmente não eram integrados com a base de códigos até estar mais próximo do prazo da liberação, o que é arriscado e muito perigoso. Tanto os alternadores de recursos como as ramificações recursos são abordagens viáveis que você pode usar para conseguir uma liberação estável com apenas recursos concluídos que passaram nos testes de QA necessários. A escolha para usar um ou outro depende das sua necessidades e de seus processos de desenvolvimento em vigor.

Bill Heys é um consultor ALM sênior com Soluções e Processo de Design. Ele foi anteriormente um consultor ALM sênior junto à Microsoft. Ele é um membro do Microsoft Visual Studio ALM Rangers, desenvolvedor líder na diretriz de mesclagem e ramificação Rangers e um contribuidor da liberação da diretriz de controle da versão Rangers. Entre em contato com ele no email bill.heys@live.com.

AGRADECEMOS aos seguintes especialistas técnicos pela revisão deste artigo: Michael Fourie (consultor independente), Micheal Learned (Microsoft), Matthew Mitrik (Microsoft) e Willy-Peter Schaub (Microsoft)