期限付きのTODOコメント?


51

バックグラウンド

私は、ゼロダウンタイム展開の実装を検討しているチームで働いています。これを実現するために、ブルー/グリーン展開戦略の使用を計画しています。研究を行う上で私が理解していることの1つは、データベースの変更を行うことがどれほど複雑になるかです。カラムの名前を変更するなどの簡単な操作は、完了するまで3回の完全なリリースサイクルを必要とします。

変更の完全なロールアウトに複数のリリースサイクルがかかると、ヒューマンエラーが発生する可能性が大きくなるように思えます。リンクされた記事では、2つのリリースにはコードの変更が必要であり、3つのリリースにはデータベースの移行が必要であることを示しています。

私が探しているもの

現在、何かを行うことを覚えている場合は、問題管理システムでチケットを作成できます。または、TODOコメントを作成することもできますが、おそらく完全に忘れられます。

私が探しているのは、TODOコメントに期限があり、この期限が切れた場合、継続的インテグレーションシステム(現在使用する未定)がビルドを拒否する方法です。

たとえば、列の名前を変更する場合、最初の移行を作成し、次に2つのTODOコメントを作成して、残りの2つの移行が作成されるようにします。

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

これは実装するのはかなり簡単に思えますが、車輪の再発明をしたくないので、このようなものがすでに存在するかどうか疑問に思っています。

追加の考え

ローリングデプロイメントとブルー/グリーンデプロイメントがベストプラクティスであると考えられるため、ここでXYの問題に苦しんでいるように感じます。データベースの更新の痛みを軽減するソリューションを見つけることができないのは奇妙に思えます。私が間違っていることを完全に調査していると思われる場合は、コメントでお知らせください!とはいえ、私が挙げたデータベースの例はほんの一例に過ぎず、期日付きのTODOコメントは他の状況でも役立つと思うので、この特定の状況に近づいていたとしても、私は本当に自分の答えにしたい実際の質問も。ありがとう!

編集:これが役立つ別の状況を考えました。機能のトグルを使用して、準備ができたときにアプリの一部を有効にする場合、それらをクリーンアップするように注意する必要があります。そうしないと、Toggle Debtになる可能性があります。期限付きのコメントは、これを思い出す良い方法です。


19
TODOの問題は、ツールよりも規律の問題です。
ブランドン

16
人間はすべて間違いを犯すと思いますが、ツールはこれを軽減する良い方法です。
ジョシュアウォルシュ


3
プログラムでこれを行うのはどうですか。クラスのメンバーにあなたのバージョンを書いてください。バージョンが== 56でメッセージが「クラスy」の場合、アプリの起動に失敗します。この機能が必要な場合、そのようなメッセージのリストを作成できます。どう思いますか?
ベンデイビッドトーマー

6
反対意見に向けて、私は同意しません。私たちのコードベースは、私たちが取り組んでいない他の多くのコンポーネントに依存しているためTODO <Bug#>:、他のコンポーネントの問題の回避策を追跡するために使用します。これらのコンポーネントの1つでバグが解消されると、関連する回避策を簡単に見つけて対処できます。課題トラッカーに置き換わるものではなく、メンテナンスが容易になります。
TemporalWolf

回答:


53

この質問は、実際には2つの質問です。

Todoコメント

アクション項目を追跡するすべての方法の中で、これは最悪です。TODOコメントは、アクティブな作業中、またはメンテナーへの提案の方法として、「これは将来改善される可能性があるものです」といいです。しかし、作業を完了するためにTODOコメントに依存している場合、失敗する運命にあります。

それについてどうするか

TODOコメントは基本的に技術的な負債であるため、他の技術的な負債と同様に処理する必要があります。時間があれば、すぐにそれらに取り組むか、追跡して優先順位付けできるようにバックログに入れてください。

一般的に言えば、これは完全に意見が分かれており、議論の余地がありますが、TODOコメントはコードのにおいと見なすことができます。TODOコメントがバージョン管理にチェックインされている限り、自問する必要があります。実際にそれをフォローしますか?そうでない場合、それは大丈夫です。自分に正直になって、バックログに入れてください。

