TODO commentaires avec des délais?

51

Contexte

Je travaille dans une équipe qui cherche à mettre en œuvre des déploiements sans temps d'arrêt. Nous prévoyons d'utiliser une stratégie de déploiement bleu / vert pour y parvenir. En réalisant cette recherche, je réalise notamment à quel point il est difficile de modifier les bases de données. Une opération simple, comme renommer une colonne, peut prendre 3 cycles complets avant d'être complétée!

Il me semble que le déploiement complet d'un changement prend plusieurs cycles de publication, ce qui crée un potentiel d'erreur humaine. Dans l'article lié, il est montré que les modifications de code sont nécessaires pour 2 versions et qu'une migration de base de données est nécessaire pour 3 versions.

Ce que je cherche

Actuellement, si nous voulons nous souvenir de faire quelque chose, nous pouvons créer un ticket dans notre système de gestion des problèmes, ce qui crée un fouillis et peut également être déplacé vers un sprint ultérieur ou le retard accumulé par la direction; ou nous pouvons créer un commentaire TODO, qui sera probablement complètement oublié.

Ce que je recherche, c’est la manière dont un commentaire TODO peut être assorti d’un délai, et notre système d’intégration continue (actuellement indécis, que nous utiliserons) rejetterait la construction si ce délai était expiré.

Par exemple, si nous renommons une colonne, nous pourrions créer la migration initiale correspondante, puis deux commentaires TODO pour garantir la création des deux migrations restantes:

// 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

Cela semble assez simple à mettre en œuvre, mais je me demande si quelque chose comme cela existe déjà, car je ne veux pas réinventer la roue.

Pensées supplémentaires

Je pense que je pourrais souffrir du problème XY ici, étant donné que les déploiements progressifs et les déploiements bleu / vert sont considérés comme une pratique exemplaire. Il semble donc étrange que je ne trouve pas de solution pour rendre les mises à jour de base de données moins pénibles. Si vous pensez que je cherche à me tromper complètement, faites-le-moi savoir dans un commentaire! Cela dit, l'exemple de base de données que j'ai donné n'est qu'un exemple, et je pense que les commentaires de TODO avec les dates d'échéance seraient également utiles dans d'autres situations. Par conséquent, même si j'aborde cette situation en particulier de manière erronée, j'aimerais vraiment répondre à mes questions. question réelle aussi. Merci!

EDIT: Je viens de penser à une autre situation où cela pourrait être utile. Si vous utilisez Feature Toggles pour activer des parties de votre application lorsqu'elles sont prêtes, vous devez faire attention à les nettoyer, sinon vous risquez de vous retrouver avec Basculer la dette . Les commentaires avec des délais pourraient être un bon moyen de s'en souvenir.

Joshua Walsh
la source
19
La question TODO relève davantage de la discipline que de l’outillage.
Brandon
16
Je pense que les humains font tous des erreurs, et l’outillage peut être un bon moyen d’atténuer cela.
Joshua Walsh
3
Qu'en est-il de faire cela par programme, comme. Je veux dire écrire dans un membre du groupe votre version. Échec de démarrage de l'application si la version est égale == 56 avec le message "classe y" doit avoir cette fonctionnalité, vous pouvez avoir une liste de ces messages. Qu'est-ce que tu penses?
Tomer Ben David
6
En ce qui concerne les opposants, je ne suis pas d'accord: notre base de code repose sur de nombreux composants sur lesquels nous ne travaillons pas, nous utilisons donc TODO <Bug#>:pour suivre les solutions de contournement des problèmes liés aux autres composants. Lorsqu'un bogue est effacé sur l'un de ces composants, vous pouvez facilement trouver et résoudre les solutions de contournement pertinentes. Il ne remplace pas un outil de suivi des problèmes, il facilite la maintenance.
TemporalWolf

Réponses:

53

Cette question est vraiment deux questions en une.

Todo commentaires

