Visual Studio(2008)の大規模ソリューションのベストプラクティス[終了]


87

約100以上のプロジェクトでソリューションがあり、そのほとんどがC#です。当然、開くことも構築することも時間がかかるので、そのような獣のベストプラクティスを探しています。私が答えを得ることを望んでいる質問の線に沿って、次のとおりです。

  • プロジェクト間の参照をどのように処理するのが最適ですか
    • 「ローカルコピー」をオンにするかオフにするか。
  • すべてのプロジェクトを独自のフォルダーにビルドする必要がありますか、それともすべて同じ出力フォルダーにビルドする必要があります(すべて同じアプリケーションの一部です)

  • ソリューションのフォルダは、ものを整理するための良い方法ですか?

ソリューションを複数の小さなソリューションに分割することはオプションですが、それは独自のリファクタリングと構築の頭痛の種を伴うので、おそらく別のスレッドのためにそれを保存することができます:-)


2
1つのソリューションに100以上のプロジェクトが必要な理由を尋ねてもよいですか?彼らはそれぞれ独自のアセンブリを作成していますか?
ニールN

1
はい、そうです。それぞれが論理的に別個の機能を表しています。
Eyvind

2
@ Eyvind-それはクラスと名前空間の目的ではありませんか?別々のアセンブリはどのような利点をもたらしますか?潜在的に小さなアップグレードやメモリ使用量(一部がロードされていない場合)など、いくつか考えることができますが、コンパイルと管理に100以上のアセンブリを用意するには確かにコストがかかります。
si618 2009年

1
@マーク私はあなたの痛みを感じます。ここには最大94のプロジェクトがあります。再構築するために複数のチームの開発を停止する必要があるため、今はそれについて多くを行うことはできません。他の91を参照する3つのEXEプロジェクトがあります。私は1つの共通の出力フォルダーで実験していますが、これまでのところ、その利点は非常に印象的です。
ケビン

2
男、100歳以上?それは...今ここに約600を押して...私たちが持っているものは何もありません
C・ジョンソン

回答:


41

私が書いたこれら2つのMSBuildの記事に興味があるかもしれません。

MSBuild:信頼性の高いビルドを作成するためのベストプラクティス、パート1

MSBuild:信頼性の高いビルドを作成するためのベストプラクティス、パート2

特にパート2には、見てみたいと思われる大きなソースツリーの構築のセクションがあります。

ここであなたの質問に簡単に答えるには:

  • CopyLocal?確かにこれをオフにしてください
  • 1つまたは複数の出力フォルダーにビルドしますか?1つの出力フォルダーにビルドする
  • ソリューションフォルダ?これは好みの問題です。

イブラヒム橋見は言った

私の本:Microsoft Build Engineの内部:MSBuildとTeam FoundationBuildの使用


ありがとう、私はそれらを必ずチェックします!
Eyvind

1
私はこの本とその素晴らしい本を持っていると言います。これは、TFSビルドとローカル開発ビルドを非常に広範囲に自動化するのに役立ちました。私は現在インクリメンタルビルドに取り組んでおり、この本は主題に非常に深く関わっています。価格の価値があります。ありがとうと言った。これからもいい結果を出し続けてください。
irperez 2011年

コメントをありがとうirperez–
イブラヒム橋

