変更依頼が柔軟なソフトウェアの統合とリリースモデルをどのように提供するか

この記事では、変更依頼の方法について説明し、より柔軟なソフトウェア統合とリリースモデルをユーザーに提供する方法について説明しています。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/change-request-a-more-flexible-software-integration-and-release-model_594858)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

執筆者：アリババR&D有効性部シニアプロダクトエキスパート、東越（愛称：He Chu）氏

今日の典型的なソフトウェア統合・リリースモデルは、GitHub の Pull Request や GitLab の MergeRequest のようなメソッドを使って機能ブランチを管理することです。機能ブランチへの変更がコードレビューによって正しく適切であることが証明されると、それらは統合ブランチにマージされます。次に、コードの変更はリリースされるまで、統合ブランチ上で実行される継続的なデリバリーパイプラインに含まれます。

研究開発コラボレーションツールのAone（公称：Yunxiao）もこのモデルをサポートしていますが、アリババのほとんどの研究者や開発者はこのモデルを選択していません。その代わりに、リリース前の機能ブランチを管理するために、Change Requestと呼ばれるオブジェクトを使用しています。

一見すると、変更リクエストはPullやMergeRequestと非常に似ているように見えるかもしれません。しかし、概念的には大きく異なります。

この記事では、これらの方法の類似点と違いを説明し、なぜユーザーが変更リクエストを好むのかを説明します。また、変更リクエストのリスクとデメリットについてもこの記事で紹介しています。この記事があなたの参考になれば幸いです。

#類似点
変更リクエストとPull/MergeRequestの類似点は、主にフィーチャーブランチ自体の品質とプロセス管理にあります。

- Pull/MergeRequestと同様に、変更リクエストは一般的にフィーチャーブランチに対応しています。
- Pull/MergeRequestを使用すると、対応する機能ブランチへのコード変更がコードレビューのために可視化されます。同様に、粒度を変更することでコードレビューを行うこともできます。
- フィーチャーブランチへのコード提出は、継続的インテグレーションツールを自動的にトリガーして作成作業を行い、様々な自動検出を実装することができます。その結果をPull/Merge Requestで表示することができます。同様に、結果は変更リクエストで表示することもできます。
- Pull/MergeRequestで最新のコードをその専用のテスト環境にデプロイし、そのコードを実行してテストやデバッグを行うことができます。これは変更リクエストでも実行できます。
- Pull/MergeRequestでは、承認の条件を設定することができます。例えば、少なくとも2人のレビュアーが変更を承認する、コードレビューで見つかった問題がすべて修正または明確化されている、機能ブランチ上の継続的インテグレーションパイプラインが正常に実行されている、などです。同様の設定は、変更要求でもサポートされています。

#違いと主なメリット
変更リクエストとPull/MergeRequestの主な違いは、対応する機能ブランチがどのように統合され、他の機能ブランチと一緒に配信されるかです。

Pull/MergeRequestに対応する機能ブランチは、統合ブランチに組み込まれます。その後、コードの変更はフィーチャーブランチの粒度では管理されません。そのフィーチャーブランチは統合ブランチに組み込まれ、そのフィーチャーブランチ上のコード変更は、他のフィーチャーブランチ上のコード変更と一緒に統合・リリース手順にマージされ、各統合・リリース段階を通過しています。

しかし、変更依頼は異なります。変更依頼が他の変更依頼と統合されていたとしても、それは一定レベルの独立性と柔軟性を特徴としています。必要に応じて、その変更依頼に対して個別に操作を行うことができます。次に、2つの例を用いて、より詳細な説明をします。


 ###例1
簡単にするために、統合と配信が 3 つのフェーズで実施されていると仮定します: 日常的な統合テスト、リリース前の環境テスト、一般的な可用性のリリース。アプリケーションには 5 つの変更があります: 変更 A から E です。

毎日の統合テストを経て、アプリケーションの変更は、現在、リリース前の環境テストのフェーズにあります。このテストフェーズでは、変更 C に 1 つの障害があることが判明しました。この障害は、日々の統合テスト環境の限界のため、日々の統合テストフェーズでは公開されません。

適切な分析が行われた後、変更 C は他の 4 つの変更とは独立していることがわかります。他の 4 つの変更のリリースへの影響を最小化するために、リリース前の環境テストから変更 C を削除することにしました。そうすれば、他の4つの変更のテストと検証の間、この不具合は発生しません。これら4つの変更はリリース前の環境テストに合格し、一般的な可用性のリリースフェーズに進みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/c1d9f094-47ae-0e1a-b4f0-d2023e77e367.png)

この例では、変更 C が削除された後、他の 4 つの変更は 2 つの理由で再び日常的な統合テストを受けません。1つは、日々の統合テスト環境が新しい変更によって使用されてしまったことにあります。これらの新しい変更をテストするには時間がかかり、繰り返しの調整が必要になる場合があります。日々の統合テスト環境から新しい変更を追放したり、既存の4つの変更に新しい変更を混ぜたり、4つの変更を待機リストに入れたりすることは、明らかに不適切であり、不利益であるからです。

