不断发展的.NET项目的管理和结构

时间:2011-06-21 17:13:35

标签: c# structure

我们正在为我们公司内部使用的测试自动化构建一个.NET软件平台。

应用程序由GUI(WinForms)组件和动态加载到其中的各种“动作”组成。

大约有大约100个行动项目已经开始,这个数字正在增加。 其中一些项目与其他项目相互依赖等等。

加载的所有操作必须引用我们的“SDK”dll用于各种活动(结果到主应用程序,记录等)。

通过这种相对简单的设计,我们面临着一些我们希望以最佳方式解决的管理决策:

  1. 动作(“插件”)应该引用我们的SDK项目输出,还是某些已知的稳定版本? 例如,在开发大型应用程序(仅用于示例的MS Office)时,并非所有团队都自然地使用所有组件的源代码。
  2. 对于这样的事情,最好的解决方案是什么?为什么?

    1. 如何正确验证所有需要的依赖项(例如第三方库)确实是从正确的位置获取的?
    2. 在管理众多项目之间的场景中,常见做法是什么?这样做有什么提示吗?

2 个答案:

答案 0 :(得分:2)

这是一个没有明确答案的问题,但是......

您可以采取两种方式。强耦合系统或松耦合系统。

对于强耦合系统,我可以为二进制文件建议两个目录:第三方目录和一个包含公司构建的DLL的目录,其他开发人员可以引用这些目录。第三方DLL(公司外部)应位于源代码管理中,以便所有开发人员从同一位置引用相同版本的第三方DLL,从而避免开发人员机器不一致,并且遇到在每台计算机上安装第三方软件的问题。内部DLL不应该在源代码控制中引用,并且应该通过自动构建批处理文件或类似方式在每个开发人员机器上构建。在构建后期步骤中,您可以将它们全部复制到同一目录中,只要开发人员获得最新的源代码控制和构建,每个人都有来自公司内部的相同DLL。

例如,获取最新版本,构建(使用批处理文件构建所需的所有项目),然后作为后期构建步骤将输出复制到common。现在,您的所有其他项目都可以从同一位置引用常见的compnay DLL和第三方DLL,并且每个人都是一致的。

问题在于引用是强耦合的,因此如果不能正确地进行通信,更改有时会出现问题。

松散耦合的系统使用MEF(Managed Extensibility Framework)等框架,您的组件引用“Contract DLL”,它们定义了组件的接口。该项目引用接口或合同DLL,并不真正关心实现,然后MEF为您管理插件。

在这种情况下,您引用接口DLL但不引用实现的实际DLL。

例如,假设我有一个名为ILog的接口,其接口名为LogMessage。

private ILog _logger;
_logger.LogMessage();

因此,在一个强耦合的情况下:Action.DLL直接引用Logger.DLL。

在松散耦合的情况下,Action.DLL引用ILog.DLL(只是接口)。 Logger.DLL实现了ILog.DLL。但Action.DLL没有直接引用Logger.DLL。

现在我可以有任意数量的DLL来实现ILog接口,但是Action.DLL并没有直接引用它们。这非常酷,而且MEF的一个更令人激动的功能和松散的耦合,一般来说,没有依赖的能力。

你选择如何去,无论哪种方式都可以接受,我认为松散耦合的想法最适合你的场景,因为团队只需知道合同与实际的实施。

我不会有一个庞大的合同DLL,我会尝试将接口分解为逻辑分组。例如,日志记录看起来像是一种实用程序类型的接口,因此我将使用ILog接口创建一个Utility合约DLL。如何拆分取决于你想要做什么。或者每个接口可能是一个合约DLL,但也许这有点极端。

答案 1 :(得分:1)

这是一个有点复杂的话题,特别是在.NET领域。我不知道“最佳”解决方案,但我会解释我们如何管理它;也许你会对自己有用。

这允许您构建包含大量链接项目的大型系统,但会引发许多复杂性问题。我认为,任何此类解决方案都可以。

第一:物理结构(我们使用SVN)。

  • 每个项目都有一个源代码管理根
  • 每个项目都有自己的主干,分支和标签
  • trunk文件夹有一个版本化的\ src和\ build文件夹,以及一个unversioned \ lib文件夹 \ lib文件夹包含要引用的二进制文件。 这些二进制文件可能是第三方库或您需要链接到的其他项目(例如,您的SDK)。 \ lib下的所有二进制文件都来自企业ivy存储库(请参阅http://ant.apache.org/ivy/)。这些天在.NET领域有很多关于NuGet的运动,所以你也可以检查一下。

您的版本化\ build文件夹包含构建脚本,例如从ivy获取二进制文件,将项目发布到ivy或编译每个项目。当您想在每个项目中指向持续集成服务器时,它们也会派上用场。

第二:定义依赖关系的来源

答案:它们来自您的常春藤存储库(它可能像网络共享文件系统一样简单)。 您已创建存储库,因此您可以控制其内容。 对安装在GAC中的第三方二进制文件要非常小心。 Visual Studio是一个痛苦的^^来处理这个问题。

具体来说:

  

如何正确验证所有需要的内容   依赖关系(第三方库)   确实是从中获取的   正确的位置?

Ivy为依赖项提供了极大的灵活性,它还解决了传递依赖性问题;例如,你可以依赖SDK rev =“1。+”status =“latest.release”这意味着“SDK的最新稳定1.x版本,或SDK rev =”2。+“status =”latest。 “这将意味着2.x SDK的最新可用二进制文件(可能是由持续集成构建产生的)。

因此,您将始终依赖于已编译的二进制文件,而不是项目输出。并且您可以控制要获取哪个版本的二进制文件。第三方依赖项可能会在SDK上传递。

这也意味着项目中的代码量将保持在您需要的可用Visual Studio解决方案所需的数量。这也意味着像ReSharper这样的重构工具将不那么有用。您的构建脚本和分支策略也会有一定的复杂性。这在很大程度上取决于组件的逻辑。

这是一个简短的概述,如果你认为这是你想要的东西我可以扩展答案。祝好运; .NET生态系统,尤其是Visual Studio,实际上并不像这样工作。