2
CopyLocalを無効にするための無条件の推奨事項の場合は-1。CopyLocal = falseを設定すると、展開時にさまざまな問題が発生する可能性があります。「サブ配列を理解していない限り、falseにプロジェクト参照。」私のブログ記事「ない変更」ローカルコピーを参照してください(geekswithblogs.net/mnf/archive/2012/12/09/...
マイケルFreidgeimに

「1つの出力フォルダーにビルド」すると、複数のスレッドでコンパイルするときに問題が発生する可能性がありますか?
BrunoLM 2015年

9

ものを整理するのに役立つソリューションフォルダの使用を控えるための+1 。

独自のフォルダへのプロジェクト構築の+1。最初に共通の出力フォルダーを試しましたが、これにより、古い参照を見つけるのが微妙で苦痛になる可能性があります。

FWIWでは、ソリューションにプロジェクト参照を使用しています。最近はnugetの方が適していると思われますが、svn:externalsはサードパーティと(フレームワークタイプの)社内アセンブリの両方で適切に機能することがわかりました。svn:externalsを参照するときは、HEADの代わりに特定のリビジョン番号を使用する習慣を身に付けてください(有罪:)


2
+1一般的な出力フォルダソリューションにも問題があります。私は、もう少し説明してくださいどのような手段「ソリューションのプロジェクト参照」を理解していなかった...
マウリシオ・シェファー

のように、VS->参照の追加->参照の代わりに、VS->参照の追加->プロジェクトを使用します。私が知っている小さな点ですが、一部の人々はそれを異なって行います(そしてこれはより多くの頭痛を引き起こすと思います)。MSBuild csprojテキストを見ると、Referenceの代わりにProjectReferenceプロパティが表示されます。
si618 2009年

面白い答え!私たちはあなたがジグザグしたところをジグザグにしたと思います。ソリューションフォルダーはまったくなく、プロジェクトの名前付けに依存しています(プロジェクトの名前は名前空間と同じです)。すべての出力は単一のフォルダーに入れられるため、開発者のセットアップはデプロイメントのものにはるかに近くなります。依存関係が正しく設定されている場合、古い参照はありません。
トーマスブラット

ええ、共通の出力ディレクトリは、特にresharperを使用するときに、多くの苦痛をもたらします。確かに時代遅れの参照。
Florian Doyon 2010年

1
@Kevin、もう数年ですが、メモリからの1つの例は、同じアセンブリを参照する2つのプロジェクトです。たとえば、プロジェクトが参照されていない外部ライブラリです。同じバージョンであれば問題ありませんが、このライブラリの新しいリリースがリリースされますが、参照を更新するプロジェクトは1つだけです。どのバージョンが共通の出力フォルダーで使用されますか?
si618 2011

8

あまり使用しないプロジェクトをアンロードし、SSDを購入します。SSDはコンパイル時間を改善しませんが、VisualStudioのオープン/クローズ/ビルドが2倍速くなります。


3
プロジェクトのアンロードはユーザーごとの設定であるため、チームの開発者は関心のあるプロジェクトのみをロードできることに注意してください。これは私たちのチームを本当に助けてくれました。
ページ

Solution Load Manager拡張機能visualstudiogallery.msdn.microsoft.com/…を使用して、デフォルトでロードしないものを定義できます
Michael Freidgeim 2012

6

109の個別のプロジェクトを処理する必要があるため、同様の問題が発生します。私たちの経験に基づいて元の質問に答えるには:

1.プロジェクト間の参照をどのように最適に処理しますか

「参照の追加」コンテキストメニューオプションを使用します。'project'が選択されている場合、依存関係はデフォルトで単一のグローバルソリューションファイルに追加されます。

2.「ローカルコピー」をオンにするかオフにするか。

私たちの経験ではオフ。余分なコピーは、ビルド時間を増やすだけです。

3.すべてのプロジェクトを独自のフォルダーにビルドする必要がありますか、それともすべて同じ出力フォルダーにビルドする必要があります(すべて同じアプリケーションの一部です)。

すべての出力は、「bin」と呼ばれる単一のフォルダーに配置されます。このフォルダは、ソフトウェアが展開されたときと同じであるという考えです。これにより、開発者の設定がデプロイメントの設定と異なる場合に発生する問題を防ぐことができます。

4.ソリューションフォルダは、ものを整理するための良い方法ですか?

私たちの経験ではありません。ある人のフォルダ構造は別の人の悪夢です。深くネストされたフォルダは、何かを見つけるのにかかる時間を増やすだけです。完全にフラットな構造ですが、プロジェクトファイル、アセンブリ、名前空間に同じ名前を付けます。


プロジェクトを構造化する私たちの方法は、単一のソリューションファイルに依存しています。プロジェクト自体が変更されていなくても、これを構築するには長い時間がかかります。これを支援するために、通常、別の「現在のワーキングセット」ソリューションファイルを作成します。私たちが取り組んでいるプロジェクトはすべてこれに追加されます。ビルド時間が大幅に改善されましたが、現在のセットにないプロジェクトで定義されたタイプに対してIntellisenseが失敗するという問題があります。

ソリューションレイアウトの部分的な例:

\bin

OurStuff.SLN

OurStuff.App.Administrator
OurStuff.App.Common
OurStuff.App.Installer.Database
OurStuff.App.MediaPlayer
OurStuff.App.Operator
OurStuff.App.Service.Gateway
OurStuff.App.Service.CollectionStation
OurStuff.App.ServiceLocalLauncher
OurStuff.App.StackTester
OurStuff.Auditing
OurStuff.Data
OurStuff.Database
OurStuff.Database.Constants
OurStuff.Database.ObjectModel
OurStuff.Device
OurStuff.Device.Messaging
OurStuff.Diagnostics
...
[etc]

「1つの出力フォルダーにビルド」すると、複数のスレッドでコンパイルするときに問題が発生する可能性がありますか?
BrunoLM 2015年

4

ここでも同様の大規模プロジェクトに取り組んでいます。ソリューションフォルダは物事を整理するための良い方法であることが証明されており、ローカルコピーをtrueに設定したままにする傾向があります。各プロジェクトは独自のフォルダーにビルドされ、そこにデプロイ可能なプロジェクトごとに、バイナリの正しいサブセットが配置されていることがわかります。

時間の開始と時間の構築に関しては、より小さなソリューションに分割せずに修正するのは難しいでしょう。ここで速度を向上させるために、ビルドの並列化(これを実行してUIに統合する方法についてはGoogleの「ParallelMSBuild」)を調査できます。また、設計を見て、プロジェクトの一部をリファクタリングして全体的な数を減らすことが役立つかどうかを確認します。


3

ビルドの手間を軽減するという観点から、ビルドの[構成マネージャー...]オプションを使用して、特定のプロジェクトのビルドを有効または無効にすることができます。特定のプロジェクトを除外して、特定のプロジェクトをターゲットにするときに使用できる「プロジェクト[n]ビルド」を作成できます。

100以上のプロジェクトに関する限り、ソリューションサイズを削減することの利点についてこの質問に打ちのめされたくないことはわかっていますが、読み込み時間の短縮に関しては他に選択肢はないと思います(そしてdevenvのメモリ使用量)。


うーん、これは間違っていたのか、それとも単に反対したのか?理由を教えていただければ、前者と一緒に暮らすことができます。
Michael Meadows

同意しました。コメントなしで
反対票を投じる

2
ところで、私は個人的に、この種のことのために構成管理をいじくり回すのは好きではありません。どうして?変更した構成を誤ってコミットすると、ビルドサーバーまたは他の開発者が影響を受けるためです。
si618 2009年

同意しました。実際、同じ問題は、プロジェクトが多すぎるソリューションにも当てはまります。:)
Michael Meadows