De toutes les façons de suivre les actions, c'est la pire. Les commentaires de TODO sont bons pendant le travail actif ou comme moyen de suggestion au responsable, "voici quelque chose qui pourrait peut-être être amélioré dans le futur". Mais si vous vous fiez aux commentaires de TODO pour accomplir votre travail, vous êtes voué à l'échec.

Que faire à ce sujet

Les commentaires de TODO sont essentiellement des dettes techniques, ils doivent donc être traités comme toute autre dette technique. Vous pouvez soit vous en occuper immédiatement, si vous en avez le temps, soit les mettre dans l'arriéré afin qu'ils puissent être suivis et hiérarchisés.

De manière générale, et ceci est totalement une opinion et ouverte au débat, les commentaires de TODO pourraient être considérés comme une odeur de code. Si un commentaire TODO parvient jusqu'à être enregistré dans le contrôle de version, vous devez vous demander: allez-vous le suivre maintenant? Si non, ça va. Soyez juste honnête avec vous-même et mettez-le dans l'arriéré.

La façon dont vous gérez cet arriéré dépend des processus opérationnels, de la politique de l'entreprise et peut-être de l'autonomie personnelle. Mais vous avez toujours besoin d'un arriéré suivi et hiérarchisé pour vous en assurer.

Changements de base de données

Oui, les modifications de base de données sont délicates avec une politique de zéro temps d'arrêt. Quelques astuces pour aider à le rendre moins douloureux:

Processus post-déploiement

Créez un processus post-déploiement qui s'exécute dans la même version. Cependant, vous voulez que cela fonctionne. Sur le dernier système sur lequel j'ai travaillé, j'ai conçu un déploiement en 4 phases:

  1. scripts de base de données preapp
  2. applications web
  3. scripts de base de données postapp
  4. scripts de base de données de fenêtre de maintenance

L'idée était que, dans la mesure du possible, nous intégrerions autant que possible les modifications apportées à la base de données.

Postapp était réservé aux cas inhabituels dans lesquels nous devions apporter des modifications de schéma incompatibles. Dans ces cas, preapp apporterait une modification suffisante pour rendre le nouveau code d'application compatible (en créant éventuellement une vue temporaire), et postapp supprimerait tout artefact temporaire de ce type.

La phase de la fenêtre de maintenance était réservée aux modifications qui nécessitaient réellement des temps d'arrêt ou pour lesquelles le risque ou le coût d'un déploiement réel n'en valait pas la peine. Par exemple, les scripts qui modifient des quantités énormes de données peuvent avoir besoin de verrouiller une table entière.

Déployer fréquemment

Si vous déployez suffisamment de nouvelles versions, vous pouvez atteindre un point où effectuer une modification sur 2 ou 3 versions est simple. Les cycles de publication longs amplifient le coût des modifications apportées à la base de données.

