web-dev-qa-db-ja.com

単一の大規模なソリューション-良いアイデア?

.NET Framework 4.5.2のWindowsフォームアプリケーションを、4つの個別のソリューションと150万行のコード(および10年の開発)を組み合わせて分析しています。

  • Libraries.sln(54プロジェクト)
  • Tools.sln(ライブラリ内の28のプロジェクトに依存する多くの18のプロジェクト)
  • MainApp.sln(ライブラリ内の28のプロジェクトに依存する140のプロジェクト)
  • MainAppTest.sln(MainAppの多くのプロジェクトに依存する60のプロジェクト)

現在、すべての参照は、対応するbin/debugフォルダー内の特定のdllにハードコードされています

現在、1つの特定のマシンでのみビルドを実行できます(正しいドライブマッピングとフォルダー構造を使用)。

建築思想

  • すべてを単一のソリューションと参照プロジェクトに入れます(そのため、ビルドDLLを直接参照しないでください)。ソリューションフォルダーを使用して領域を実質的に分離できます(ライブラリ、テスト、ツール)
  • 既存の4つのソリューションを保持し、28の共有ライブラリ用のプライベートNuGetフィードを使用して開始します(Dev OpsのArtifactsを使用してこれを試してみましたが、正常に機能しますが、pdbデバッグシンボルをパッケージに含めるかどうかに関して複雑になります)。
  • 複数のプロジェクト(28の共有ライブラリなど)を単一のNuGetパッケージにパックします-これには問題があります https://github.com/NuGet/Home/issues/3891

質問

今日の最新のマシンと高速SSDで、現在コードの再利用が他にないソリューションに対して単一の大規模なソリューション(270プロジェクト、1.5mの場所)を持たない理由はありますか?

アップデート1

本当にありがとうございました。時間と回答に本当に感謝しています。

  • 私が解決しようとしている(そしてそれを定義するのに良い)問題は、別のマシンでビルドを機能させることです。そのため、手動であるリリースプロセスを自動化できます(ビルドの10時間/ 11,000テストの実行/ビルド) Innoインストーラー)。 CI/CDにはAzure DevOpsを使用すると思います。

  • Librariesプロジェクトは時々変更されると思いますが、クライアントはデバッグ時にコードにステップインできるようにしたいので、問題がそこにある場合に明確にすることができます。

  • すべてのソリューションの完全なクリーンビルド時間については不明です(再構築に多大な労力を必要とする唯一の稼働中のマシンをそのままにしているため)
  • ビルドスクリプトに関する良いアイデア(もしそうなら)

アップデート2

すべての回答に適切なポイントがあります。ありがとうございます。

4
Dave Mateer

すべての場合と同様に、トレードオフがあります。私のチームが開発しなければならないプロジェクトが1つあります。これは似ていますが、いくつかの点でさらに悪いものです。すべてのプロジェクト名は似ており、それらが差し込まれているフォルダーは意味がありません。結局のところ、あなたのソリューションのセットには、おそらく死んでいて未使用のコードが含まれています。

第一歩

すべてがバージョン管理されていることを確認します。既知の良好な状態に戻せない場合は、本当に悪い状況に陥ります。

ステップ2

何からも参照されていないプロジェクトを削除します。もちろん、デスクトップ、コマンドライン、およびWebアプリケーションをソリューションから除外します。しかし、残骸を選別することで、次に対処する必要のあるものを最小限に抑えることができます。

たとえば、Libraries.slnで定義されている56のライブラリのうち28のみが定義されている場合、残りのすべてのプロジェクトを実行する必要はありません。それらを取り除く(バージョン管理からいつでも復活させることができます)。

ステップ3

毒を選ぶ:絶対パスを定義してコンパイル済みライブラリをプッシュするか、それらをNugetにパッケージ化してローカルのNugetサーバーに公開します。時間が許せば、後者を強くお勧めします。壊れにくいです。

ステップ4

手順3で定義した方法で公開されたライブラリを使用するようにプロジェクトを調整します。

すべてが完了すると...

これで、これらを個別のプロジェクトとして管理するのか、1つの大きなプロジェクトとして管理するのがより簡単であるか、またはより適切であるかを判断するためのより良い立場にあります。

1つの大きなソリューションの大きな問題は、Visual Studioで管理するのが非常に扱いにくいことです。フォルダを使用して組織を追加する必要がありますが、フォルダに名前を付けて整理する方法に注意してください。そうしないと、探しているものが見つかりません。

ソリューション内でプロジェクトをマージする(つまり、2つのライブラリを1つにする)ことについては、他のプロジェクトへの影響に気づくまではお勧めしません。

ライブラリがNuget経由でデプロイされている場合は、いくつかのプロジェクトをお勧めします。

5
Berin Loritsch

あなたが説明する構造は非常に問題があると思います。なぜ誰かがこのようなプロジェクト構造を作るのか理解しています。しかし、それは本当の問題の回避策にすぎず、解決策ではないと私は信じています。

経験則は次のとおりです。頻繁に変更されるアセンブリを1つのソリューションにまとめます。また、プロジェクトが頻繁に変更される場合は、依存するプロジェクトを同じソリューションで維持してください。

