代码之家  ›  专栏  ›  技术社区  ›  Benjol

用c语言构造大型winforms应用程序的项目和依赖关系#

  •  24
  • Benjol  · 技术社区  · 16 年前

    更新:
    这是我访问最多的问题之一,但我仍然没有找到一个满意的解决方案,我的项目。我在回答另一个问题时读到的一个想法是创建一个工具,它可以为您从列表中挑选出的项目“即时解决方案”。不过,我还没有试过。


    如何构造一个非常大的应用程序?

    • 一个大解决方案中有多个小型项目/程序集?
    • 几个大项目?
    • 每个项目一个解决方案?

    以及在没有解决方案的情况下如何管理依赖关系。 注:我正在寻找基于经验的建议,而不是谷歌上找到的答案(我自己也可以这样做)。

    我目前正在开发一个应用程序,它有超过80个dll,每个dll都有自己的解决方案。管理依赖关系几乎是一项全职工作。有一个自定义的内部“源代码管理”,添加了在所有地方复制依赖性dll的功能。对我来说似乎是次优解,但有更好的方法吗?我担心,用80个项目来制定一个解决方案在实践中会相当困难。

    (上下文:winforms,而不是web)

    编辑: (如果你认为这是另一个问题,请给我留言)

    在我看来:

    • 应用程序的项目/解决方案结构
    • 文件夹/文件结构
    • 源代码管理的分支结构(如果使用分支)

    但如果可能的话,我很难把它们分开单独考虑。

    我又问了一个相关的问题 here .

    9 回复  |  直到 12 年前
        1
  •  5
  •   Ewan Makepeace    16 年前

    源代码管理

    我们有20或30个项目被构建成4或5个离散的解决方案。我们正在使用subversion for scm。

    1)SVN中有一棵树,包含按名称空间和项目名称逻辑组织的所有项目。在根目录下有一个.sln来构建它们,但这不是必需的。

    2)对于每个实际的解决方案,我们在svn中都有一个新的trunks文件夹,其中包含svn:对所有必需项目的外部引用,以便它们从主树下的位置进行更新。

    3)在每个解决方案中都是.sln文件加上一些其他必需的文件,再加上该解决方案唯一的、不在解决方案之间共享的任何代码。

    有许多较小的项目有时会有点麻烦(例如,tortoisesvn update消息会被所有这些外部链接弄得一团糟),但它有一个巨大的优势,即依赖性是不允许循环的,因此,我们的ui项目依赖于bo项目,但是bo项目不能引用ui(它们也不应该!).

    建筑 我们完全改用 MS SCSF and CAB enterprise 模式来管理各种项目在Win窗体界面中的组合和交互方式。我不确定您是否有相同的问题(多个模块需要在公共表单环境中共享空间),但如果您有,那么这可能会给您如何设计和组装解决方案带来一些理智和约定。

    我提到这一点是因为scsf倾向于将bo和ui类型的函数合并到同一个模块中,而之前我们保持了严格的3级策略:

    fw-框架代码。其功能与软件相关的代码。 业务对象。其功能与问题域相关的代码。 ui-与ui相关的代码。

    在这种情况下,依赖关系是严格的ui->bo->fw

    我们发现,即使使用SCSF生成的模块,我们也可以保持这个结构,因此在世界上都是好的:

        2
  •  2
  •   Patrick from NDepend team    16 年前

    要管理依赖项,无论您拥有多少程序集/命名空间/项目,都可以查看该工具 NDepend .

    个人而言,如果需要的话,我会在一个或多个解决方案中培养一些大型项目。我在这里写下了我这样做的动机: Benefit from the C# and VB.NET compilers perf

        3
  •  1
  •   Martin    16 年前

    我认为有一个包含所有80个项目的解决方案是非常重要的,即使大多数开发人员大部分时间都使用其他解决方案。根据我的经验,我倾向于使用一个大型解决方案,但是为了避免每次单击f5时重建所有项目的痛苦,我转到解决方案资源管理器,右键单击我现在不感兴趣的项目,然后执行“卸载项目”。这样的话,这个项目就可以解决了,但不需要我付出任何代价。

    尽管如此,80是一个很大的数字。根据这80个分解成dicrete子系统的程度,我还可以创建其他解决方案文件,每个文件都包含一个有意义的子集。这样可以省去很多右击/卸载操作。尽管如此,事实上你会有一个大的解决方案,这意味着他们之间的相互依赖总是有一个明确的观点。

    在我使用过的所有源代码管理系统中,它们的vs集成选择将.sln文件放在源代码管理中,并且许多系统不能正常工作 除非 该.sln文件在源代码管理中。我觉得这很有趣,因为.sln文件过去被认为是个人的事情,而不是整个项目的事情。我认为唯一一种真正值得源代码管理的.sln文件是包含所有项目的“一个大解决方案”。例如,您可以使用它来进行自动生成。正如我所说,个人可能为了方便而创建自己的解决方案,我并不反对那些进入源代码管理的人,但他们对个人的意义比对项目的意义更大。

        4
  •  1
  •   Warrior    16 年前

    我认为最好的解决方案是把它分解成更小的解决方案。在我目前工作的公司,我们有同样的问题;80个项目+在解决方案。我们所做的,就是把项目分成几个更小的解决方案。来自其他项目的依赖dll将被生成并链接到项目,并与项目一起检入到源代码管理系统。它使用更多的磁盘空间,但磁盘很便宜。这样做,我们可以继续使用版本1的项目,直到升级到版本1.5是绝对必要的。不过,在决定升级到其他版本的dll时,您仍然需要添加dll。有一个关于谷歌代码的项目叫做 TreeFrog 这说明了如何构造解决方案和开发树。它不包含MISH文档,但我想你可以通过看结构来了解如何去做。

        5
  •  1
  •   Bravax    16 年前

    我已经看到的一个方法是有一个包含所有项目的大的解决方案,允许一个项目范围的构建被测试(没有人真的用它来构建,尽管它太大了)。然后有更小的项目供开发人员使用,这些项目将各种相关的项目组合在一起。

    它们确实依赖于其他项目,但是,除非接口发生更改,或者需要更新它们正在使用的dll的版本,否则它们可以继续使用较小的项目,而不必担心其他任何事情。 因此,他们可以在处理项目时签入项目,然后在其他用户应该开始使用它们时(在更改版本号之后)锁定它们。

    最后,一周或两次,甚至更频繁地,整个解决方案仅使用PIN代码进行重建,从而检查集成是否正常工作,并赋予测试人员良好的测试能力。

    我们经常发现大量的代码段并没有频繁地更改,所以一直加载它是没有意义的。(当你在做一些小项目的时候。)

    使用这种方法的另一个优点是,在某些情况下,我们有一些功能需要几个月才能完成,通过使用上述方法意味着这可以在不中断其他工作流的情况下继续。

    我想一个关键的标准是在你的解决方案中没有太多的交叉依赖关系,如果你这样做了,这种方法可能不合适,但是如果依赖关系更加有限,那么这可能是一条路要走。

        6
  •  1
  •   forgot my open id login    15 年前

    对于我研究过的两个系统,我们对不同的组件有不同的解决方案。每个解决方案都有一个通用的输出文件夹(包含调试和发布子文件夹)

    我们在解决方案中使用项目引用,在它们之间使用文件引用。每个项目都使用引用路径从其他解决方案定位程序集。我们不得不手动编辑.csproj.user文件,以便在vs坚持验证路径时向引用路径添加$(configuration)msbuild变量。

    对于vs之外的构建,我编写了msbuild脚本,这些脚本递归地标识项目依赖项,从subversion获取并构建它们。

        7
  •  1
  •   Mafu Josh    12 年前

    我放弃了项目引用(尽管你的宏听起来很棒),原因如下:

    • 在不同的解决方案之间切换并不容易,有时依赖项目存在,有时不存在。
    • 需要能够自己打开项目并构建它,并独立于其他项目部署它。如果使用项目引用构建,这有时会导致部署问题,因为项目引用导致它查找特定版本或更高版本,或类似的内容。它限制了交换不同版本依赖项的混合和匹配能力。
    • 另外,我有指向不同.NET框架版本的项目,因此一个真正的项目引用并不总是发生。

    (仅供参考,我所做的一切都是为vb.net做的,所以不确定c的行为是否有细微的差异)

    所以,我:

    • 我根据在解决方案中打开的任何项目进行构建,而那些没有打开的项目则来自全局文件夹,如c:\ globalassembly
    • 我的持续集成服务器在网络共享上保持此更新,并且我有一个批处理文件将任何新的内容同步到本地文件夹。
    • 我有另一个本地文件夹,如c:\ globalassembliesdebug,其中每个项目都有一个后期生成步骤,该步骤只在处于调试模式时将bin文件夹的内容复制到此调试文件夹。
    • 每个项目都将这两个全局文件夹添加到其引用路径中。(首先是C:\ globalassembliesdebug,然后是C:\ globalassemblies)。我必须手动将此引用路径添加到.vbproj文件,因为visual studio的ui将它们添加到.vbprojuser文件。
    • 我有一个预构建步骤,如果在发布模式下,它将从c:\ globalassembliesdebug中删除内容。
    • 在作为宿主项目的任何项目中,如果有需要复制的非dll(输出到其他项目的bin文件夹的文本文件是我需要的),则我在该项目上放置一个预构建步骤,以将它们复制到宿主项目中。
    • 我必须在解决方案属性中手动指定项目依赖项,以使它们以正确的顺序生成。

    所以,它的作用是:

    • 允许我在任何解决方案中使用项目,而不干扰项目引用。
    • visual studio仍然允许我进入解决方案中打开的依赖项项目。
    • 在调试模式下,它根据打开的加载项目生成。所以,它首先查找c:\ globalassembliesdebug,如果没有,则查找c:\ globalassemblies
    • 在发布模式下,由于它删除了c:\ globalassembliesdebug中的所有内容,所以它只查看c:\ globalassemblies。我之所以要这样做,是因为发布的版本不是针对我的解决方案中临时更改的任何东西构建的。
    • 加载和卸载项目很容易,无需太多努力。

    当然,这并不完美。调试经验不如项目参考。(不能做“去定义”,让它正常工作)和其他一些古怪的事情。

    不管怎样,这就是我努力让事情对我们最好的地方。

        8
  •  0
  •   Nenad Dobrilovic    16 年前

    我们有一个关于源代码管理的巨大解决方案,在主分支上。

    但是,每个开发人员/团队都有自己的分支,其中包含一个解决方案,只需要很少的项目。这样,该解决方案足够小,易于维护,并且不会影响较大解决方案中的其他项目/dll。

    然而,这有一个条件:解决方案中不应该有太多相互关联的项目。

        9
  •  0
  •   Community George Stocker    7 年前

    好的,在消化了这些信息之后,还回答了 this question 关于项目引用,我目前正在使用此配置,它似乎“对我有效”:

    • 一个大的解决方案,包含应用程序项目和所有依赖程序集项目
    • 我保留了所有的项目引用,并对一些动态实例化的程序集的手动依赖项(右键单击项目)进行了一些额外的调整。
    • 我有三个解决方案文件夹(工作的、同步的和外部的)-考虑到我的源代码管理没有与vs集成( 呜咽 ,这允许我在工作和同步之间快速拖放项目,这样我就不会丢失更改。外部文件夹用于属于同事的程序集。
    • 我为自己创建了一个“workingsetonly”配置(debug/release下拉列表中的最后一个选项),它允许我限制在f5/f6上重建的项目。
    • 就磁盘而言,我将所有项目文件夹都放在几个文件夹中的一个文件夹中(因此,仅对项目进行一级分类)
    • 所有项目生成(dll、pdb& xml )到相同的输出文件夹,并具有与引用路径相同的文件夹。(所有引用都设置为不复制)-这让我可以选择从解决方案中删除项目,并轻松切换到文件引用(我有一个宏用于此操作)。
    • 在与“项目”文件夹相同的级别上,我有一个“解决方案”文件夹,在该文件夹中,我为某些程序集维护单独的解决方案,以及特定于程序集的测试代码(例如)和文档/设计等。

    目前看来,这种配置对我来说工作正常,但大测试将试图把它卖给我的同事,并看看它是否会作为一个团队设置飞行。

    目前尚未解决的缺点:

    • 我仍然对单个程序集解决方案有问题,因为我并不总是希望包含所有依赖的项目。这会与“主”解决方案产生冲突。我用一个宏(再次)解决了这个问题,该宏将断开的项目引用转换为文件引用,如果项目被添加回来,则将文件引用还原为项目引用。
    • 不幸的是,没有办法(到目前为止我已经发现)将构建配置链接到解决方案文件夹-可以说“在这个文件夹中构建所有内容”会很有用-就目前的情况而言,我必须手动更新(痛苦的,很容易忘记)。(可以右键单击要创建的解决方案文件夹,但不处理F5方案)
    • 解决方案文件夹实现中存在一个(小)错误,这意味着重新打开解决方案时,项目将按其添加顺序显示,而不是按字母顺序显示。(我打开了一个 bug with MS ,显然现在已经纠正了,但我猜是VS2010)
    • 我不得不卸载 CodeRushXPress 添加,因为它在所有代码上都被阻塞了,但是这是在修改了构建配置之前,所以我将再尝试一次。

    总结-在提出这个问题之前我不知道的事情,这些事情证明是有用的:

    1. 使用 solution folders 组织解决方案而不干扰磁盘
    2. 创建生成配置以排除某些项目
    3. 能够手动定义项目之间的依赖关系,即使它们使用的是文件引用

    这是我最喜欢的问题,所以我希望这个答案能帮助读者。我仍然对其他用户的进一步反馈很感兴趣。