Brandon
la source
18
Les commentaires de Todo sont un moyen terrible de suivre et de hiérarchiser le travail. Ils sont un moyen valable d’expliquer pourquoi un morceau de code à moitié fini bat au vent. Dans un monde parfait, aucun code ne fait jamais cela. Pendant ce temps, dans celui-ci ...
candied_orange
6
... il est parfois agréable de disposer d'un moyen de suivre la dette technique qu'aucune réduction de priorité du chef ne peut dissimuler. Bien sûr, vous ne recevrez aucun crédit pour le réparer. Parfois, vous le réparez quand même.
candied_orange
3
La stratégie avec post-application consiste donc à ce que ces migrations soient exécutées une fois que le déploiement de l'application est terminé avec succès? Qu'en est-il du code? Disons que vous renommez une colonne de last_name en nom de famille. Votre ancien code utilise last_name. Vous migrez la base de données pour ajouter le nom de famille et changez votre code pour utiliser le nom de famille s'il est disponible, sinon nom_nom. Une fois le déploiement entièrement déployé, vous exécutez la migration suivante en supprimant l'ancienne colonne last_name. Mais votre code contient toujours le code de nom de famille, qui est maintenant inutilisé et donc une dette technique. Comment imposez-vous le nettoyage?
Joshua Walsh
3
Bien que la gestion des actions dans les commentaires soit effectivement un moyen épouvantable, le fait de créer automatiquement des problèmes dans un système de suivi peut être un bon outil à ne pas oublier car vous êtes en train de coder quelque chose et que vous ne voulez pas basculer dur contexte au système de suivi des problèmes.
PlasmaHH
6
IMHO cette réponse manque le point. Le PO a demandé une solution permettant à l’IC d’indiquer à l’équipe qu’une opération de nettoyage importante était oubliée, sans encombrer le "système de gestion des problèmes" (les commentaires de TODO n'étaient qu'un exemple, peut-être pas la solution idéale pour cela). Le PO a donné quelques bonnes raisons pour lesquelles il ne veut pas l'utiliser par la suite. Néanmoins, cette réponse suggère de s’appuyer entièrement sur l’arriéré, qui n’est en réalité que son "système de gestion des problèmes". Donc, à mon humble avis, cette réponse ignore le cœur de la question et ne présente pas de solution.
Doc Brown
24

N'utilisez pas de TODO. Vous avez déjà une liste TODO dans votre projet. C'est ce qu'on appelle le suivi des problèmes.

Je pense que le vrai problème est dans cette phrase:

nous pouvons créer un ticket dans notre système de gestion des problèmes, ce qui crée un fouillis et peut également être déplacé vers un sprint ultérieur ou le backlog par la direction.

Si votre outil de suivi des problèmes génère beaucoup de fouillis, trouvez des moyens de remédier à cela. Peut-être un type / tag spécial qui implique moins de cérémonie. Peut-être des sous-problèmes. Peut-être moins de cérémonie tout à fait. Nous ne pouvons pas vraiment dire. Mais si votre système de suivi des problèmes crée tellement de travail, que les gens préfèrent formuler une question complexe sur un forum public que pour simplement ajouter ce problème, quelque chose ne va vraiment pas.

Si votre gestion retarde indûment la dernière partie d'une tâche, vous avez deux options:

  1. demandez à votre direction pourquoi c’est une mauvaise idée.

  2. gérez-le comme une tâche unique. Cela pourrait être la solution de référence. Dans un monde parfait, vous devriez être capable de faire les trois changements nécessaires à chaque étape. Appliquez-en un à la branche principale, laissez-la se construire et se déployer. Pendant ce temps, appliquez la seconde à la branche principale, laissez-la se construire et se déployer, etc., de manière à ce que tout se passe dans le même sprint. Sinon, ce n'est pas fait. Peut-être même que quelque chose d'automatique a du sens lorsque vous faites logiquement un déploiement, mais il est en fait divisé en 3.

Jens Schauder
la source
Bon conseil, je vais réfléchir aux moyens de faire en sorte que le système de gestion des problèmes fonctionne pour nous à cette fin. J'aime aussi beaucoup l'idée de "Peut-être même quelque chose d'automatique a-t-il du sens si vous faites logiquement un déploiement", j'essaie de trouver des moyens de le faire. Je ne suis cependant pas sûr que ce soit réaliste.
Joshua Walsh
11
Il est tout à fait raisonnable d'avoir des commentaires du formulaire // TODO(#12345): Frobnicate the sprocket before passing it along, à condition que le bogue n ° 12345 soit un "vrai" numéro de problème et que le problème soit attribué à quelqu'un. Cela rend la source plus facile à lire en clarifiant: "Non, l'étape frobnicate ne se cache pas dans l'une des méthodes d'assistance, elle est simplement complète et non implémentée. Consultez le bogue n ° 12345 pour plus de contexte." Idéalement, vous feriez une linter journalière sur la base de code à la recherche de numéros d’émission fermés ou invalides, bien sûr.
Kevin
9

