it-swarm.com.de

TODO-Kommentare mit Fristen?

Hintergrund

Ich arbeite in einem Team, das Bereitstellungen ohne Ausfallzeiten implementieren möchte. Wir planen, eine blau/grüne Bereitstellungsstrategie zu verwenden, um dies zu erreichen. Eines der Dinge, die mir bei der Recherche klar werden, ist, wie kompliziert es wird, Datenbankänderungen vorzunehmen. Ein einfacher Vorgang wie das Umbenennen einer Spalte kann vollständige Release-Zyklen dauern, bis er abgeschlossen ist!

Es scheint mir, dass die vollständige Einführung einer Änderung über mehrere Veröffentlichungszyklen hinweg viel Potenzial für menschliches Versagen birgt. In dem verlinkten Artikel wird gezeigt, dass Codeänderungen für 2 Releases erforderlich sind und eine Datenbankmigration für 3 Releases erforderlich ist.

Was ich suche

Wenn wir uns daran erinnern möchten, etwas zu tun, können wir derzeit ein Ticket in unserem Issue-Management-System erstellen, das Unordnung schafft und möglicherweise auch vom Management auf einen späteren Sprint oder den Rückstand verschoben wird. oder wir können einen TODO-Kommentar erstellen, der wahrscheinlich komplett vergessen wird.

Was ich suche, ist eine Möglichkeit, wie ein TODO-Kommentar eine Frist haben kann, und unser Continuous Integration-System (derzeit unentschlossen, das wir verwenden werden) würde den Build ablehnen, wenn diese Frist abgelaufen wäre.

Wenn wir beispielsweise eine Spalte umbenennen, können wir die anfängliche Migration dafür erstellen und dann zwei TODO-Kommentare, um sicherzustellen, dass die verbleibenden zwei Migrationen erstellt werden:

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

Dies scheint ziemlich einfach zu implementieren zu sein, aber ich frage mich, ob so etwas bereits existiert, weil ich das Rad nicht neu erfinden möchte.

Zusätzliche Gedanken

Ich habe das Gefühl, dass ich hier unter XY-Problemen leide, da rollierende Bereitstellungen und blau/grüne Bereitstellungen als bewährte Methode angesehen werden. Es erscheint seltsam, dass ich keine Lösung finden kann, um Datenbankaktualisierungen weniger schmerzhaft zu machen. Wenn Sie denken, dass ich mich völlig mit dem Falschen befasse, lassen Sie es mich bitte in einem Kommentar wissen! Das Datenbankbeispiel, das ich gegeben habe, ist jedoch nur ein Beispiel, und ich denke, TODO-Kommentare mit Fälligkeitsterminen wären auch in anderen Situationen nützlich. Selbst wenn ich mich dieser speziellen Situation ganz falsch nähere, würde ich gerne auf meine antworten aktuelle Frage auch. Vielen Dank!

EDIT: Ich habe gerade an eine andere Situation gedacht, in der dies hilfreich sein könnte. Wenn Sie Feature Toggles verwenden, um Teile Ihrer App zu aktivieren, wenn sie fertig sind, müssen Sie vorsichtig sein, um sie zu bereinigen, da Sie sonst möglicherweise Toggle Debt erhalten. Kommentare mit Fristen könnten eine gute Möglichkeit sein, sich daran zu erinnern.

51
Joshua Walsh

Diese Frage ist wirklich zwei Fragen in einer.

Todo Kommentare

Von allen Möglichkeiten, Aktionselemente zu verfolgen, ist dies die schlechteste. TODO-Kommentare eignen sich gut für die aktive Arbeit oder als Vorschlag für einen Betreuer: "Hier ist etwas, das möglicherweise in Zukunft verbessert werden könnte." Wenn Sie sich jedoch auf TODO-Kommentare verlassen, um Ihre Arbeit zu erledigen, sind Sie zum Scheitern verurteilt.

Was tun?

TODO-Kommentare sind im Grunde genommen technische Schulden, daher sollten sie wie alle anderen technischen Schulden behandelt werden. Wenn Sie Zeit haben, können Sie sie entweder sofort angehen oder in den Rückstand aufnehmen, damit sie nachverfolgt und priorisiert werden können.

Im Allgemeinen können TODO-Kommentare als Code-Geruch angesehen werden, und dies ist völlig unvoreingenommen und offen für Debatten. Wenn ein TODO-Kommentar es schafft, in die Versionskontrolle eingecheckt zu werden, müssen Sie sich fragen, ob Sie ihn jetzt tatsächlich durchziehen werden. Wenn nicht, ist das in Ordnung. Sei einfach ehrlich zu dir selbst und stelle es in den Rückstand.

