c#解决方案中的命名空间和文件夹结构:如何组织磁盘上的文件夹?

首先,让我们同意命名空间应该匹配文件夹结构,并且每个语言工件应该在它自己的文件中。

(请参阅解决方案中的文件夹是否应与命名空间匹配? )。

接下来的问题是如何在磁盘上实际组织文件夹。
假设我在ABC命名空间中有ClassC,在ABCD命名空间中有ClassD。
我们还假设每个命名空间都构建在它自己的程序集(项目)中,并且命名空间根据公认的最佳实践从右到左依赖(ABCD可以依赖于ABC,它可以依赖于AB,它可以依赖于A)。 我感谢每个命名空间不必在一个单独的程序集中,但在一般情况下,我们将在单独的程序集中有一些命名空间,我的示例说明了这一点。

我可以看到(至少)两种创建文件夹树的方法 – 我称之为“嵌套文件夹”和“平面文件夹”:

1 – 嵌套文件夹:

一个
–A.csproj
–B
—- ABcsproj
– – C
—— ABCcsproj
—— classC.cs
—— d
——– ABCDcsproj
——– classD.cs

要么

2 – 扁平文件夹:

一个
–A.csproj
AB
–ABcsproj
ABC
–ABCcsproj
–classC.cs
A B C D
–ABCDcsproj
–classD.cs

你会看到我已经做了一些假设:

  • 每个项目文件都具有基于命名空间的完全限定名称(FQN)。
  • 每个类文件都使用非FQN

嵌套文件夹似乎更自然(我们都喜欢层次结构),但在大型解决方案中导航可能有点困难:

当您在VS中查看解决方案时,它会显示项目的平面列表,而不是嵌套视图。 这看起来更像是“平面文件夹”,因此在磁盘上组织文件夹以匹配VS中的视图可能是有好处的。

如果查看磁盘上的每个文件夹,您将看到该项目的文件夹文件加上命名空间的子文件夹:以C为例:

C
–bin
–D
–obj
–properties
–ABCcsproj
–classC.cs

根据D的真实名称,D可能并不明显是命名空间文件夹而不是C命名空间中的组织文件夹。

我知道我们在.NET(8或9年前)和Java之前的第一天就有文件夹和命名空间,但是,就个人而言,我们似乎没有就大型的最佳实践项目组织达成共识解决方案。 我真的很想知道你们都在想什么。

谢谢
迈克尔

我使用扁平方法。 我发现嵌套的层次结构太难维护了。 我将我的项目分组到几个解决方案中,考虑到最大的可重用性和交叉引用,并且始终认为这是令人满意的。 示例(项目缩进):

CompanyName CompanyName.Core Class1 Struct2 Enum3 CompanyName.Data CompanyName.Web CompanyName.Projects CompanyName.Projects.Core CompanyName.Projects.ProjectX CompanyName.Projects.ProjectX.Core CompanyName.Projects.ProjectX.Website CompanyName.Projects.ProjectX.ToolY 

等等

编辑:删除废话备注

我不是嵌套项目的忠实粉丝,因为它将项目深埋在结构中,如果你需要在另一个应用程序中重用该项目,那么你做什么,复制/粘贴代码? 我喜欢遵循一些扁平结构,但是按命名空间组织。

我是这样做的:

 - DataHelpers\ ---Factory\ ---DataAccess\ ---... - Components\ --- EmailProcessor\ --- ErrorLogger\ - Desktop\ --- WindowsApp1\ - Services\ --- WindowsService1\ --- WindowsService2\ - WebApps\ --- WebApp1\ --- WebApp2\ 

现在,在我拥有的每个主要应用程序中,例如:

 - WindowsService1\ --- WindowsService1\ (this contains all *.cs, bin, obj, etc and .csproj file) --- Solution\ (this contains the .sln file where you link to other projects like ErrorLogger, etc) 

我希望这是有道理的!

“首先,我们同意命名空间应该匹配文件夹结构,并且每个语言工件[sic]应该在它自己的文件中。”

有趣,这就是Java在Java中的工作方式。 我一直认为打破名称空间和目录结构之间的联系被认为是C#引入的改进之一。 这不是真的吗? (原谅我的无知,我是一个Java人。)

我一直在做嵌套层次结构。 这使得将新项目添加到现有解决方案的位置变得非常明显,并使您的命名空间在磁盘上得到很好的组织。 它还使命名空间与项目的划分更加明显。

如果您使用嵌套项目,则存在遇到Windows MaxPath问题的风险。 这对于使用嵌套结构来说是一个巨大的破坏者。 想象一下,通过一个开发项目中途遇到这个小gem,不得不用三个字母的首字母缩写来命名VS项目,以免击中MaxPath。 MS错误最终成为程序集名称的灵感。 真是个笑话。 全面使用扁平结构更好。

  -SouceControlFolderName -Project1 -Src -Main -Company.Project1.AppName *Company.Project1.AppName.sln *Company.Project1.AppName.Tests.sln -Company.Project1.AppName.Common -Company.Project1.AppName.Common.Tests -Company.Project1.AppName.Entities -Company.Project1.AppName.Entities.Tests -Company.Project1.AppName.Security -Company.Project1.AppName.Security.Tests -etc. 

您可以为测试项目创建一个单独的目录,或者如上所述,将它们全部放在一起,在添加到源代码控制时更容易管理,即Subversion(TFS在很多方面更好,除了它需要Explorer集成而不仅仅是VS集成和适当的离线故事)

我认为你需要定义一个平面方法不再有效的截止点。 例如,如果您在一个小型项目中拥有典型的3层架构,那么在外层拥有3个项目就没有问题。 但是,如果您有几十个,那么某种分组有助于细分function并使整个解决方案更容易理解。

我更喜欢在根部有项目的扁平结构。

  • MyCorp.Core
  • MyApp.Domain
  • MyApp.Data
  • MyApp.UI
  • MyApp.Test

在这些内部我有各种文件夹和命名空间。 我只为可部署单元创建不同的程序集。 小应用程序甚至不会有这种分离。 IMO让事情变得简单。 如果我决定我需要在其他地方使用代码,只要我遵循良好的命名空间实践,只要需要就可以将其分解为程序集。