Ce que je recherche, c’est la manière dont un commentaire TODO peut être assorti d’un délai, et notre système d’intégration continue (actuellement indécis, que nous utiliserons) rejetterait la construction si ce délai était expiré.

Ce que vous demandez est faisable si vous êtes prêt à faire le travail et à le suivre.

// TODO by v55: Créer une migration pour déplacer les contraintes vers une nouvelle colonne, supprimer les références à une ancienne colonne dans app // TODO by v56: Créer une migration pour supprimer l'ancienne colonne

grep pour //TODO by v55quand il est temps de déployer v55. Deploy build exécute un script qui le fait en tant que test d'intégration.

Vous pouvez associer 55 à votre suivi de version ou tout simplement demander une confirmation.

Cela devient intéressant si vous voulez vérifier // TODO by v54 en effectuant 55. Plutôt que de rechercher dans la base de code 55 fois, il vous suffit de rechercher // TODO by. Puis filtrez ce résultat de 1 à 55. Maintenant, 56 ne déclenchera pas un échec.

Vous pourriez penser "Oh, nous n'en aurons pas besoin. Nous réglerons cela à chaque fois que nous aurons le chèque". Non, vous ne le ferez pas.

confits_orange
la source
4
Si c'est le cas, nous ne faisons pas de recommandations ici.
candied_orange
3
S'il existe un nom générique pour ce genre de chose, mais que si vous lisez la page, vous avez lié la ligne
contenant des
6
Pour être clair, c'est votre commentaire que je m'oppose à toute la question.
candied_orange
2
Les sites @YM_Industries SE ont tendance à être autonomes, les recommandations sont des réponses simples avec des liens vers des sites externes, ou vous invitent à le rechercher sur Google au lieu d'un lien, mais c'est la même chose au final. Ils peuvent expirer et devenir morts. Donc, une question sur la recommandation est hors sujet, mais si quelqu'un veut mentionner un outil en complément d'une réponse ou d'un simple commentaire, il peut le faire.
Walfrat
2
"Je me demandais si une solution existante existait" - essayez de nous
contacter à l'adresse
4

Nous avons eu un problème très similaire dans notre équipe. Pour résoudre ce problème, nous avons écrit une vérification d'analyse statique qui gère ces TODO en vérifiant le problème JIRA ou le problème Git auquel ils font référence. Notre génération échoue lorsque le problème spécifié dépasse la colonne "En développement".

Par conséquent, nous pouvons facilement avoir des TODO sans nous soucier de les oublier.

J'ai créé une implémentation open-source de celui-ci, en Java. Oui, un avis de non-responsabilité est que j'ai écrit ceci, mais comme je l'ai dit, il s'agit d'une source complètement ouverte et d'une licence.

L'outil s'appelle Westie et un exemple de l' outil de vérification des problèmes de Jira figure dans le fichier README.md. Voir aussi le GitIssueAnalyser.

Pour éviter toute promotion personnelle, si vous avez d'autres questions, envoyez-moi un message. Si vous décidez de l'utiliser et que vous avez des suggestions, veuillez soulever les problèmes éventuels sur github.

tjheslin1
la source
1
C'est super! Nous utilisons JIRA aussi, je pourrais envisager d’utiliser ceci. Cela ne résout pas vraiment mes inquiétudes quant à la création de fouillis dans notre système de gestion des problèmes, mais au moins cela garantira qu'ils ne peuvent pas être oubliés.
Joshua Walsh
@YM_Industries Je suis content. Je serais heureux d'accepter toute contribution ou de travailler sur toute question soulevée.
tjheslin1
4

Ne pas faire. Fais le maintenant.

TLDR: écrivez (et testez) vos scripts de base de données maintenant, pas plus tard; il suffit de les coder pour que leur exécution dépende de la version de la base de données.

Exemple

