TODO comenta com prazos?

51

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.

Joshua Walsh
fonte
19
A questão TODO é mais uma questão de disciplina do que de ferramentas.
Brandon
16
Acho que todos os seres humanos cometem erros, e as ferramentas podem ser uma boa maneira de mitigar isso.
Joshua Walsh
3
Que tal fazer isso programaticamente. Quero dizer, escreva em um aluno sua versão. Se o aplicativo não iniciar, se a versão for igual a == 56 com a mensagem "classe y", você precisará desse recurso. Você pode ter uma lista dessas mensagens. O que você acha?
Tomer Ben David
6
Dirigido às pessoas que não dizem nada, eu discordo: nossa base de código se baseia em muitos outros componentes nos quais não trabalhamos, então usamos 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.
TemporalWolf

Respostas:

53

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:

  1. scripts de banco de dados preapp
  2. aplicativos da web
  3. scripts de banco de dados postapp
  4. scripts de banco de dados da janela de manutenção

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.

Brandon
fonte
18
Todo comentários são uma maneira terrível de rastrear e priorizar o trabalho. Eles são uma maneira válida de explicar por que um pedaço de código meio acabado está balançando ao vento. Em um mundo perfeito, nenhum código faz isso. Enquanto isso, neste ...
candied_orange 30/05
6
... às vezes é bom ter uma maneira de rastrear dívidas técnicas que nenhuma quantidade de depriorização de para o chefe pode esconder. Claro que você não receberá crédito por corrigi-lo. Às vezes você conserta de qualquer maneira.
Candied_orange 30/05
3
Portanto, a estratégia do pós-aplicativo é que essas migrações sejam executadas quando a implantação do aplicativo for concluída com êxito? E o código? Digamos que você esteja renomeando uma coluna de last_name para sobrenome. Seu código antigo usa last_name. Você migra o banco de dados para adicionar sobrenome e altera seu código para usar sobrenome, se disponível, caso contrário, last_name. Após a implantação ter sido totalmente implementada, você executa a próxima migração, solte a coluna last_name antiga. Mas seu código ainda contém o código para last_name, que agora não é utilizado e, portanto, dívida técnica. Como você impõe a limpeza disso?
Joshua Walsh
3
Embora o gerenciamento de itens de ação nos comentários seja realmente uma maneira terrível, fazer com que os comentários criem problemas automaticamente em um sistema de rastreamento pode ser uma boa ferramenta para não esquecer de fazê-lo, porque você está atualmente no meio da codificação de algo e não quer mudar muito contexto ao sistema de rastreamento de problemas.
PlasmaHH
6
IMHO esta resposta está faltando o ponto. O OP solicitou uma solução em que o IC notificasse a equipe quando uma limpeza importante foi esquecida, sem sobrecarregar o "sistema de gerenciamento de problemas" (os comentários do TODO eram apenas um exemplo, talvez não a solução ideal para isso). O OP deu algumas boas razões para ele não querer usá-lo antes. No entanto, essa resposta sugere confiar completamente no backlog, que no caso do OP nada mais é que o seu "sistema de gerenciamento de problemas". Portanto, IMHO esta resposta ignora o cerne da questão e não apresenta uma solução.
Doc Brown
24

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:

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.

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:

  1. converse com sua gerência por que essa é uma má ideia.

  2. 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.

Jens Schauder
fonte
Bom conselho, vou pensar em maneiras pelas quais podemos fazer com que o sistema de gerenciamento de problemas funcione para nós para esse fim. Também gosto muito da ideia de "Talvez até algo automático faça sentido onde você faz logicamente uma implantação". Estou tentando pensar em maneiras de fazer isso. Não tenho certeza se é realisticamente possível.
Joshua Walsh
11
É inteiramente razoável ter comentários do formulário // 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.
30717 Kevin
9

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.

O que você está pedindo é factível se você estiver disposto a fazer o trabalho e seguir adiante.

// TODO by v55: Crie migração para mover restrições para a nova coluna, remova referências à coluna antiga no aplicativo // TODO by v56: Crie migração para descartar a coluna antiga

grep para //TODO by v55quando 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.

candied_orange
fonte
4
Se isso acontecer, não fazemos recomendações aqui.
Candied_orange 30/05
3
Se houver um nome genérico para esse tipo de coisa, mas se você ler a página que vinculou a linha sobre recomendações, você será
direcionado
6
Para deixar claro, é ao seu comentário que estou objetando, em vez de toda a questão.
Candied_orange 30/05
2
Os sites @YM_Industries SE tendem a ser independentes, a recomendação é basicamente respostas simples com links para sites externos ou convidamos você a pesquisar no Google em vez de em um link, mas no final é o mesmo. Eles podem expirar e ficar mortos. Portanto, uma pergunta sobre recomendação é fora de tópico; no entanto, alguém quer mencionar uma ferramenta como complemento de uma resposta ou um simples comentário, ele pode fazê-lo.
Walfrat 30/05
2
"Eu queria saber se existe uma solução existente" - tente perguntar-nos em softwarerecs.stackexchange.com
Mawg
4

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.

