Visual Studio中大型解决方案的最佳实践(2008)[关闭]


87

我们有一个解决方案,涉及大约100多个项目,其中大多数是C#。自然,打开和构建都需要很长时间,因此我正在寻找此类野兽的最佳实践。我希望得到的答案是:

  • 您如何最好地处理项目之间的引用
    • 应该打开还是关闭“本地复制”?
  • 应该将每个项目都构建到其自己的文件夹,还是应该将它们都构建到相同的输出文件夹(它们都属于同一应用程序)

  • 解决方案的文件夹是整理资料的好方法吗?

我知道将解决方案分为多个较小的解决方案是一种选择,但这带有其自身的一系列重构和令人头疼的问题,因此也许我们可以将其保存在单独的线程中:-)


2
请问为什么一个解决方案需要100多个项目?他们每个人都在创建自己的程序集吗?
尼尔·N

1
是的,它们是,它们每个都代表逻辑上独立的功能。
艾文德

2
@Eyvind-这不是什么类和名称空间吗?单独的装配为您带来什么好处?我可以想到一些功能,例如可能较小的升级和内存使用(如果未加载某些功能),但是拥有100多个组件进行编译和管理肯定会带来成本。
si618

1
@马克,我感到你很痛苦。我们这里有多达94个项目。现在不能做太多事情了,因为我们必须暂停多个团队的开发以进行重组。我们有3个EXE项目引用其他91个项目。我正在尝试一个通用的输出文件夹,到目前为止,取得的成就是非常可观的。
凯文

2
伙计,一百多岁?那对我们已经没有什么...现在将近600个推到这里...
C Johnson

Answers:


41

您可能对我写的这两篇MSBuild文章感兴趣。

MSBuild:创建可靠版本的最佳实践,第1部分

MSBuild:创建可靠版本的最佳实践,第2部分

特别是在第2部分中,您可能要看一下“构建大型源代码树”一节。

要在这里简要回答您的问题:

  • CopyLocal?确定关闭此功能
  • 构建到一个或多个输出文件夹?构建到一个输出文件夹
  • 解决方案文件夹?这是一个品味问题。

易卜拉欣·哈希米说

我的书:在Microsoft Build Engine中:使用MSBuild和Team Foundation Build


谢谢男人,我一定会检查出来的!
Eyvind

1
我会说我有这本书,而且很棒。它帮助我使TFS构建自动化,并且本地开发人员构建非常广泛。我现在正在从事增量构建,这本书非常深入地探讨了该主题。值得的价格。谢谢。继续努力。
irperez 2011年