Pour un exemple, imaginons que vous souhaitez modifier un nom de colonne de SSNà TaxID, une exigence commune lors du passage international.

Pour ce faire, vous aurez peut-être temporairement TaxIDune SSNcolonne et une . Et tout en prenant en charge les deux versions, vous aurez un déclencheur pour mettre à jour l’une de l’autre. Mais vous ne voulez pas garder ce déclencheur indéfiniment. Par conséquent, plus tard, lorsque la compatibilité en amont n'est plus nécessaire, vous souhaitez que ce déclencheur soit supprimé (et la SSNcolonne supprimée). Nous allons coder tout cela à l’avance sans qu’il soit nécessaire de créer des tâches.

Dans notre exemple, nous allons déployer la version 102 (qui contient la nouvelle colonne) tout en maintenant la compatibilité avec la version 101 (ce qui n’est pas le cas).

Voici les étapes.

1. Configurer la table de gestion des versions

  1. Ajouter une seule table appelée Configurationavec deux colonnes, Nameet Value.

  2. Ajoutez une ligne avec Name"TargetVersion" et définissez-le Valuesur la version de la nouvelle version à déployer.

  3. Ajoutez une ligne avec Name"CompatibleWith" et définissez le Valuesur le numéro de version minimum avec lequel le déploiement doit être compatible.

Inspectez et mettez à jour ces lignes avant chaque déploiement.