このバックログをどのように管理するかは、ビジネスプロセス、会社の政治、そしておそらく個人の自律性にかかっています。ただし、それを確実に行うには、追跡され、優先順位付けされたバックログが必要です。

データベースの変更

はい、ゼロダウンタイムポリシーでは、データベースの変更には注意が必要です。痛みを軽減するためのコツ:

展開後のプロセス

同じリリースの一部として実行される展開後プロセスを作成します。しかし、あなたはそれが機能することを望みます。最後に取り組んだシステムで、4フェーズの展開を設計しました。

  1. プリアプリデータベーススクリプト
  2. ウェブアプリ
  3. postappデータベーススクリプト
  4. メンテナンスウィンドウデータベーススクリプト

アイデアは、可能な限り、可能な限り多くのデータベースの変更をプリアプリに入れるというものでした。

Postappは、互換性のないスキーマの変更を行う必要がある異常なケースのために予約されていました。そのような場合、preappは新しいアプリケーションコードの互換性を確保するために十分な変更を行い(互換性のために一時ビューを作成する場合があります)、postappはそのような一時アーティファクトをクリーンアップします。

メンテナンスウィンドウフェーズは、ダウンタイムを本当に必要とする変更、またはライブ展開のリスクやコストに見合わない変更のために予約されていました。たとえば、大量のデータを変更するスクリプトでは、テーブル全体をロックする必要がある場合があります。

頻繁に展開する

新しいリリースを十分に頻繁に展開する場合、2つまたは3つのリリースに変更を加えるのが簡単になるポイントに到達できます。長いリリースサイクルは、データベース変更のコストを増幅します。


18
Todoコメントは、作業を追跡して優先順位を付けるためのひどい方法です。これらは、半分のコードが風になびいている理由を説明する有効な方法です。完璧な世界では、これを行うコードはありません。一方、これでは
...-candied_orange

6
...技術的な負債を追跡する方法があると便利な場合があります。これは、上司からの優先順位を下げることはできません。修正しても信用は得られません。とにかくそれを修正することがあります。
candied_orange

3
それでは、ポストアプリの戦略は、アプリの展開がすべて正常に完了した後にそれらの移行を実行するということですか?コードはどうですか?列の名前をlast_nameからsurnameに変更するとします。古いコードはlast_nameを使用します。DBを移行して姓を追加し、使用可能な場合は姓を使用するようにコードを変更し、そうでない場合はlast_nameを使用します。展開が完全に展開されたら、次の移行を実行して、古いlast_name列を削除します。ただし、コードにはlast_nameのコードがまだ含まれており、現在は未使用であるため技術的な負債があります。これをどのようにクリーンアップしますか?
ジョシュアウォルシュ

3
コメントでアクションアイテムを管理するのは本当にひどい方法ですが、トラッキングシステムでコメントを使用して問題を自動的に作成することは、現在何かをコーディングしている途中でハードスイッチングをしたくないため、これを忘れないための優れたツールです問題追跡システムのコンテキスト。
PlasmaHH

6
私見この答えはポイントがありません。OPは、重要なクリーンアップが忘れられたときにCIが「問題管理システム」を乱雑にすることなくチームに通知するソリューションを求めました(TODOコメントは単なる例であり、これには理想的なソリューションではないかもしれません)。OPは、これを使用したくない理由をいくつか示しました。それにもかかわらず、この回答は、OPの場合は彼の「問題管理システム」以外のバックログに完全に依存することを示唆しています。だから私見この答えは質問の核心を無視し、解決策を提示しません。
Doc Brown

24

TODOを使用しないでください。プロジェクトにはすでにTODOリストがあります。課題追跡と呼ばれます。

私は本当の問題はこの文にあると思う:

問題管理システムでチケットを作成できます。これにより、混乱が生じ、管理者によって後のスプリントまたはバックログに移動される可能性があります。