感谢irperez的评论
易卜拉欣·哈希米(Ibrahim

2
-1为UNCONDITIONAL建议以禁用CopyLocal。设置CopyLocal = false可能在部署期间导致其他问题。请参见我的博客文章“不改变”复制本地”项目引用为假,除非了解序列。”(geekswithblogs.net/mnf/archive/2012/12/09/...
迈克尔Freidgeim

使用多个线程进行编译时,“构建到一个输出文件夹”会引起问题吗?
BrunoLM

9

+1备用使用解决方案文件夹来帮助组织内容。

+1用于将项目构建到其自己的文件夹。最初,我们尝试了一个常见的输出文件夹,这可能会导致微妙而痛苦地查找过时的引用。

FWIW,我们使用项目参考作为解决方案,尽管现在nuget可能是一个更好的选择,但发现svn:externals对于第3方和(框架类型)内部组装均适用。引用svn:externals时,要养成使用特定版本号而不是HEAD的习惯(有罪的:)


2
+1我也对通用输出文件夹解决方案有疑问。我不明白“解决方案的项目参考”的含义,请多解释一下...
Mauricio Scheffer,2009年

就像我们使用VS-> Add Reference-> Projects一样,而不是VS-> Add Reference-> Browse。我知道的一点,但有些人的做法有所不同(我认为这会引起更多的头痛)。如果查看MSBuild csproj文本,将看到ProjectReference属性而不是Reference。
si618 2009年

有趣的答案!我想我们在你z拉的地方曲折了。我们根本没有解决方案文件夹,它依赖于项目命名(项目的名称与名称空间相同)。我们所有的输出都放在一个文件夹中,这使开发人员的设置与部署更接近。如果依存关系设置正确,则我们没有过期的引用。
Thomas Bratt,2009年

是的,常见的输出目录会带来很多麻烦,尤其是在使用Resharper时。确实是过时的参考。
Florian Doyon 2010年

1
@Kevin,已经有好几年了,但是从内存来看,一个例子是两个引用同一程序集的项目,比如说一个外部库,它没有被项目引用。当它们使用相同版本时,一切都很好,但是此库的新版本发布了,但是只有一个项目更新了它们的引用,哪个版本在公共输出文件夹中使用?
si618 2011年

8

卸载不常用的项目,然后购买SSD。SSD不能改善编译时间,但是Visual Studio的打开/关闭/构建速度快两倍。


3
值得注意的是,卸载项目是针对每个用户的设置,因此团队中的开发人员只能装载他们关心的项目。这确实帮助了我们的团队。

您可以使用解决方案负载管理器扩展visualstudiogallery.msdn.microsoft.com/…来定义默认情况下不加载的内容
Michael Freidgeim

6

我们有类似的问题,因为我们有109个单独的项目要处理。根据我们的经验回答原始问题:

1.您如何最好地处理项目之间的引用

我们使用“添加参考”上下文菜单选项。如果选择“项目”,则默认情况下将依赖项添加到我们的单个全局解决方案文件中。

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]

使用多个线程进行编译时,“构建到一个输出文件夹”会引起问题吗?
BrunoLM

4

我们在这里从事类似的大型项目。实践证明,解决方案文件夹是组织事情的一种好方法,我们倾向于将copy local设置为true。每个项目都构建到其自己的文件夹,然后我们知道对于其中的每个可部署项目,我们都有正确的二进制子集。

至于时间的开放和时间的建立,如果不采用更小的解决方案,将很难解决。您可以在此处研究如何并行化构建(通过Google的“ Parallel MS Build”进行并行化并集成到UI中)来提高速度。另外,请查看设计并查看是否重构某些项目以减少总体数量可能有所帮助。


3

为了减轻构建的麻烦,您可以对构建使用“ Configuration Manager ...”选项,以启用或禁用特定项目的构建。您可以拥有一个“项目[n]构建”,它可以排除某些项目,并在定位特定项目时使用。

就100多个项目而言,我知道您不希望在缩小解决方案规模的好处这一问题上受挫,但我认为在加快加载时间方面,您别无选择。内存使用率)。


嗯,这是因为错误,还是只是因为不同意而受到谴责?如果您能告诉我原因,我可以与前者同住。
Michael Meadows,2009年

同意,我不喜欢
无故投降

2
顺便说一句,我个人不喜欢这种配置管理。为什么?因为如果您不小心提交了修改后的配置,那么您的构建服务器或其他开发人员将受到影响。
si618

同意 实际上,相同的问题适用于具有太多项目的解决方案。:)
Michael Meadows

3

我通常会做些什么,实际上取决于“调试”过程是如何发生的。通常,尽管我没有将本地副本设置为true。我为每个项目设置构建目录,以将所有内容输出到所需的端点。

因此,每次构建后,我都有一个包含所有dll和所有Windows / Web应用程序的填充文件夹,并且所有项目都位于正确的位置。不需要复制本地,因为dll最终位于正确的位置。

注意

上面的代码适用于我的解决方案,通常是Web应用程序,我在引用方面没有遇到任何问题,但是可能!


3