tjheslin1
fonte
11
Isso é legal! Também usamos o JIRA, posso usar isso. Realmente não resolve minhas preocupações sobre criar confusão no nosso sistema de gerenciamento de problemas, mas pelo menos garantirá que eles não possam ser esquecidos.
Joshua Walsh
@YM_Industries Estou feliz. Ficaria feliz em aceitar qualquer contribuição ou trabalhar em qualquer questão levantada.
Tjheslin1 31/05
4

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 SSNpara TaxID, um requisito comum ao se internacionalizar.

Para fazer isso acontecer, talvez você tenha temporariamente a TaxIDe uma SSNcoluna. 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 a SSNcoluna 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

  1. Adicione uma única tabela chamada Configurationcom duas colunas Namee Value.

  2. Adicione uma linha com Name"TargetVersion" e defina Valuea versão da nova compilação a ser implantada.

  3. Adicione uma linha com Name"CompatibleWith" e defina o Valuenú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

  1. Adicione um script que crie uma nova coluna TaxID, lado a lado SSNe a preencha a partir da SSNcoluna. Coloque esse código em uma Ifinstrução que verifique TargetVersion; se a versão de destino estiver muito baixa (por exemplo, a TaxIDainda não é necessária), pule.

    SELECT @TargetVersion = TargetVersion FROM Configuration
    IF @TargetVersion < '102' THEN RETURN
    ALTER TABLE Customer ADD COLUMN taxID VarChar(12) NOT NULL
    UPDATE Customer SET TaxID = SSN
    
  2. Adicione um script que crie um gatilho que seja preenchido TaxIDao inserir ou atualizar SSNe vice-versa. Coloque esse código em uma Ifdeclaração que verifique a versão de destino e a versão compatível; pule se TargetVersion for muito baixo ( TaxIDnão é necessário) ou se a versão CompatibleWith for muito alta (o SSNcampo não é necessário).

    SELECT @TargetVersion  = TargetVersion,
           @CompatibleWith = CompatibleWith 
    FROM Configuration
    IF @TargetVersion  < '102' THEN RETURN
    IF @CompatibleWith > '101' THEN RETURN
    CREATE TRIGGER SSNAndTaxIDTrigger ON Customer etc.
    
  3. Adicione um script para remover a SSNcoluna. Coloque em uma Ifdeclaração que remova a coluna apenas se a versão CompatibleWith for alta o suficiente ( SSNnão é mais necessária).

    SELECT @CompatibleWith = CompatibleWith FROM Configuration
    IF @CompatibleWith <= '101' THEN RETURN
    IF OBJECT_ID('SSNAndTaxIDTrigger') IS NOT NULL DROP TRIGGER SSNAndTaxIDTrigger
    IF EXISTS (SELECT * FROM syscolumns c JOIN sysobject o ON o.id = c.is WHERE o.Name = 'Custeomr' AND c.Name = 'SSN') BEGIN
        ALTER TABLE Customer DROP COLUMN SSN
    END
    

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 Configurationtabela 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.

John Wu
fonte
Eu realmente gosto dessa abordagem, é mais elegante que os comentários do ToDo. Pensei nisso logo após fazer essa pergunta e estava pensando em fazer outro post perguntando sobre a melhor forma de implementar isso, mas achei que eu faria minha própria pesquisa primeiro. O truque para nós é que estamos usando o Phinx para nossas migrações de banco de dados, e ele realmente não suporta isso. Quando tiver tempo, procurarei uma maneira de estendê-lo para suportar esse tipo de fluxo de trabalho. Essa abordagem não resolve o problema de como garantir que o código de compatibilidade com versões anteriores seja removido do meu nível de aplicativo, mas é elegante para o problema do banco de dados.
Joshua Walsh
1

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.

Eternal21
fonte
11
Sim, eu esperava idealmente tratar um TODO expirado como um teste reprovado. A quantidade de impulsos contra os TODOs me surpreendeu um pouco, sei que eles não substituem um sistema de gerenciamento de problemas, mas dada a prevalência de TDD / BDD, fica claro que não há problema real em definir requisitos em código e usar código para impor conclusão do recurso.
Joshua Walsh
-2

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.

mpiazza
fonte
11
Replicar o banco de dados em uma implantação azul / verde causa muita dor de cabeça. Quando meu ambiente de produção está entre azul e verde (50% de carga distribuída para cada um, por exemplo), preciso que o código de replicação mantenha os dois bancos de dados sincronizados, mesmo que seus esquemas sejam diferentes. A partir da pesquisa que fiz, parece que a maioria das pessoas no mundo real tem uma instância de banco de dados compartilhada entre suas pilhas azuis e verdes. Não vejo isso como um problema importante, desde que as migrações de banco de dados sejam bastante rápidas. Pilhas azuis / verdes precisam inerentemente compartilhar alguns recursos, no mínimo o balanceador de carga / proxy reverso.
Joshua Walsh