3

私がこれで通常行うことは、「デバッグ」プロセスが実際にどのように行われるかに少し依存します。通常、ローカルコピーをtrueに設定していませんが。各プロジェクトのビルドディレクトリを設定して、すべてを目的のエンドポイントに出力します。

したがって、ビルドするたびに、すべてのdllとWindows / Webアプリケーションが格納されたフォルダーが作成され、すべてのアイテムが適切な場所に配置されます。dllは最終的に正しい場所に配置されるため、ローカルコピーは必要ありませんでした。

注意

上記は私のソリューションで機能します。これは通常、Webアプリケーションであり、参照に関する問題は発生していませんが、可能性があります。


3

同様の問題があります。より小さなソリューションを使用して解決します。すべてを開くマスターソリューションがあります。しかし、パフォーマンス。その上で悪いです。そのため、開発者の種類ごとに小さなソリューションをセグメント化します。したがって、DB開発者には、関心のあるプロジェクトをロードするソリューションがあり、サービス開発者とUI開発者は同じことを行います。誰かがソリューション全体を開いて、日常的に必要なことを実行しなければならないことはめったにありません。それは万能薬ではありません-それはそれが良い面と悪い面を持っています。この記事の「マルチソリューションモデル」を参照してください(VSSの使用に関する部分は無視してください:)


2

ソリューションの場合、これほど大きなベストプラクティスはそれらを分割することだと思います。「解決策」は、問題の解決策に取り組むために必要なプロジェクトやおそらく他の部分をまとめる場所と考えることができます。100以上のプロジェクトを、問題全体の一部のみのソリューションの開発に特化した複数のソリューションに分割することで、必要なプロジェクトとのやり取りを高速化し、問題のドメインを簡素化することで、特定の時間に処理する量を減らすことができます。

各ソリューションは、それが担当する出力を生成します。この出力には、自動化されたプロセスで設定できるバージョン情報が含まれている必要があります。出力が安定したら、依存プロジェクトおよびソリューションの参照を最新の内部ディストリビューションで更新できます。それでもコードにステップインしてソースにアクセスする場合は、Visual Studioを使用して参照アセンブリにステップインしたりソースコードをフェッチしたりできるMicrosoftシンボルサーバーを使用して、実際にこれを行うことができます。