Wie Sie diesen Rückstand verwalten, hängt von Geschäftsprozessen, Unternehmenspolitik und möglicherweise einer gewissen persönlichen Autonomie ab. Sie benötigen jedoch noch einen nachverfolgten und priorisierten Rückstand, um sicherzustellen, dass dies geschieht.

Datenbankänderungen

Ja, Datenbankänderungen sind mit einer Richtlinie ohne Ausfallzeiten schwierig. Einige Tricks, um es weniger schmerzhaft zu machen:

Post-Deployment-Prozess

Erstellen Sie einen Post-Deployment-Prozess, der als Teil derselben Version ausgeführt wird. Wie auch immer Sie möchten, dass es funktioniert. Auf dem letzten System, an dem ich gearbeitet habe, habe ich eine 4-Phasen-Bereitstellung entworfen:

  1. preapp-Datenbankskripte
  2. web-Apps
  3. postapp-Datenbank-Skripte
  4. wartungsfenster-Datenbank-Skripte

Die Idee war, dass wir, wo immer möglich, so viele Datenbankänderungen wie möglich in preapp umsetzen würden.

Postapp war für ungewöhnliche Fälle reserviert, in denen inkompatible Schemaänderungen vorgenommen werden mussten. In diesen Fällen würde preapp genug Änderungen vornehmen, um den neuen Anwendungscode kompatibel zu machen (möglicherweise eine temporäre Ansicht für die Kompatibilität erstellen), und postapp würde solche temporären Artefakte bereinigen.

Die Phase des Wartungsfensters war Änderungen vorbehalten, die tatsächlich Ausfallzeiten erforderten oder bei denen sich das Risiko oder die Kosten einer Live-Bereitstellung nicht gelohnt haben. Beispielsweise müssen Skripte, die große Datenmengen ändern, möglicherweise eine gesamte Tabelle sperren.

häufig bereitstellen

Wenn Sie neue Releases häufig genug bereitstellen, können Sie einen Punkt erreichen, an dem eine Änderung in zwei oder drei Releases trivial ist. Lange Release-Zyklen erhöhen die Kosten für Datenbankänderungen.

53
Brandon

Verwenden Sie keine TODOs. Sie haben bereits eine TODO-Liste in Ihrem Projekt. Es heißt Issue Tracker.

Ich denke, das eigentliche Problem liegt in diesem Satz:

wir können ein Ticket in unserem Issue-Management-System erstellen, was zu Unordnung führt und möglicherweise auch vom Management auf einen späteren Sprint oder den Rückstand verschoben wird.

Wenn Ihr Issue-Tracker zu viel Unordnung verursacht, finden Sie Möglichkeiten, dies zu beheben. Möglicherweise ein spezieller Problemtyp/Tag, der weniger Zeremonie beinhaltet. Vielleicht Unterprobleme. Vielleicht insgesamt weniger Zeremonie. Wir können es nicht wirklich sagen. Wenn Ihr Issue-Tracker jedoch so viel Arbeit verursacht, dass die Leute in einem öffentlichen Forum lieber eine ausführliche Frage formulieren, als nur dieses Problem hinzuzufügen, stimmt etwas nicht.

Wenn Ihr Management den letzten Teil einer Aufgabe übermäßig verzögert, haben Sie zwei Möglichkeiten:

  1. sprechen Sie mit Ihrem Management, warum dies eine schlechte Idee ist.

  2. behandle es als eine einzige Aufgabe. Dies könnte die Goldstandardlösung sein. In einer perfekten Welt sollten Sie in der Lage sein, die drei erforderlichen Änderungen in jedem Schritt vorzunehmen. Wenden Sie eine auf den Hauptzweig an, lassen Sie ihn erstellen und bereitstellen. Wenden Sie in der Zwischenzeit die zweite auf den Hauptzweig an, lassen Sie ihn erstellen und bereitstellen usw., damit alles im selben Sprint geschieht, und wenn dies nicht der Fall ist, wird dies nicht getan. Vielleicht macht sogar etwas Automatisches Sinn, wenn Sie logisch eine Bereitstellung durchführen, aber es ist tatsächlich in drei Teile aufgeteilt.

24
Jens Schauder