つまり、Solution1のプロジェクトAに変更を加え、Solution2に切り替えて正しくビルドできることを確認すると、問題が発生します。そして最善の解決策は、これらのプロジェクトを1つのソリューションにまとめることです。

アセンブリを外部ライブラリとしてソリューションに分割する場合、ライブラリのAPIが安定していて高品質であることを確認する必要があります。悪いAPIのライブラリを使用しなければならず、APIを簡単に変更できないことは、全体的な設計の品質に非常に有害です。ライブラリのAPIが安定していて高品質であると確信している場合は、そのライブラリからNuGetパッケージを作成すると、作業がはるかに簡単になります。

私の個人的な経験では、開発者がプロ​​ジェクト間でこのようなAPIを作成することはめったになく、ライブラリとしての分割プロジェクトを完全に実行可能にしています。優れたライブラリAPIを作成するには、多くの意図的な努力とスキルが必要です。それは自然にそして有機的に起こるものではありません。特にあなたのような大規模で古いプロジェクトで。私が賭けたとしても、プロジェクトのどのライブラリも個別のNuGetパッケージとして保持する価値はありません。

現在、すべての参照は、対応するbin/debugフォルダー内の特定のdllにハードコードされています

うん。これはいけません。ずっと。 「プロジェクトの依存関係」を使用して、プロジェクトが正しい順序でビルドされるようにする必要があります。そして、この設定を正しく保つのはPITAです。直接のプロジェクト参照またはNuGet参照が物事を簡単にする場合。

現在、1つの特定のマシンでのみビルドを実行できます(正しいドライブマッピングとフォルダー構造を使用)。

私はあなたが何をするか気にしません。これを修正!これは、構造が間違っているという大きな赤信号です。

MainApp.slnおよびMainAppTest.sln

これは明らかに間違っています。テストするコードが変更されると、テストは常に変更されます。それらを別々のソリューションに保存すると、上記の経験則がすぐに破られます。アセンブリとそのテストアセンブリは常に同じソリューションである必要があります。彼らがどのようにしてさまざまなソリューションで快適に存在できるかはわかりません。

4
Euphoric

ここではすでにいくつかの優れた答えがありますが、主な問題であると述べたものに焦点を当てましょう別のマシンでビルドを動作させる

これは、現在のプロジェクト/ソリューション構造で発生する他の問題とほぼ直交になるはずです。それがあなたの最優先事項である場合、私は最初にこれを解決することをお勧めします。すべてを1つのソリューションに統合しても、主な目標に近づくことはできません。

コメントで@JohnWuが言及したように、ビルドスクリプトから始めます。このスクリプトは

  • 必要ないくつかの環境変数を初期化します(おそらく、必要なツールがインストールされているフォルダーを検出します)

  • 必要なドライブフォルダーが使用可能かどうかを確認します(または他の前提条件)

  • 実行msbuild.exe(またはdevenv.exe)4つのソリューションの正しい順序で、正しい構成(およびビルドの1つが失敗した場合の検出を含む)。これがどのように見えるかを理解するために、ここにビルドスクリプトの1つの抜粋を示します。

    %MSBUILD% /m /p:Configuration=Release %MYFOLDER%\MySolution.sln >MyBuild.log
    if ERRORLEVEL 1 goto :displayerror
    find "0 Warn" MyBuild.log >nul:
    if ERRORLEVEL 1 goto :displayerror
    
  • リリースプロセスに必要なすべてのEXEファイル、DLL、ドキュメント、構成テンプレートを「展開」フォルダにコピーします(それ以上ではありません)。

必要なビルドツールがインストールされている標準(Visual Studioが配置されているフォルダーなど)があることを確認することをお勧めします。ビルドスクリプトは、異なる環境間のいくつかの違いを軽減することができますが、必要以上に難しくするべきではありません。

さて、あなたの目標は、任意のマシンのあるフォルダにあるソースツリー全体をチェックアウトし、そのスクリプトを実行してビルドを完了することです。

このため、VSプロジェクトからすべての絶対パス参照を削除することが重要です。すべての参照、すべてのビルド前またはビルド後のイベントは、可能な限り、相対パスを使用する必要があります。このため、「プロジェクト参照」またはDLL参照)を使用するかどうかは関係ありません。どちらも相対パスである必要があります。

ビルド前またはビルド後のイベントの一部で絶対参照をすべて削除できない場合は、このタスクのビルドスクリプトから環境変数の初期化を利用できます。これらを独自のヘルパースクリプトに入れて、必要な場所でそのスクリプトを呼び出すだけです。

最後に、プロジェクトに不要な構成が含まれていないことを確認することを強くお勧めします。 Visual Studioの構成マネージャーを使用して、どの構成があるかを確認し、不要なものをすべて削除します。たとえば、標準の "AnyCPU"構成のみが必要な場合は、 "x86"および "x64"構成がないことを確認します(構成が異なる場合、Visual Studioはデフォルトで "間違ったもの"を開く傾向があります。 IDEで次のビルドを実行すると、問題が発生する可能性があります。

2
Doc Brown