コンポーネント化によるコラボレーションとアジャイル開発の促進

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

製品は成功し、組織は成長しており、この成功に合わせてコードベースをスケールアップします。 1 つの製品で 1 つのコードベースで作業している過去 2 ~ 3 チームをスケールアウトすると、次のような質問をする場合があります。

  • チームが再利用可能なコンポーネントを効率的に共有するにはどうすればよいですか?

  • 操作方法、機能チームが他のチームの作業を踏まずに迅速に反復できるようにしますか?

  • 操作方法チームに自律性を与え、適切なペースで反復処理を行うことができますか?

どの段階のチームでも、これらの質問を検討することでメリットを得ることができます。 従来のコードベースを持つ確立されたチームの場合は、これまで以上に迅速に、より多くの価値を提供するように求められているのと同じ質問をする可能性があります。 状況に関係なく、コンポーネント化は、チームの規模と今日の開発のスピードに合わせてスケーリングするコードベースを構築するのに役立ちます。

この記事では、Azure Artifacts を介したバイナリコンポジションが、外部の依存関係、オープンソース ソフトウェア、および分離された共有コンポーネントを管理および共有するのにどのように役立つかについて説明します。

コンポーネントと構成

コンポーネント化とは、製品を個別のコンポーネントに分割して整理するプロセスです。 ほとんどの .NET プロジェクトには、ソリューション内のプロジェクトの形式でコンポーネントの概念が既にあります。 たとえば、基本的な Web サイトは、フロントエンド コンポーネント、データ アクセス コンポーネント、モデル/データ ストレージ コンポーネントで構成される場合があります。

ソースコンポジション

製品が成長すると、ソリューションとプロジェクト モデルが非効率的になる可能性があります。 変更は統合に時間がかかり、マージが困難になり、ビルドが遅くなり、コンポーネントが 1 つのプロジェクトから複数のプロジェクトに拡大し始めます。 一般に、これはチームが関連プロジェクトのこれらのセットを個別のソリューションに分割し始めるポイントです。

1 つのソリューションを拡張したら、コンポーネント化する方法が興味深い質問になります。 ソースコンポジションから始めて、Visual Studio のプロジェクト参照を介して各コンポーネントを参照します。 ソースコンポジションは、ソースが単一のコンポジション境界(単一のソースリポジトリ内の単一のソリューション)に存在する限り可能です。

残念ながら、これらのプロジェクト参照は、複数のソリューションが関係する場合に分解し始めます。 この時点で、ソリューション A がソリューション B に依存する場合は、ソリューション B によって生成されるビルドされたバイナリ (DLL など) を参照する必要があります。これはバイナリ構成です

したがって、これらのバイナリは、正常にビルドする前に、ソリューション A でビルドして使用できるようにする必要があります。 これを行うには、いくつかの方法があります。

  • ソース管理にチェックできます。 ソース管理システムに応じて、バイナリはリポジトリのサイズをすばやく吹き出し、チェックアウト時間と一般的なリポジトリのパフォーマンスを低下させることができます。 ブランチで作業を開始すると、複数のチームが異なるバージョンで同じバイナリを導入し、困難なマージの競合に至る可能性があります。

  • または、ファイル共有でホストすることもできますが、この方法には特定の制限があります。 ファイル共有にはクイック検索のインデックスがないため、将来のバージョンの上書きに対する保護は提供されません。

パッケージの構成

パッケージは、バイナリを参照する多くの課題に対処します。 それらをソースにチェックするのではなく、ソリューション B に、別のソリューション A が使用できる NuGet パッケージとしてバイナリを生成させることができます。 ソリューション A とソリューション B が個別のコンポーネントとしてメイン、A と B の同時変更がまれである場合、パッケージコンポジションは、B に対する A の依存関係を管理するための優れた方法です。パッケージコンポジションでは B が独自の周期で反復処理でき、A のスケジュールが許可されている場合、A は B から更新を自由に取得できます。 これにより、複数のチームがソリューション A (または他のソリューション C または D) に影響を与えることなく、ソリューション B を反復処理および更新できます。

ただし、パッケージ構成には独自の課題があります。 ここまで、簡単な例を調べました。 大きなコードベース (Windows や Bing など) のサイズまでパッケージの構成をスケーリングすると、一連の課題が発生する可能性があります。

  • 依存関係グラフの低いコンポーネントの破壊的変更の影響を理解することは非常に困難になります。

  • ダイヤモンドの依存関係 は、機敏性の重要な障害になる可能性があります。 ひし形の依存関係では、コンポーネント B と C の両方が共有コンポーネント A に依存し、コンポーネント D は B と C の両方に依存します。コンポーネント A が破壊的変更を伴う新しいバージョンを導入した場合、B が新しいバージョンに更新されても C が更新されない場合、D は依存関係の競合を発生させずに B の更新プログラムを取得できません。 この単純な例では、競合を解決するために必要な C との会話がすべてである可能性があります。 しかし、複雑なグラフでは、ダイヤモンドはすぐに解決不能になる可能性があります。

  • パッケージを使用して構成される 2 つのコンポーネントに変更を適用する必要がある場合、開発者の反復サイクルが大幅に遅くなります。 コンポーネント A が更新されると、コンポーネント A の再構築、再パッケージ化、再発行が必要になります。 その後、コンポーネント B は、コンポーネント A で行われた変更を検証するために、最近公開されたバージョンに更新する必要があります。コンポーネント A と B の同時ビルドを可能にするソースコンポジションを使用すると、開発者は一貫して迅速な反復サイクルを実現できます。

使用する必要がある内容

一般に、大規模なチームがコンポジション戦略を組み合わせたとき、最も成功しているのを見てきました。 コードベースに適したものを判断するには、まず製品の依存関係グラフをマッピングし、コンポーネントを関連コンポーネントのセットにグループ化することから始めます。

たとえば、フレームワークを構成するコンポーネントのコレクションと、ユーザー向けサービスを形成するコンポーネントの別のセットがある場合があります。 次に、関連するコンポーネントのグループごとに、次の質問をします。

  • チームに対して確立したセット全体で頻繁にチェックインを予測できますか?

  • 1 つのチームがセット全体を担当していますか?

  • 1 セットの場合、共有リリース周期はありますか?

この経験から、ソースコンポジションの使用は、1 つのチームまたは関連チームのグループによって処理される関連プロジェクトに最も効果的であることがわかりました。 逆に、バイナリ構成は、オープンソース ソフトウェア、外部依存関係 (離れたチームまたは分離されたチームのコンポーネント)、独立した共有コンポーネントに有利であることが証明されます。