Was ich suche, ist eine Möglichkeit, wie ein TODO-Kommentar eine Frist haben kann, und unser Continuous Integration-System (derzeit unentschlossen, das wir verwenden werden) würde den Build ablehnen, wenn diese Frist abgelaufen wäre.

Was Sie verlangen, ist machbar, wenn Sie bereit sind, die Arbeit zu erledigen und durchzuhalten.

// TODO von v55: Erstellen Sie eine Migration, um Einschränkungen in eine neue Spalte zu verschieben. Entfernen Sie Verweise auf eine alte Spalte in der App. // TODO von v56: Erstellen Sie eine Migration, um eine alte Spalte zu löschen

grep für //TODO by v55 wenn es Zeit ist, v55 bereitzustellen. Deploy Build führt ein Skript aus, das dies als Integrationstest ausführt.

Sie können 55 in Ihre Versionsverfolgung einbinden oder einfach dazu auffordern.

Es wird interessant, wenn Sie bei 55 nach // TODO von v54 suchen möchten. Suchen Sie stattdessen 55 Mal in der Codebasis nach // TODO von. Filtern Sie dann das Ergebnis nach 1 bis 55. Jetzt löst 56 keinen Fehler aus.

Sie könnten denken "Oh, das werden wir nicht brauchen. Wir werden diese jedes Mal reparieren, solange wir den Scheck haben". Nein, wirst du nicht.

9
candied_orange

Wir hatten ein sehr ähnliches Problem in unserem Team. Um dies zu lösen, haben wir eine statische Analyseprüfung geschrieben, die diese TODOs behandelt, indem das JIRA- oder Git-Problem überprüft wird, auf das sie verweisen. Unser Build schlägt fehl, wenn das angegebene Problem die Spalte "In Entwicklung" überschreitet.

Daher können wir bequem TODOs haben, ohne uns Sorgen machen zu müssen, dass sie vergessen werden.

Ich habe eine Open-Source-Implementierung davon in Java erstellt. Ja, ein Haftungsausschluss ist, dass ich dies geschrieben habe, aber wie gesagt, es ist vollständig Open Source und lizenziert.

Das Tool heißt Westie und ein Beispiel für die Jira-Problemprüfung finden Sie in der README.md. Siehe auch den GitIssueAnalyser.

Senden Sie mir eine Nachricht, um zu verhindern, dass Sie sich selbst fördern, wenn Sie weitere Fragen haben. Wenn Sie sich für die Verwendung entscheiden und Vorschläge haben, werfen Sie bitte Probleme mit github auf.

4
tjheslin1

Nicht zu tun. Mach es jetzt.

TLDR: Schreiben (und testen) Sie Ihre DB-Skripte jetzt und nicht später. Codieren Sie sie einfach, damit ihre Ausführung von der DB-Version abhängt.

Beispiel

Stellen Sie sich zum Beispiel vor, Sie möchten einen Spaltennamen von SSN in TaxID ändern, eine häufige Anforderung, wenn Sie international arbeiten.

Um dies zu erreichen, haben Sie möglicherweise vorübergehend sowohl eine TaxID als auch eine SSN Spalte. Und während Sie beide Versionen unterstützen, haben Sie einen Auslöser, um eine von der anderen zu aktualisieren. Sie möchten diesen Trigger jedoch nicht unbegrenzt beibehalten. Wenn später keine Abwärtskompatibilität mehr erforderlich ist, möchten Sie diesen Trigger entfernen (und die Spalte SSN wird gelöscht). Wir werden das alles im Voraus codieren, ohne dass ToDo-Elemente erforderlich sind.

In unserem Beispiel werden wir Build 102 (mit der neuen Spalte) bereitstellen und gleichzeitig die Kompatibilität mit Build 101 beibehalten (was nicht der Fall ist).

Hier sind die Schritte.

1. Richten Sie eine Versionierungstabelle ein

  1. Fügen Sie eine einzelne Tabelle mit dem Namen Configuration mit zwei Spalten hinzu: Name und Value.

  2. Fügen Sie eine Zeile mit einem Name von "TargetVersion" hinzu und setzen Sie Value auf die Version des neuen Builds, der bereitgestellt werden soll.

  3. Fügen Sie eine Zeile mit einem Name von "CompatibleWith" hinzu und setzen Sie Value auf die Mindestversionsnummer, mit der die Bereitstellung kompatibel sein muss.

Überprüfen und aktualisieren Sie diese Zeilen vor jeder Bereitstellung.