問題追跡ツールが混乱を招く場合は、それを修正する方法を見つけてください。たぶん、より少ないセレモニーを伴う特別な問題タイプ/タグ。副次的な問題かもしれません。たぶん、より少ない式典。本当にわかりません。ただし、問題追跡ツールが非常に多くの作業を作成する場合、人々はその問題を追加するだけでなく、公開フォーラムで詳細な質問を作成するので、何かがひどく間違っています。

管理者がタスクの最後の部分を過度に遅延させる場合、2つのオプションがあります。

  1. これが悪い考えである理由をあなたの経営者に話してください。

  2. 単一のタスクとして処理します。これがゴールドスタンダードソリューションかもしれません。完全な世界では、各ステップで必要な3つの変更を行うことができるはずです。1つをmasterブランチに適用し、ビルドしてデプロイします。それまでの間、2番目をmasterブランチに適用し、すべてを同じスプリントで実行し、そうでない場合は実行しないように、ビルドとデプロイなどを行います。論理的に1つの展開を行う場合は、自動化されたものも理にかなっているかもしれませんが、実際には3つに分割されています。


良いアドバイスです。この目的のために問題管理システムを機能させる方法について考えます。また、「論理的に1つの展開を行う場合、自動であっても理にかなっているかもしれない」というアイデアが本当に好きです。それを実現する方法を考えています。しかし、現実的に可能かどうかはわかりません。
ジョシュアウォルシュ

11
// TODO(#12345): Frobnicate the sprocket before passing it alongバグ#12345が「実際の」問題番号であり、問​​題が誰かに割り当てられている場合、フォームのコメントを付けることは完全に合理的です。これにより、ソースを読みやすくなります。「いいえ、フロブニケートステップはヘルパーメソッドの1つに隠れていません。実装されていないため、フラットです。詳細については、バグ#12345をご覧ください。」もちろん、クローズドまたは無効な問題番号を探すために、コードベース上で毎日リンターを実行するのが理想です。
ケビン

9

私が探しているのは、TODOコメントに期限があり、この期限が切れた場合、継続的インテグレーションシステム(現在使用する未定)がビルドを拒否する方法です。

あなたが仕事をして、フォロースルーをする気があるなら、あなたの求めていることは実行可能です。

// v55によるTODO:制約を新しい列に移動する移行を作成し、アプリの古い列への参照を削除します// v56によるTODO:古い列を削除する移行を作成します

//TODO by v55v55をデプロイするときのgrep 。ビルドをデプロイすると、統合テストとしてそれを行うスクリプトが実行されます。

55をバージョントラッキングに結び付けるか、単にそれを促すことができます。

55を実行するときにv54で// TODOをチェックする場合は興味深いものになります。代わりに// TODO byを検索するだけでコードベースを55回検索します。次に、その結​​果を1〜55でフィルターします。56は失敗をトリガーしません。

「ああ、それは必要ないでしょう。チェックがある限り、これらを毎回修正します」と思うかもしれません。いいえ、違います。


4
その場合、ここでは推奨事項を実行しません。
candied_orange

3
提供できるこの種の一般的な名前はあるが、推奨事項に関する行をリンクしているページを読んだ場合、これを指すようになります:softwareengineering.meta.stackexchange.com/a/6487/131624
candied_orange

6
明確にするために、質問全体ではなく、私が反対しているのはあなたのコメントです。
candied_orange

2
@YM_Industries SEサイトは自己完結型であることが多く、推奨事項は基本的に外部サイトへのリンクを含む簡単な回答です。または、リンクの代わりにGoogleに招待してください。それらは期限が切れて死んでしまうかもしれません。したがって、推奨事項に関する質問はトピックから外れていますが、誰かがツールを回答または簡単なコメントの補足として言及したい場合、彼はそれを行うことができます。
ウォルフラット

2
「既存のソリューションが存在する場合、私は思っていた」 -で、私たちの上に尋ねてみてくださいsoftwarerecs.stackexchange.com
Mawg

4

