私の会社では、開発(バグ修正と新機能)はすべて別々のブランチで行われています。完了したら、それをそのブランチでテストするQAに送信します。QAが青信号を出したら、それをメインブランチにマージします。これには1日から1年かかります。
ブランチでリファクタリングを絞り込もうとした場合、それが「アウト」される期間がわからないため、マージされたときに多くの競合が発生する可能性があります。
たとえば、私が取り組んでいる機能がこの関数を多用しているために、関数の名前を変更したいとします。その名前は目的に実際には適合していないことがわかりました(これも単なる例です)。そこで、この関数のすべての使用法を調べて、名前をすべて新しい名前に変更すると、すべてが完全に機能するので、QAに送信します。
その間、新しい開発が行われていて、名前を変更した関数は、メインから分岐しているどのブランチにも存在しません。私の問題がマージされると、それらはすべて壊れるでしょう。
これに対処する方法はありますか?
経営陣がリファクタリングのみの問題を承認することはないので、他の作業をしなければなりません。メインで直接開発することはできません。すべての変更はQAを通過する必要があり、メインを壊して不要なリファクタリングを少しでもできるように、誰もジャークになりたくないからです。
この環境では、リファクタリングを困難にするために混合しているいくつかの問題があります。これにはいくつかの非技術的な問題が混じっています(しかし、それは管理上の問題であり、私がまだ勝てない戦いです)。
最初に確認する問題は、実行時間の長いブランチです。これらのブランチは、開発者の視野の外で変更を追跡することが困難です。これに対処するには:
これに混ざっているもう1つの問題は、上記のポイントで触れたように、時間の経過とともにブランチの役割が変化することです。これは、開発者がコミットする開発ブランチとして始まり、次にテスト領域になります(アプリケーション全体で意味のあるテストはここで行われます)。その後、安定版にマージされます(そしておそらくリリースされます-です)もう一度テストされましたか?).
機能の開始から終了までの時間が短いと、リファクタリングを他のブランチで取得しやすくなります。
開発者に環境全体を入手するように勧めます。チェリーを選ぶだけの変更は、...につながる可能性があります。興味深い開発者環境について考えてみましょう。チェリーピッキングには用途がありますが、それを変更をブランチにプルするデフォルトのモードにするのは気になる可能性があります。
リファクタリングは、理想的には絶えず実行される、またはダウンタイムがわずかでもある場合は常に実行されないものです。ブランチし、単純なリファクタリングを行い、ユニットテストを実行してすべてがまだ機能していることを確認します(そのユニットテストは正しいですかright?)。安定した。他の開発者がリファクタリングした変更を独自のブランチにプルするための情報を渡します。
開発者がコードの品質を所有することは重要です。機能の方向性は外部からのものであり、時間の割り当ては私たち自身のものではないことがよくありますが、コードの品質は、誇りを持って時間をかける必要があるものです。
次の質問は、技術的負債を処理するための時間を割り当てるための探求で役立ちます。
また、リファクタリングに最も作業が必要なコードの領域を特定するのに役立つ sonar などのツールを確認することもできます。 テクニカルデットプラグイン は、コードベースの長期にわたるデットの蓄積を指摘するのに役立つものです。
多くの場合、技術的負債に対処するための [〜#〜] roi [〜#〜] は、開発チームからの機能とバグ修正のターンアラウンドタイムが速いことを指摘する必要があります。
通常、リファクタリングされたバージョンを現在と並行して、つまり同じコードベースで開発していますが、コアアプリケーションからは参照していません。そして、新しいソリューションが完成してテストされると、私は実際のリファクタリングを始めています。
例1。私はモノを持っていると仮定し、それを関数、インターフェース、モジュール、またはその他のものとします。そして、それをリファクタリングしたいと思います。同じコードベースでThing2を作成していますが、これはThingのリファクタリングバージョンです。完了してテストされると、Thingを参照するすべてのものをリファクタリングして、Thing2に置き換えます。通常、このステップには比較的短い時間がかかります。
実際のリファクタリングがチームを台無しにせずに同期を維持するのに時間がかかりすぎる場合、私はすべての関連機能を使用し、それらも並行してリファクタリングしています。
例2。新しいレンダリングバックエンドがあります。これは古いもののリファクタリングバージョンです。ただし、古いレンダリングフロントエンドとは互換性がありません。したがって、私はフロントエンドをリファクタリングする必要があります。そして再び:同じコードベースで。すべてが完了したら、フロントエンドインスタンスのクラスを変更するだけです。理想的には、1つの短いコミットが必要です。
はい、再帰的にeverythingは並行して実行する必要があるという結論に達するかもしれません。ただし、これは通常、コードベースの結合が多すぎるか、変化が速すぎる場合に発生します。
最後に、新しいコードが統合されて正常に機能すると、古い機能がコードベースから削除され、新しい機能の名前が変更されて古い名前が取得される場合があります。
一般的には、新しい機能を並行して準備し、1つの小さなステップでそれらを使用するように切り替えるというアイデアです。
John Carmackは、この(または少なくとも同様の)アプローチを使用しています。おそらく彼のブログ投稿がそれをよりよく説明しています: (link)
問題はあなたが枝で過度に長く働いているように私に思われます。競合のコストは、誰もがブランチにとどまっている長さとともに指数関数的に増加します。そのため、非常に長い競合では、リファクタリングを実行する機会はほとんどありません。
実際には要件側にあるのに、技術側では難しそうに見えるかもしれません。
開発がさまざまなブランチのさまざまな要件に向けられている場合、本当の困難です。チームのマネージャーとアーキテクトは、さまざまなビジネスニーズの共存を可能にする可能性のある決定を行う必要があります。
ZBBプロセスとCo-Devは、すべての開発者からの関連する入力を使用して適切な決定を行った後、「妥協」する必要があります。
ZBBは ゼロベースの予算編成 の略です。 Co-Devと言って、私は並列プログラミングで働いている少数の人々を意味しました。
あなたの問題はあなたが使っているブランチモデルです。ブランチで開発することもできます。完成してQAの準備ができると、ブランチは「中間トランク」に統合され、「インテグレーション」または「テスト」と呼ばれることもあります。次の機能を開発するときは、代わりにこの中間トランクから分岐できます。
このモデルでは、さまざまなブランチで複数の機能を並行して開発し、それらをすべてIntegrationブランチにマージしてQAに送信し、リリースの単一のトランクを維持することもできます(認定時に、受信したコードベースQAをメイントランクにマージします) )
QAに配信された変更は大きな変更なしに渡されると想定していますが、QAコードに変更の半分を削除する指示が表示された場合、元に戻す必要がありますが、それが行われない場合は、変更が行われます。開発がはるかにスムーズになります。つまり、現在の機能(現在のトランク)ではなく、メインラインコード(つまり、QAに渡されたコードをマージした後のトランク)から新しい機能の分岐を作成しているため、以前のリリースのコードベースでは開発されていません。 。