もう一つの理由は、変更A、B、D、Eを変更Cと一緒にしたことで、すでに日常の統合テストが完了しているからです。さらに、変更Cは他の4つの変更とは関係ありません。これら4つの変更点について、日常的な統合テストを再度実施した場合、新たな問題が見つかる可能性は非常に低いと考えられます。また、テストは、ゼロフォールトだけを確実にするのではなく、費用対効果の高いものである必要があります。これらの理由から、開発チームは実際の状況を評価して、これらの4つの変更を日常の統合テストフェーズに再び入れるのではなく、変更Cが削除された後のリリース前の環境テストで他の4つの変更をテストすることを決定することがあります。



###例2
日々の統合テスト、リリース前の環境テスト、一般的な可用性のリリースの3つのフェーズで統合と配信が実施されていると仮定してみましょう。日々の統合テストを経て、アプリケーションの変更はリリース前の環境テストのフェーズに入っています。

この時点で、市場の状況の変化に基づいて、例えば、ページの説明文をいくつか変更するなど、変更 C で表される新機能に対して、いくつかの調整を行う必要があります。新しい変更と変更Cの両方をリリースする必要があるか、どちらもリリースしない必要があるので、管理を容易にするために、新しい変更を変更Cに対応する機能ブランチにすることにします。そして、変更Cと他の4つの変更の更新内容をプレリリース環境でテストし、すべての変更がプレリリーステストに合格したら、それらを一般に利用できるようにします。


前述の 2 つの例では、従来の統合とリリースのモデルに一定レベルの柔軟性を注入しています。チームによっては、変更要求に対処するために、よりシンプルなアプローチを採用する場合もあります。チームはもはや統合エンジニアのような役割を持たず、統一された統合とリリースの計画も立てません、各開発者は自分の変更に責任を持ち、変更を統合するのに十分な品質が改善されるまで変更の追跡を続けます。

さらに、各開発者は、自分たちが扱う変更を統合とリリースの個々の段階にプッシュする責任があり、一般的に利用可能になるまで変更を追跡します。言い換えれば、個々の変更が統合とリリースの段階にあっても、対応する開発者によって追跡され、プッシュされます。これらの変更は、互いに介入することなく、異なる速度とペースでプッシュされることがあります。

相互に独立した変更は、テスト効率を向上させるために、特定のテスト環境を使用し、偶然にも同じバッチテストを通過し、キューイングを避けるために、一般的に同時に利用できるようにします。そのため、開発からリリースまでの期間が最小限に抑えられ、比較的頻繁なリリースにも対応しています。これは、「You build it, you run it」というDevOpsの原則にも合致します。

この変化の傾向は、ソフトウェア開発管理のプラクティスで起こることと似ています。ウォーターフォールモデルは例外です。ウォーターフォールモデルは、イテレーション方式に置き換えられています。スクラム方式のスプリントが典型的な例です。リーン開発では、イテレーションの役割が弱くなります。各イテレーションが何をするのか、どの段階を経験しているのかということから、各ワークインプロセスが現在どの段階にあるのか、各段階のワークインプロセス製品の総数はどうなっているのかということに焦点が切り替わります。

同様に、先行する変更管理方法の焦点は、各特定の統合バージョンの現在の統合とリリースのフェーズから、各変更と各フェーズに含まれる変更の現在の統合とリリースのフェーズへと進化します。

#変更要求の追加的な利点

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/8d1cedbe-e05d-b5e8-b1cf-fa25ee1ee044.png)

前項では、変更依頼管理手法によって可能になった柔軟性と、業務の柔軟性による効率化について説明した。変更依頼管理には、情報の記録と追跡にメリットがあります。

テストやリリースにどのような機能が含まれているかを知るには、単純にどのような変更が含まれているかを見るだけで良く、変更自体には関連する説明文があります。また、変更の目的を詳細に説明するために、要件、タスク、障害などの項目と関連付けることもできます。変更依頼を使用する場合を除いて、他のコードの変更を直接統合に提出することはできません。

変更依頼に対するすべての変更は、対応する機能ブランチ上で行われ、複数の変更を行っても異なる場所に分散されることはありません。したがって、私たちはこれらの変更を便利に閲覧し、操作することができます。その間、私たちは常に変更の状態と現在のフェーズを知ることができます。開発プロセスは終了しているのか？毎日の統合テストの段階に入っているか？一般的に利用可能な状態になっているか？これらの質問に簡単に答えることができます。


変更は、要件、タスク、不具合などの項目に関連付けることができます。一方、変更の状態は自動的に取得することができます。したがって、原則として、かんばん上の追跡項目は、実際の状態を反映するように自動的に移動させることができます。かんばんは、共同作業と進捗状況を明確に示しています。

#デメリットと潜在的なリスク
前述のセクションでは、すべて変更依頼方式のメリットについて話しています。しかし、この方法にはデメリットやリスクがあるのでしょうか？