チームでも同様の問題がありました。これを解決するために、参照するJIRAの問題またはGitの問題をチェックすることにより、これらのTODOを処理する静的分析チェックを作成しました。指定した問題が「開発中」列を通過すると、ビルドは失敗します。

したがって、忘れられることを心配することなく、TODOを快適に使用できます。

Javaでこれのオープンソース実装を作成しました。はい、免責事項はこれを書いたということですが、私が言ったように、それは完全にオープンソースであり、ライセンスされています。

このツールはWestieと呼ばれ、Jiraの問題チェッカーの例はREADME.mdにあります。GitIssueAnalyserも参照してください。

さらに質問がある場合に自己宣伝を防ぐには、メッセージを送ってください。あなたがそれを使用することに決め、何か提案がある場合は、githubで問題を提起してください。


1
カッコいい!私たちもJIRAを使用しています。これの使用を検討するかもしれません。問題管理システムに混乱が生じるという私の懸念を実際に解決することはできませんが、少なくとも、それらが忘れられないことは保証されます。
ジョシュアウォルシュ

@YM_Industriesうれしいです。私はどんな貢献も受け入れるか、提起された問題に取り組みたいです。
tjheslin1

4

やることはありません。今やれ。

TLDR:後でではなく、今すぐDBスクリプトを記述(およびテスト)してください。DBバージョンに依存して実行されるようにコーディングするだけです。

例として、国際化する際の一般的な要件である列名をからSSNに変更したいとしますTaxID

これを実現するために、一時的に列TaxIDSSN列の両方を使用することになるでしょう。また、両方のバージョンをサポートしている間、一方を他方から更新するトリガーがあります。ただし、そのトリガーを無期限に保持したくないので、後で、下位互換性が不要になったら、そのトリガーを削除する(およびSSN列を削除する)必要があります。ToDoアイテムを必要とせずに、これらすべてを事前にコーディングします。

この例では、ビルド102(新しい列があります)をデプロイし、ビルド101(そうではない)との互換性を維持します。

手順は次のとおりです。

1.バージョン管理テーブルを設定する

  1. 呼ばれる単一のテーブルの追加Configuration2つのカラムを持つが、NameValue

  2. Name「TargetVersion」の行を追加し、Value展開する新しいビルドのバージョンに設定します。

  3. Name「CompatibleWith」の行を追加しValue、展開に互換性が必要な最小バージョン番号を設定します。

すべての展開の前に、これらの行を調べて更新します。

2.展開スクリプトを変更する

  1. の新しい列を作成するスクリプトを追加します。これは、とTaxID並べてSSNSSN列からデータを入力します。このコードをIfTargetVersionをチェックするステートメントで囲みます。ターゲットバージョンが低すぎる(つまり、TaxIDまだ必要ない)場合は、スキップします。

    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. TaxID挿入または更新時に挿入するトリガーを作成するスクリプトを追加しますSSN。逆も同様です。このコードをIf、ターゲットバージョンと互換バージョンをチェックするステートメントで囲みます。TargetVersionが低すぎる(TaxID必要ない)場合、またはCompatibleWithバージョンが高すぎる(SSNフィールドが不要な)場合はスキップします。

    SELECT @TargetVersion  = TargetVersion,
           @CompatibleWith = CompatibleWith 
    FROM Configuration
    IF @TargetVersion  < '102' THEN RETURN
    IF @CompatibleWith > '101' THEN RETURN
    CREATE TRIGGER SSNAndTaxIDTrigger ON Customer etc.
    
  3. SSN列を削除するスクリプトを追加します。IfCompatibleWithバージョンが十分に高い(SSN不要になった)場合にのみ列を削除するステートメントで囲みます。

    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.テスト

運用環境でサポートできるようにしたいBlue / Greenバージョン番号の任意の組み合わせで展開をテストしてください。ConfigurationQA環境でテーブルを操作することにより、コードの準備ができ次第テストできます。

4.展開プレイブック