同時開発は、インターフェースを事前に指定し、開発中のアセンブリをモックアウトして、完全ではないが開発したい依存関係を待っている間に実行できます。

この方法で物理的に分解すると、全体的な作業がどれほど複雑になるかには制限がないため、これがベストプラクティスであると思います。すべてのプロジェクトを1つのソリューションにまとめると、最終的には上限に達します。

この情報がお役に立てば幸いです。


2

約60以上のプロジェクトがあり、ソリューションファイルは使用していません。C#プロジェクトとVB.Netプロジェクトが混在しています。パフォーマンスは常に問題でした。すべてのプロジェクトに同時に取り組むわけではありません。各開発者は、作業中のプロジェクトに基づいて独自のソリューションファイルを作成します。ソリューションファイルはソース管理にチェックインされません。

すべてのクラスライブラリプロジェクトは、ソースディレクトリのルートにあるCommonBinフォルダにビルドされます。実行可能/ Webプロジェクトは個々のフォルダーにビルドされます。

プロジェクト参照は使用せず、代わりにCommonBinフォルダーからのファイルベースの参照を使用します。プロジェクトを検査してビルドの順序を決定するカスタムMSBuildタスクを作成しました。

私たちはこれを数年使用しており、苦情はありません。


3
カスタムmsbuildタスクを共有していただけませんか?
andreapier 2013年

0

それはすべて、ソリューションとプロジェクトが何であるかについてのあなたの定義と見方に関係しています。私の考えでは、解決策はまさにそれであり、非常に特定の要件を解決するプロジェクトの論理的なグループ化です。大規模なイントラネットアプリケーションを開発します。そのイントラネット内の各アプリケーションには独自のソリューションがあり、exeまたはWindowsサービスのプロジェクトが含まれている場合もあります。そして、基本クラスやヘルパー、httphandlers / httpmodulesなどを備えた一元化されたフレームワークがあります。基本フレームワークはかなり大きく、すべてのアプリケーションで使用されます。このように多くのソリューションを分割することで、ソリューションに必要なプロジェクトの量を減らすことができます。それらのほとんどは互いに関係がないためです。

ソリューションにこれだけ多くのプロジェクトがあるのは、悪い設計です。多くのプロジェクトを解決策の下に置く理由はないはずです。私が目にするもう1つの問題は、プロジェクトの参照に関するものです。特に、ソリューションをより小さなものに分割したい場合は、最終的には本当に失敗する可能性があります。

私のアドバイスは、これを実行し、一元化されたフレームワークを開発することです(必要に応じて、エンタープライズライブラリの独自の実装)。共有するためにGACするか、ファイルの場所を直接参照して中央ストアを作成することができます。一元化されたビジネスオブジェクトにも同じ戦術を使用できます。

DLLを直接参照する場合は、プロジェクト内でcopy local false(c:\ mycompany \ bin \ mycompany.dllなど)を使用してDLLを参照する必要があります。ランタイムGACまたはランタイムビンにないファイルを参照するように、app.configまたはweb.configにいくつかの設定を追加する必要があります。実際には、コピーがローカルであるかどうか、またはdllが最終的にbinにあるか、GACにあるかは関係ありません。これは、構成によって両方がオーバーライドされるためです。ローカルをコピーしてシステムが乱雑になるのは悪い習慣だと思います。ただし、これらのアセンブリの1つにデバッグする必要がある場合は、ローカルを一時的にコピーする必要があります。

GACなしでDLLをグローバルに使用する方法に関する私の記事を読むことができます。GACは、xcopyの展開を妨げ、アプリケーションの自動再起動をトリガーしないため、私は本当に嫌いです。

http://nbaked.wordpress.com/2010/03/28/gac-alternative/


0

CopyLocal = falseを設定すると、ビルド時間が短縮されますが、展開時にさまざまな問題が発生する可能性があります。

「ローカルのコピー」をTrueのままにする必要がある場合、多くのシナリオがあります。たとえば、トップレベルのプロジェクト、第2レベルの依存関係、リフレクションによって呼び出されるDLLなどです。

CopyLocal = falseを設定した私の経験は成功しませんでした。私のブログ投稿「サブシーケンスを理解しない限り、「ローカルコピー」プロジェクト参照をfalseに変更しないでください」の賛否両論の要約を参照してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.