fundo
Estou trabalhando em uma equipe que procura implementar implantações com tempo de inatividade zero. Planejamos usar uma estratégia de implantação azul / verde para conseguir isso. Uma das coisas que estou percebendo ao fazer a pesquisa é como fica complicado fazer alterações no banco de dados. Uma operação simples como renomear uma coluna pode levar três ciclos completos de lançamento até que seja concluída!
Parece-me que ter a distribuição completa de uma mudança leva vários ciclos de lançamento apresenta muito potencial para erro humano. No artigo vinculado, mostra que as alterações de código são necessárias para duas liberações e uma migração de banco de dados é necessária para três liberações.
O que estou olhando
Atualmente, se queremos lembrar de fazer algo, podemos criar um ticket em nosso sistema de gerenciamento de problemas, o que cria confusão e também pode ser movido para um sprint posterior ou para o backlog pela gerência; ou podemos criar um comentário TODO, que provavelmente será esquecido completamente.
O que estou procurando é uma maneira de um comentário TODO ter um prazo contra ele, e nosso sistema de Integração Contínua (atual indeciso que usaremos) rejeitaria a compilação se esse prazo expirasse.
Por exemplo, se renomearmos uma coluna, poderemos criar a migração inicial para ela e, em seguida, dois comentários TODO para garantir que as duas migrações restantes sejam criadas:
// TODO by v55: Create migration to move constraints to new column, remove references to old column in app
// TODO by v56: Create migration to drop old column
Isso parece bastante simples de implementar, mas estou me perguntando se algo assim já existe, porque não quero reinventar a roda.
Pensamentos adicionais
Sinto que posso estar sofrendo do problema XY aqui, dado que as implantações contínuas e as implantações azul / verde são consideradas uma prática recomendada, parece estranho que eu não consiga encontrar uma solução para tornar as atualizações do banco de dados menos dolorosas. Se você acha que estou analisando completamente a coisa errada, informe-me em um comentário! Dito isto, o exemplo do banco de dados que dei é apenas um exemplo, e acho que os comentários do TODO com datas de vencimento também seriam úteis em outras situações, portanto, mesmo que eu esteja me aproximando dessa situação específica de maneira errada, gostaria muito de responder às minhas perguntas. pergunta real também. Obrigado!
Edição: Acabei de pensar em outra situação em que isso poderia ser útil. Se você usar Alternâncias de recursos para ativar partes do seu aplicativo quando estiverem prontas, tenha cuidado para limpá-las; caso contrário, poderá acabar com Alternar dívida . Comentários com prazos podem ser uma boa maneira de lembrar disso.
fonte
TODO <Bug#>:
para rastrear soluções alternativas para problemas com outros componentes. Quando um bug é solucionado em um desses componentes, você pode encontrar e resolver facilmente as soluções alternativas relevantes. Ele não substitui um rastreador de problemas, facilita a manutenção.Respostas:
Esta questão é realmente duas perguntas em uma.
Todo comments
De todas as maneiras de rastrear itens de ação, esse é o pior. Os comentários do TODO são bons durante o trabalho ativo ou como uma forma de sugestão para um mantenedor "aqui está algo que talvez possa ser melhorado no futuro". Mas se você confiar nos comentários do TODO para concluir o trabalho, estará fadado ao fracasso.
o que fazer sobre isso
Os comentários do TODO são basicamente dívida técnica, portanto devem ser tratados como qualquer outra dívida técnica. Lide com eles imediatamente, se tiver tempo, ou coloque-os na lista de pendências para que possam ser rastreados e priorizados.
De um modo geral, e isso é totalmente opinativo e aberto a debate, os comentários do TODO podem ser considerados um cheiro de código. Se um comentário do TODO chegar a um controle de versão, você deve se perguntar: será que o seguirá agora? Se não, tudo bem. Seja honesto consigo mesmo e coloque-o na lista de pendências.
A maneira como você gerencia esse backlog se resume a processos de negócios, políticas da empresa e talvez alguma autonomia pessoal. Mas você ainda precisa de uma lista de pendências monitorada e priorizada para garantir que isso aconteça.
Alterações no banco de dados
Sim, as alterações no banco de dados são complicadas com uma política de tempo de inatividade zero. Alguns truques para ajudar a torná-lo menos doloroso:
Processo pós-implantação
Crie um processo pós-implantação que seja executado como parte da mesma versão. No entanto, você quer que ele funcione. No último sistema em que trabalhei, projetei uma implantação em quatro fases:
A idéia era que, sempre que possível, colocaríamos o máximo possível de alterações no banco de dados.
Postapp foi reservado para os casos incomuns em que precisávamos fazer alterações de esquema incompatíveis. Nesses casos, o preapp faria uma alteração suficiente para tornar o novo código do aplicativo compatível (talvez criando uma exibição temporária de compatibilidade), e o postapp limparia esses artefatos temporários.
A fase da janela de manutenção foi reservada para alterações que realmente exigiam tempo de inatividade ou onde o risco ou custo de uma implantação ativa não valeu a pena. Por exemplo, scripts que alteram grandes quantidades de dados podem precisar bloquear uma tabela inteira.
Implante frequentemente
Se você implantar novos lançamentos com frequência suficiente, poderá chegar a um ponto em que a alteração entre 2 ou 3 lançamentos é trivial. Ciclos de liberação longos amplificam o custo das alterações no banco de dados.
fonte
Não use TODOs. Você já tem uma lista TODO em seu projeto. Chama-se rastreador de problemas.
Eu acho que o verdadeiro problema está nesta frase:
Se o rastreador de problemas cria muita confusão, encontre maneiras de corrigir isso. Talvez um tipo / tag de edição especial que envolva menos cerimônia. Talvez sub-questões. Talvez menos cerimônia por completo. Nós realmente não podemos dizer. Mas se o rastreador de problemas cria tanto trabalho, que as pessoas preferem formular uma pergunta elaborada em um fórum público do que apenas adicionar esse problema, algo está seriamente errado.
Se seu gerenciamento atrasar indevidamente a última parte de uma tarefa, você terá duas opções:
converse com sua gerência por que essa é uma má ideia.
lidar com isso como uma única tarefa. Essa pode ser a solução padrão-ouro. Em um mundo perfeito, você poderá fazer as três alterações necessárias em cada etapa. Aplique um ao ramo principal, deixe-o construir e implantar. Enquanto isso, aplique o segundo ao ramo principal, deixe-o construir e implantar e assim por diante, para que tudo aconteça no mesmo sprint; caso contrário, não será feito. Talvez até algo automático faça sentido onde você faz logicamente uma implantação, mas na verdade é dividido em três.
fonte
// TODO(#12345): Frobnicate the sprocket before passing it along
, desde que o bug # 12345 seja um número de problema "real" e o problema seja atribuído a alguém. Isso facilita a leitura da fonte, esclarecendo: "Não, a etapa frobnicada não está escondida em um dos métodos auxiliares, é simplesmente não implementada. Veja o bug # 12345 para obter mais contexto". Idealmente, você deve executar uma operação diária na base de código procurando números de problemas fechados ou inválidos, é claro.O que você está pedindo é factível se você estiver disposto a fazer o trabalho e seguir adiante.
grep para
//TODO by v55
quando for a hora de implantar a v55. A implantação de implantação executa um script que faz isso como um teste de integração.Você pode vincular 55 ao rastreamento de versão ou apenas solicitá-lo.
Fica interessante se você deseja verificar // TODO by v54 ao fazer 55. Em vez disso, pesquise a base de código 55 vezes apenas pesquise // TODO by. Em seguida, filtre o resultado de 1 a 55. Agora, 56 não causará falha.
Você pode pensar "ah, não precisaremos disso. Vamos consertar isso sempre que tivermos o cheque". Não. Não, você não vai.
fonte
Tivemos um problema muito semelhante em nossa equipe. Para resolver isso, escrevemos uma verificação de análise estática que lida com esses TODOs, verificando o problema do JIRA ou do Git que eles fazem referência. Nossa criação falha quando o problema especificado passa pela coluna "Em desenvolvimento".
Portanto, podemos ter confortavelmente os TODO sem nos preocuparmos com o fato de eles serem esquecidos.
Eu criei uma implementação de código aberto disso, em Java. Sim, um aviso é que eu escrevi isso, mas como eu disse, é completamente de código aberto e licenciado.
A ferramenta é chamada Westie e um exemplo do verificador de problemas do Jira está no README.md. Veja também o GitIssueAnalyser.
Para impedir a autopromoção, se você tiver mais alguma dúvida, envie-me uma mensagem. Se você decidir usá-lo e tiver alguma sugestão, levante problemas no github.
fonte
Não faça. Faça isso agora.
TLDR: escreva (e teste) seus scripts de banco de dados agora, não mais tarde; apenas codifique-os para que sua execução seja contingente na versão do banco de dados.
Exemplo
Por exemplo, vamos imaginar que você deseja alterar o nome de uma coluna de
SSN
paraTaxID
, um requisito comum ao se internacionalizar.Para fazer isso acontecer, talvez você tenha temporariamente a
TaxID
e umaSSN
coluna. E, embora ofereça suporte às duas versões, você terá um gatilho para atualizar uma da outra. Mas você não deseja manter esse gatilho indefinidamente; portanto, mais tarde, quando a compatibilidade com versões anteriores não for mais necessária, você deseja que esse gatilho seja removido (e aSSN
coluna caiu). Vamos codificar tudo isso antecipadamente, sem a necessidade de itens de tarefas.Em nosso exemplo, implementaremos a versão 102 (que possui a nova coluna), mantendo a compatibilidade com a versão 101 (que não possui).
Aqui estão os passos.
1. Configure a tabela de controle de versão
Adicione uma única tabela chamada
Configuration
com duas colunasName
eValue
.Adicione uma linha com
Name
"TargetVersion" e definaValue
a versão da nova compilação a ser implantada.Adicione uma linha com
Name
"CompatibleWith" e defina oValue
número de versão mínimo com o qual a implantação deve ser compatível.Inspecione e atualize essas linhas antes de cada implantação.
2. Modifique os scripts de implantação
Adicione um script que crie uma nova coluna
TaxID
, lado a ladoSSN
e a preencha a partir daSSN
coluna. Coloque esse código em umaIf
instrução que verifique TargetVersion; se a versão de destino estiver muito baixa (por exemplo, aTaxID
ainda não é necessária), pule.Adicione um script que crie um gatilho que seja preenchido
TaxID
ao inserir ou atualizarSSN
e vice-versa. Coloque esse código em umaIf
declaração que verifique a versão de destino e a versão compatível; pule se TargetVersion for muito baixo (TaxID
não é necessário) ou se a versão CompatibleWith for muito alta (oSSN
campo não é necessário).Adicione um script para remover a
SSN
coluna. Coloque em umaIf
declaração que remova a coluna apenas se a versão CompatibleWith for alta o suficiente (SSN
não é mais necessária).3. Teste
Teste sua implantação com qualquer combinação de números de versão azul / verde que você deseja oferecer suporte na produção. Você pode testar assim que o código estiver pronto, manipulando a
Configuration
tabela em seu ambiente de controle de qualidade.4. No seu manual de implantação
Adicione uma etapa para um engenheiro atualizar a versão CompatibleWith e as linhas TargetVersion. Se você estiver implantando no Blue, defina TargetVersion como o número da versão do Blue e a versão CompatibleWith como o número da versão do Green; inverta-os se você estiver implantando o Green.
Armadilhas
Não há problema em seus scripts de implantação fazer referência e confiar nesses números de versão mantidos nessa tabela de banco de dados. NÃO código de tempo de execução.
Se você começar a escrever seu código de tempo de execução para inspecionar os números de versão, estará introduzindo um novo nível de complexidade em seu aplicativo que pode se tornar um grande problema de manutenção. Cada caminho de execução do tempo de execução deve ser testado; se você levar essas condições adiante, o controle de qualidade terá que montar uma matriz de dor para validá-las a cada liberação. Meu conselho é manter condições como essas apenas nos scripts de implantação.
O resultado de tudo isso
No final, você deve poder escrever todo o código antecipadamente (e testá-lo também) sem medo de que seja executado muito cedo. Além disso, o código limpará o gatilho de compatibilidade com versões anteriores quando chegar a hora, sem que você precise se preocupar com isso.
Dessa forma, você pode escrever e testar todo o código antecipadamente, quando estiver pensando, e não precisará lidar com esses comentários confusos do ToDo.
fonte
Você está recebendo muitas críticas à sua ideia de TODO, mas pessoalmente não vejo problema nisso. No final, a melhor (e mais fácil) maneira de garantir que a migração entre em produção é falhar em um teste de unidade, se não acontecer. Você levará literalmente menos de um minuto para criar uma função de migração vazia que lança uma exceção se a versão for 55 ou mais (ou quaisquer que sejam os requisitos).
Então, se você tentar lançá-lo, você terminará com um teste com falha e alguém terá que transformar essa exceção em um código de migração real.
fonte
Ninguém parece estar se concentrando na raiz de sua reclamação, que é o fato de que as alterações no banco de dados podem levar muitos ciclos de lançamento. Ele quer continuar com sua agenda de implantação azul / verde e a solução já deve estar lá, mas, a menos que eu esteja perdendo algo, sua descrição parece indicar que há apenas um banco de dados compartilhado pelos dois sistemas. Não é um sistema azul / verde verdadeiro, se for esse o caso. Como parece que o banco de dados é o pólo mais longo da barraca, ele também deve ser duplicado, para que, independentemente de quanto tempo ou quantos ciclos de liberação sejam necessários para implementar as alterações do banco de dados no sistema offline, eles não serão ativados até a conclusão e totalmente testado. No sistema offline provisório, os scripts podem manter o banco de dados offline totalmente atualizado diariamente.
fonte