エンジニアがCompatibleWithバージョンおよびTargetVersion行を更新するためのステップを追加します。Blueにデプロイする場合、TargetVersionをBlueのバージョン番号に設定し、CompatibleWithバージョンをGreenのバージョン番号に設定します。グリーンを展開している場合は、それらを逆にします。

落とし穴

展開スクリプトは、そのDBテーブルに保持されているバージョン番号を参照し、それに依存しても構いません。ランタイムコードではありません。

バージョン番号を調べるためにランタイムコードの記述を開始すると、アプリケーションに新しいレベルの複雑さが導入され、潜在的に大きな保守性の問題になりかねません。各ランタイム実行パスをテストする必要があります。今後これらの条件を持ち歩く場合、QAはリリースのたびにそれらを検証するために苦痛のマトリックスをまとめる必要があります。私のアドバイスは、このような条件を展開スクリプトのみに保持することです。

このすべての結果

最終的に、早すぎる実行を恐れることなく、すべてのコードを事前に記述(およびテスト)できるはずです。また、コードは、それを心配する必要なしに時間が来たときに後方互換性トリガーをクリーンアップします。

この方法では、考えているときにすべてのコードを事前に記述してテストでき、面倒なToDoコメントに対処する必要はありません。


私はこのアプローチが本当に好きです。ToDoコメントよりもエレガントです。私はこの質問をした直後にそれを考え、これをどのように実装するのが最善かを尋ねる別の投稿をすることを考えていましたが、最初に自分の研究を行うと考えました。私たちにとっての秘isは、データベースの移行にPhinxを使用していることであり、実際にはこれをサポートしていません。時間ができたら、この種のワークフローをサポートするために拡張する方法を探します。このアプローチでは、後方互換性コードをアプリ層から確実に削除する方法の問題は解決しませんが、DBの問題には適しています。
ジョシュアウォルシュ

1

あなたはあなたのTODOのアイデアに対して多くの反論を受けていますが、私は個人的にはそれについて何の問題も見ていません。最終的に、移行が実稼働に入ることを確認する最良の(そして最も簡単な)方法は、そうでない場合は単体テストに失敗することです。文字通り、バージョンが55以上(または要件が何であれ)である場合に例外をスローする空の移行関数をスタブするのに1分もかかりません。

その後、リリースしようとすると、テストに失敗し、誰かがその例外を実際の移行コードに変換する必要があります。


1
うん、理想的には、期限切れのTODOを失敗したテストとして扱うことを望んでいました。TODOに対するプッシュバックの量は少し驚いていますが、それらは問題管理システムの代替ではないことを知っていますが、TDD / BDDの普及を考えると、コードで要件を定義し、強制的にコードを使用することには実際の問題がないことは明らかです機能の完成。
ジョシュアウォルシュ

-2

データベースの変更にリリースサイクルがかかりすぎる可能性があるという不満の根源に焦点を当てている人はいないようです。彼は青/緑の展開スケジュールを続けたいと思っており、ソリューションはすでにそこにあるはずですが、私が何かを逃さない限り、彼の説明は両方のシステムで共有されるデータベースが1つしかないことを示しているようです。その場合、真のブルー/グリーンシステムではありません。データベースはテントの長い柱であるように見えるため、オフラインシステムにデータベースの変更を実装するのにどれだけの時間やリリースサイクルがかかっても、完了するまでは稼働しません。完全にテスト済み。中間オフラインシステムスクリプトでは、オフラインデータベースを毎日完全に更新できます。


1
ブルー/グリーン展開でデータベースを複製すると、多くの頭痛の種になります。prod envが青と緑の間にある場合(たとえば、それぞれに50%の負荷が分散されている場合)、スキーマが異なっていても、レプリケーションコードで両方のデータベースの同期を維持する必要があります。私が行った研究から、現実世界のほとんどの人は、青と緑のスタックの間に共有DBインスタンスを持っているようです。データベースの移行がかなり速い限り、これは大きな問題ではないと思います。ブルー/グリーンスタックは本質的に、少なくともロードバランサー/リバースプロキシでいくつかのリソースを共有する必要があります。
ジョシュアウォルシュ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.