我们有一个类似的问题。我们使用较小的解决方案来解决。我们有一个可以打开所有内容的主解决方案。但是性能。那是不好的。因此,我们按开发人员类型细分较小的解决方案。因此,数据库开发人员拥有一种解决方案,可以将他们关心的项目加载到服务开发人员和UI开发人员中。很少有人需要打开整个解决方案来完成他们每天需要做的事情。它不是灵丹妙药,它有它的优点和缺点。请参阅“多解模式”在这篇文章中(忽略有关使用VSS部分:)


2

我认为,采用如此庞大的解决方案,最佳实践应该是将其分解。您可以将“解决方案”视为一个地方,它将必要的项目以及其他可能需要解决的问题汇总在一起。通过将100多个项目分解为多个解决方案,这些解决方案专门为整个问题的一部分开发解决方案,通过加快与所需项目的交互并简化问题领域,您可以在给定的时间更少地解决问题。

每个解决方案都会产生它负责的输出。此输出应具有可以在自动化过程中设置的版本信息。输出稳定后,您可以使用最新的内部发行版更新相关项目和解决方案中的引用。如果您仍然想进入代码并访问源代码,则实际上可以使用Microsoft符号服务器执行此操作,Visual Studio可以使用它来使您进入引用的程序集,甚至获取源代码。

通过预先指定接口并在等待不完整但希望针对其开发的依赖项时模拟正在开发的程序集,可以完成同时开发。

我发现这是一种最佳做法,因为以这种方式进行物理分解时,对整个工作量的复杂度没有限制。将所有项目放在一个解决方案中最终将达到上限。

希望这些信息对您有所帮助。


2

我们有大约60多个项目,并且不使用解决方案文件。我们混合了C#和VB.Net项目。性能始终是一个问题。我们不会同时处理所有项目。每个开发人员都根据他们正在从事的项目创建自己的解决方案文件。解决方案文件不会检入我们的源代码管理中。

所有类库项目都将构建到源目录根目录下的CommonBin文件夹中。可执行文件/ Web项目将构建到其各自的文件夹中。

我们不使用项目引用,而是使用CommonBin文件夹中基于文件的引用。我编写了一个自定义MSBuild任务,该任务将检查项目并确定构建顺序。

我们已经使用了几年了,没有任何投诉。


3
您介意共享自定义msbuild任务吗?
andreapier 2013年

0

所有这些都与您的定义有关,并了解什么是解决方案和项目。在我看来,解决方案就是解决特定需求的逻辑项目组合。我们开发了一个大型的Intranet应用程序。该Intranet中的每个应用程序都有其自己的解决方案,其中可能还包含exe或Windows服务项目。然后,我们有了一个集中式框架,其中包含基类,帮助程序和httphandlers / httpmodules之类的东西。基本框架很大,所有应用程序都使用它。通过以这种方式拆分许多解决方案,可以减少一个解决方案所需的项目数量,因为它们中的大多数彼此无关。

一个解决方案中包含许多项目只是糟糕的设计。一个解决方案下没有太多项目的理由。我看到的另一个问题是项目引用,它们确实可以使您最终陷入困境,尤其是如果您想将解决方案拆分为更小的解决方案时。

我的建议是这样做并开发一个集中式框架(如果需要,您可以自己实施企业库)。您可以GAC共享它,也可以直接引用文件位置,以便拥有一个中央存储。您也可以对集中式业务对象使用相同的策略。

如果要直接引用DLL,则需要在项目中使用复制本地false(例如c:\ mycompany \ bin \ mycompany.dll)进行引用。运行时,您需要向app.config或web.config中添加一些设置,以使其引用不在GAC或运行时bin中的文件。实际上,它是否是本地复制都无关紧要,或者dll是否终止在bin中,甚至不在GAC中都没有关系,因为配置将覆盖这两个变量。我认为复制本地文件和凌乱的系统是一种不好的做法。但是,如果您需要调试到这些程序集之一,则很可能必须临时复制本地。

您可以阅读有关如何在不使用GAC的情况下全局使用DLL的文章。我真的不喜欢GAC,主要是因为它阻止了xcopy部署并且不会触发应用程序的自动重启。

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.