不断增长的.NET项目的管理和结构

本文关键字:结构 管理 项目 NET 不断增长 | 更新日期: 2023-09-27 17:59:43

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

该应用程序由GUI(WinForms)组件和动态加载到其中以执行的各种"操作"组成。

大约有100个行动项目正在进行中,而且这个数字还在增加。其中一些项目与其他项目相互依赖,等等

加载的所有操作都必须引用我们的"SDK"dll进行各种活动(主应用程序的结果、日志记录等)。

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

  1. 操作("插件")应该引用我们的SDK项目输出,还是它的某个已知稳定版本?例如,当开发一个大型应用程序(MSOffice只是一个例子)时,并不是所有团队都能自然地使用所有组件的源代码

对于这样的问题,最好的解决方案是什么?为什么?

  1. 如何正确验证所有需要的依赖项(例如第三方库)是否确实取自正确的位置

在管理其间链接的大量项目的场景中,常见的做法是什么?有什么建议吗?

不断增长的.NET项目的管理和结构

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

你可以走两条路。强耦合系统或松耦合系统。

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

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

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

松耦合系统使用诸如MEF(托管可扩展性框架)之类的框架,并且您的组件引用"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接口的实用工具契约DLL。如何划分取决于你想做什么。或者每个接口都可能是一个契约DLL,但这可能有点极端。

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

这允许您构建具有大量链接项目的大型系统,但会带来许多复杂性问题。我认为,任何这样的解决方案都会。

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

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

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

第二:定义依赖项来自

答:它们来自你的ivy存储库(它可以像网络共享文件系统一样简单)。您已经创建了存储库,因此您可以控制其内容。对安装在GAC中的第三方二进制文件要格外小心。Visual Studio很难处理这个问题。

具体而言:

如何正确验证所有需要依赖项(的第三方库示例)确实取自正确的位置?

Ivy在依赖关系方面给了你很大的灵活性,它还解决了可传递的依赖关系;例如,您可以依赖SDK rev="1.+"status="latest.release",这意味着"SDK的最新稳定1.x版本",也可以依赖SDK rev="2.+"status="latest.integration",它意味着2.x SDK的最晚可用二进制文件(可能是从连续集成构建中生成的)。

因此,您将始终依赖于已编译的二进制文件,而不是项目输出。您可以控制要获取的二进制文件的版本。第三方依赖关系可能会在您的SDK中作为可传递性引入。

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

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