2. Bereitstellungsskripte ändern

  1. Fügen Sie ein Skript hinzu, das eine neue Spalte von TaxID neben SSN erstellt und aus der Spalte SSN auffüllt. Fügen Sie diesen Code in eine If - Anweisung ein, die TargetVersion überprüft. Wenn die Zielversion zu niedrig ist (d. h. TaxID wird noch nicht benötigt), überspringen Sie.

    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. Fügen Sie ein Skript hinzu, das einen Trigger erstellt, der TaxID beim Einfügen oder Aktualisieren von SSN auffüllt und umgekehrt. Fügen Sie diesen Code in eine If - Anweisung ein, die die Zielversion und die kompatible Version überprüft. Überspringen, wenn TargetVersion zu niedrig ist (TaxID wird nicht benötigt) oder wenn die CompatibleWith-Version zu hoch ist (das Feld SSN wird nicht benötigt).

    SELECT @TargetVersion  = TargetVersion,
           @CompatibleWith = CompatibleWith 
    FROM Configuration
    IF @TargetVersion  < '102' THEN RETURN
    IF @CompatibleWith > '101' THEN RETURN
    CREATE TRIGGER SSNAndTaxIDTrigger ON Customer etc.
    
  3. Fügen Sie ein Skript hinzu, um die Spalte SSN zu entfernen. Fügen Sie eine If - Anweisung ein, die die Spalte nur entfernt, wenn die CompatibleWith-Version hoch genug ist (SSN wird nicht mehr benötigt).

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

Testen Sie Ihre Bereitstellung unbedingt mit einer beliebigen Kombination von blau/grünen Versionsnummern, die Sie in der Produktion unterstützen möchten. Sie können testen, sobald der Code fertig ist, indem Sie die Tabelle Configuration in Ihrer QS-Umgebung bearbeiten.

4. In Ihrem Bereitstellungs-Playbook

Fügen Sie einen Schritt hinzu, damit ein Techniker die Zeilen CompatibleWith-Version und TargetVersion aktualisiert. Wenn Sie für Blue bereitstellen, setzen Sie TargetVersion auf die Versionsnummer von Blue und die CompatibleWith-Version auf die Versionsnummer von Green. Kehren Sie sie um, wenn Sie Green bereitstellen.

Fallstricke

Es ist in Ordnung, wenn Ihre Bereitstellungsskripte auf die in dieser DB-Tabelle enthaltenen Versionsnummern verweisen und sich darauf verlassen. NICHT Laufzeitcode.

Wenn Sie anfangen, Ihren Laufzeitcode zu schreiben, um Versionsnummern zu überprüfen, führen Sie eine neue Komplexität in Ihre Anwendung ein, die möglicherweise zu einem großen Problem der Wartbarkeit werden kann. Jeder Laufzeitausführungspfad muss getestet werden. Wenn Sie diese Bedingungen in Zukunft mit sich herumtragen, muss die Qualitätssicherung eine Schmerzmatrix zusammenstellen, um sie bei jeder Veröffentlichung zu validieren. Mein Rat ist, solche Bedingungen nur in Bereitstellungsskripten beizubehalten.

Das Ergebnis all dessen

Am Ende sollten Sie in der Lage sein, den gesamten Code im Voraus zu schreiben (und ihn auch zu testen), ohne befürchten zu müssen, dass er zu früh ausgeführt wird. Außerdem bereinigt der Code den Abwärtskompatibilitätsauslöser, wenn die Zeit gekommen ist, ohne dass Sie sich weiter darum kümmern müssen.

Auf diese Weise können Sie den gesamten Code im Voraus schreiben und testen, wenn Sie darüber nachdenken, und Sie müssen sich nicht mit diesen unordentlichen ToDo-Kommentaren befassen.

4
John Wu

Sie bekommen eine Menge Rückschläge auf Ihre TODO-Idee, aber ich persönlich sehe kein Problem damit. Der beste (und einfachste) Weg, um sicherzustellen, dass die Migration in die Produktion geht, besteht darin, einen Komponententest nicht zu bestehen, wenn dies nicht der Fall ist. Es dauert buchstäblich weniger als eine Minute, um eine leere Migrationsfunktion zu löschen, die eine Ausnahme auslöst, wenn die Version 55 oder mehr ist (oder welche Anforderungen auch immer).

Wenn Sie dann versuchen, es freizugeben, wird der Test fehlgeschlagen, und jemand muss diese Ausnahme in einen tatsächlichen Migrationscode umwandeln.

1
Eternal21