15

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

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

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

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

1 - 嵌套文件夹:

A
--A.csproj --B ----ABcsproj
---- C ------ABCcsproj ------classC.cs ------D -------- ABCDcsproj --------classD.cs






或者

2 – 平面文件夹:

A
--A.csproj
AB
--ABcsproj
ABC
--ABCcsproj
--classC.cs
ABCD
--ABCDcsproj
--classD.cs

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

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

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

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

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

C
--bin --D --obj
--Properties --ABCcsproj --classC.cs



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

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

谢谢
迈克尔

4

8 回答 8

8

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

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

等等等等

编辑:删除废话

于 2008-12-31T10:01:16.730 回答
5

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

我就是这样做的:

- 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)

我希望这是有道理的!

于 2008-12-30T18:13:36.660 回答
4

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

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

于 2008-12-30T17:46:43.360 回答
3

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

于 2008-12-30T17:57:01.670 回答
2

如果您使用嵌套项目,则可能会遇到 Windows MaxPath问题。对于使用嵌套结构来说,这是一个巨大的交易破坏者。试想一下,在开发项目中途遇到这个小 Gem,必须用 3 个字母的首字母缩写词命名 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 集成和一个适当的离线故事)

于 2011-02-02T17:24:10.777 回答
0

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

于 2008-12-31T10:05:07.707 回答
0

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

  • 我的公司核心
  • 我的应用程序域
  • 我的应用程序数据
  • 我的应用程序界面
  • 我的应用程序测试

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

于 2013-10-04T22:45:18.647 回答
0

12 年过去了,这个问题有没有明确的或最佳实践的答案?

我想使用嵌套文件夹结构,但是鉴于您:

“同意命名空间应与文件夹结构匹配,并且每种语言工件都应位于其自己的文件中。”

如果从其他命名空间扩展代码,项目ABCcsproj文件夹结构将如何显示,例如:

  • 祖父母:A.csproj
  • 父母:ABcsproj
  • 孩子ABCDcsproj
  • 外部命名空间System.LinqMicrosoft.Extensions.Logging

也许是这样的:

/A                                  // namespace: A
  /B                                // namespace: A.B
    /C                              // namespace: A.B.C
      A.B.C.csproj 
      ClassC.cs                  
      /_                            // External Namespace root folder (underscore with no text)
        /System                     // namespace: System 
          /Linq                     // namespace: System.Linq
            IQueryableExtensions.cs 
        /Microsoft                  // namespace: Microsoft
          /Extensions               // namespace: Microsoft.Extensions
            /Logging                // namespace: Microsoft.Extensions.Logging
              ILoggerExtensions.cs                                  
      /__A                          // namespace: A (Grand Parent folder (2 underscores for 2 levels up)
        ClassAExtensions.cs
        /B                          // namespace: A.B (Nested Parent folder)
          ClassBExtensionsNested.cs
                                    //Parent Namespace folder (1 underscore for 1 level up)
      /_B                           // namespace: A.B
        ClassBExtensions.cs
      /D                            // namespace: A.B.C.D (Child folder)
        ClassDExtensions.cs

以上试图证明:

  • 带有单独下划线 (_) 且后面没有文本的文件夹将替换为空命名空间和所有外部命名空间的新根。
  • 在当前项目的树/层次结构中,带有下划线 (__A) 和 (_B) 后跟文本替换的文件夹作为上一级。每个下划线 1 级
于 2020-01-09T04:44:10.207 回答