はい、もちろんあります。爆発的な統合から継続的なデプロイメントパイプラインまで、業界では何十年も前から、常に1つの統合バージョンに統合とリリースのフェーズを順番に経験させるという基本的なモデルを採用してきました。これにより、次のフェーズのコンテンツが前の段階で十分にテストされていることが保証されます。ここで説明する変更依頼の方法は、より柔軟性をもたらし、この基本モデルを大幅に改善します。柔軟性は常に諸刃の剣です。柔軟性は、リスクや誤用の増加を意味することもあります。


"プロセスとツールをめぐる個人と相互作用 "は、アジャイルソフトウェア開発マニフェストの価値観の一つです。この変更要求の方法もこの価値観に沿ったものです。

しかし、実際のシナリオでこの方法を使用することは、チームメンバーにより高い要求を課すことになります。チームメンバーは、実際の具体的なシナリオにおける変更の妥当性とリスクを評価し、異なる選択が効率に与える影響を理解し、具体的なシナリオを総合的に見て判断することが求められます。具体的には

- 変更に対応するコードの修正が少ないほど、途中で変更を削除するリスクが小さくなります。
- 変更に対応したコードの修正が少ないほど、中途半端な変更の修正・改善に対応したコードの修正が少ないほど、リスクが小さくなります。
- ソフトウェアアーキテクチャが優れているほど、途中で変更を削除、修正、改善するリスクが小さくなります。
- 1つの変更と他の変更の間の関連性が小さければ小さいほど、中途半端な変更の削除、修正、改善のリスクが小さくなります。
- 緊急性が高いほど、柔軟な対応を検討すべきです。
- ビジネスの観点からは、ソフトウェアの品質要件が高いほど、柔軟な対応を検討すべきではありません。

実際、マイクロサービスや機能サービスの時代には、変更要求方式でなくても前述のようなリスクは存在します。前述したように、チームメンバー自身が適切な判断力を持つ必要があります。なぜでしょうか？

1つのアプリケーションをマイクロサービスや機能サービスに分割する大きな理由の1つは、それぞれのサービスを別々にテストしてリリースできるからです。しかし、マイクロサービスやファンクションサービスを使用する場合、テストオブジェクトは厳密にはサービスではなく、テスト環境でそのサービスと直接または間接的に相互作用するサービスと他のすべてのサービスが対象となります。各サービスを個別にテストしてリリースすると、現在のテストフェーズでのサービスのバージョンが、次のテストフェーズや一般的な可用性のリリースでのサービスのバージョンと異なることがしばしば発生する可能性があります。これは、変更要求方式と同様のリスクがあります。

したがって、どのサービス変更を一緒にテストしてリリースしなければならないのか、今回はどのサービス変更を別々に動作させることができるのかを判断するために、手動での判断が（おそらくインテリジェントなアルゴリズムの助けを借りて）必要になります。次回は状況が変わる可能性があり、それに応じて適切な判断が求められます。

これから判断すると、統合とリリースは、「常に一つの統合バージョンに統合とリリースの段階を順番に経験させる」というこの基本的なモデルを、すでに超えていることになります。変更依頼の方法は、このことをより明確にしています。

#実装とツールのサポート
前項では、独自のChange Requestメソッドとそのメリット、リスクについて説明しました。では、この方法がアリババでどのように実装されているかを見てみましょう。

まず、この方法に対応するためには、ブランチソリューションが必要になります。基本的には以下のような手順になります。

- マスターブランチは常に最新のリリースバージョンを表します。
- コードの変更は常に機能ブランチで行われます。フィーチャーブランチは常にマスターブランチから引き出され、必要に応じて再びマスターブランチから同期されます。
- 長く続く統合とリリースのブランチは一つも存在しません。その代わり、各統合・リリースステージは、短期的で自動的に管理される統合・リリースブランチに対応しています。統合・リリースブランチは自動的にマスターブランチから引き出され、各機能ブランチは自動的にそのブランチに組み込まれます（競合があった場合は手動での介入が必要です）。そうすると、そのブランチには必要な機能がすべて組み込まれます。
- 機能をさらに修正したり改善したりするには、対応する機能ブランチでこれを行い、その機能ブランチを統合・リリースブランチに組み込みます。

このソリューションは、ツールプラットフォームに高い要件を課しています。ユーザーが必要とするのは、インターフェイスの観点から、統合とリリースの各段階に含まれる変更を管理することだけです。ツールプラットフォームは、このソリューションを、新しいブランチの作成、既存のブランチの再利用、統合・リリースブランチへの機能ブランチの組み込みなど、統合・リリースブランチの管理にマッピングする必要があります。また、同じ組み込みの競合の再発を最小限に抑えるための有用なアルゴリズムも多く含まれています。

ツールプラットフォームへの要求が高いことが、このソリューションがアリババで長年にわたって広く使われてきた理由かもしれません。

以前アリババで働いていた多くの同僚は、「もうこんな良いツールは使えない」と不満を漏らしていました。今ではこれはもはや問題ではありません。Googleが社内のBorgをベースにKubernetesを公に提供しているように、Alibabaも社内のR&DコラボレーションツールプラットフォームAoneをベースにYunxiaoを公に提供しています。

*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*