2. Modifier les scripts de déploiement

  1. Ajoutez un script qui crée une nouvelle colonne TaxID, côte à côte avec elle SSN, et la remplit à partir de la SSNcolonne. Placez ce code dans une Ifinstruction qui vérifie TargetVersion; Si la version cible est trop basse (c’est-à-dire qu’elle TaxIDn’est pas encore utilisée), ignorez.

    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. Ajoutez un script qui crée un déclencheur à remplir TaxIDlors de l'insertion ou de la mise à jour, SSNet inversement. Placez ce code dans une Ifinstruction qui vérifie la version cible et la version compatible. ignore si TargetVersion est trop bas (ce TaxIDn'est pas nécessaire) ou si la version CompatibleWith est trop élevée (le SSNchamp n'est pas nécessaire).

    SELECT @TargetVersion  = TargetVersion,
           @CompatibleWith = CompatibleWith 
    FROM Configuration
    IF @TargetVersion  < '102' THEN RETURN
    IF @CompatibleWith > '101' THEN RETURN
    CREATE TRIGGER SSNAndTaxIDTrigger ON Customer etc.
    
  3. Ajoutez un script pour supprimer la SSNcolonne. Placez-le dans une Ifinstruction qui supprime la colonne uniquement si la version CompatibleWith est suffisamment élevée ( SSNn'est plus nécessaire).

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

Assurez-vous de tester votre déploiement avec toute combinaison de numéros de version Bleu / Vert que vous souhaitez pouvoir prendre en charge en production. Vous pouvez tester dès que le code est prêt, en manipulant la Configurationtable dans votre environnement d'assurance qualité.

4. Dans votre livre de déploiement

Ajoutez une étape permettant à un ingénieur de mettre à jour les lignes CompatibleWith version et TargetVersion. Si vous effectuez un déploiement sur Blue, définissez TargetVersion sur le numéro de version de Blue et la version CompatibleWith sur le numéro de version de Green. inversez-les si vous déployez Green.

Les pièges

Les scripts de déploiement peuvent référencer et utiliser les numéros de version contenus dans cette table de base de données. PAS le code d'exécution.

Si vous commencez à écrire votre code d'exécution pour inspecter les numéros de version, vous introduisez un nouveau niveau de complexité dans votre application qui pourrait potentiellement devenir un énorme problème de maintenabilité. Chaque chemin d'exécution doit être testé. Si vous gardez ces conditions à l'avenir, QA devra créer une matrice de douleur pour les valider à chaque sortie. Mon conseil est de conserver les conditions telles que celles-ci dans les scripts de déploiement uniquement.

Le résultat de tout cela

En fin de compte, vous devriez être capable d'écrire tout le code à l'avance (et de le tester aussi) sans craindre qu'il ne soit exécuté trop tôt. En outre, le code effacera le déclencheur de compatibilité ascendante le moment venu sans que vous ayez à vous en préoccuper davantage.

De cette façon, vous pouvez écrire et tester tout le code dès le départ, sans avoir à vous soucier de ces commentaires désordonnés de la tâche.

John Wu
la source
J'aime beaucoup cette approche, elle est plus élégante que les commentaires de ToDo. J'y ai pensé peu de temps après avoir posé cette question et je pensais à un autre post demandant comment le mettre en œuvre au mieux, mais j'ai décidé de faire ma propre recherche en premier. Le truc pour nous est que nous utilisons Phinx pour nos migrations de base de données, et cela ne le supporte pas vraiment. Quand j'aurai le temps, je chercherai un moyen de l'étendre pour prendre en charge ce type de flux de travail. Cette approche ne résout pas le problème de la suppression du code de compatibilité ascendante de mon niveau d'application, mais elle est élégante pour le problème de base de données.
Joshua Walsh
1

Votre idée de TODO suscite beaucoup de critiques, mais je ne vois personnellement aucun problème avec cette idée. En fin de compte, le meilleur moyen (et le plus simple) de s'assurer que la migration passe en production consiste à échouer un test unitaire s'il ne réussit pas. Cela vous prendra littéralement moins d'une minute pour remplacer une fonction de migration vide qui lève une exception si la version est au moins égale à 55 (ou quelles que soient les conditions requises).

Ensuite, si vous essayez de le libérer, vous obtiendrez un test qui échouera et quelqu'un devra transformer cette exception en code de migration réel.

Éternel21
la source
1
Oui, j'espérais idéalement traiter un test TODO expiré comme un test ayant échoué. La quantité de réactions contre les TODO m'a un peu surpris, je sais qu'ils ne remplacent pas un système de gestion des problèmes, mais compte tenu de la prévalence de TDD / BDD, il est clair qu'il n'y a pas de réel problème en ce qui concerne la définition d'exigences dans le code et son utilisation. fonctionnalité complète.
Joshua Walsh
-2

Personne ne semble se focaliser sur la racine de sa plainte, à savoir que les changements de base de données peuvent prendre trop de cycles de publication. Il souhaite poursuivre son calendrier de déploiement bleu / vert et la solution devrait déjà être là, mais à moins que quelque chose ne me manque, sa description semble indiquer qu'il n'existe qu'une seule base de données partagée par les deux systèmes. Pas un vrai système bleu / vert si c'est le cas. Comme il semble que la base de données soit le long pôle de la tente, il convient de la dupliquer également, de sorte que peu importe la durée ou le nombre de cycles de publication nécessaires à la mise en œuvre des modifications de la base de données sur le système hors ligne, elles ne seront pas actives tant qu'elles ne seront pas terminées et entièrement testé. Dans l'intervalle, les scripts système hors ligne peuvent maintenir la base de données hors ligne entièrement mise à jour quotidiennement.

mpiazza
la source
1
La réplication de la base de données dans un déploiement bleu / vert provoque beaucoup de maux de tête. Lorsque mon env. Env est quelque part entre le bleu et le vert (charge répartie à 50% entre eux, par exemple), le code de réplication doit être synchronisé, même si leurs schémas sont différents. D'après les recherches que j'ai effectuées, il semble que la plupart des gens dans le monde réel partagent une instance de base de données entre leurs piles bleue et verte. Je ne vois pas cela comme un problème majeur tant que les migrations de bases de données sont assez rapides. Les piles bleues / vertes ont par nature besoin de partager certaines ressources, au minimum l'équilibreur de charge / proxy inverse.
Joshua Walsh