解决方案中的文件夹是否应与命名空间匹配?

122 .net c# namespaces

解决方案中的文件夹是否应与命名空间匹配?

在我的一个团队项目中,我们有一个类库,项目中有许多子文件夹.

项目名称和命名空间:MyCompany.Project.Section.

在此项目中,有几个与命名空间部分匹配的文件夹:

  • Folder VehiclesMyCompany.Project.Section.Vehicles命名空间中有类
  • Folder ClothingMyCompany.Project.Section.Clothing命名空间中有类
  • 等等

在同一个项目中,是另一个流氓文件夹

  • Folder BusinessObjectsMyCompany.Project.Section命名空间中有类

有一些这样的情况,其中文件夹是为了"组织方便"而制作的.

我的问题是:标准是什么?在类库中,文件夹通常与命名空间结构匹配,还是混合包?

ang*_*son 73

另请注意,如果使用内置模板将类添加到文件夹,则默认情况下将其放在反映文件夹层次结构的命名空间中.

这些课程将更容易找到,仅此一点应该是足够好的理由.

我们遵循的规则是:

  • 项目/程序集名称与根名称空间相同,但.dll结尾除外
  • 上述规则的唯一例外是具有.Core结尾的项目,.Core被剥离
  • 文件夹等于名称空间
  • 每个文件一个类型(类,结构,枚举,委托等)使得查找正确的文件变得容易

  • 我可能添加的另一个例外是异常.异常已经以"异常"为后缀,因此额外的命名空间是多余的.使用单词Exception(可能导致令人困惑的System.Exception)的部分命名空间也会变得混乱.但是,将它们组织到文件夹中非常有帮助. (2认同)

Wey*_*ani 47

没有.

我已经在小型和大型项目上尝试了这两种方法,包括单一(我)和一组开发人员.

我发现最简单和最有效的途径是每个项目都有一个命名空间,所有类都进入该命名空间.然后,您可以自由地将类文件放入所需的任何项目文件夹中.由于只有一个命名空间,因此始终在文件顶部添加使用语句并不会产生混乱.

将源文件组织到文件夹中很重要,我认为应该使用所有文件夹.要求这些文件夹也映射到命名空间是不必要的,创造了更多的工作,我发现实际上对组织有害,因为增加的负担会鼓励混乱.

以此FxCop警告为例:

CA1020:避免使用少数类型
的命名空间:全局命名空间以外的命名空间包含少于五种类型的 https://msdn.microsoft.com/en-gb/library/ms182130.aspx

此警告鼓励将新文件转储到通用Project.General文件夹,甚至是项目根目录,直到您有四个类似的类来证明创建新文件夹.这会发生吗?

查找文件

接受的答案是"这些课程将更容易找到,而且这一点应该足够好."

我怀疑答案是指在项目中有多个名称空间没有映射到文件夹结构,而不是我建议哪个是具有单个名称空间的项目.

在任何情况下,当您无法从命名空间确定类文件所在的文件夹时,可以使用"转到定义"或Visual Studio中的"搜索解决方案资源管理器"框找到它.在我看来,这也不是一个大问题.我不会花费0.1%的开发时间来查找文件以证明优化它的合理性.

姓名冲突

当然,创建多个名称空间允许项目具有两个具有相同名称的类.但这真的是件好事吗?是否可能更容易禁止这种可能性?允许两个具有相同名称的类会创建一个更复杂的情况,其中90%的时间事情以某种方式工作,然后突然您发现您有一个特殊情况.假设您在不同的命名空间中定义了两个Rectangle类:

  • class Project1.Image.Rectangle
  • class Project1.Window.Rectangle

可能会遇到源文件需要包含两个名称空间的问题.现在你必须在该文件中的任何地方写出完整的命名空间:

var rectangle = new Project1.Window.Rectangle();
Run Code Online (Sandbox Code Playgroud)

或者用一些讨厌的使用声明搞乱:

using Rectangle = Project1.Window.Rectangle;
Run Code Online (Sandbox Code Playgroud)

在项目中使用单个命名空间时,您不得不提出不同的命名空间,我认为这些名称更具描述性:

  • class Project1.ImageRectangle
  • class Project1.WindowRectangle

并且使用情况在任何地方都是相同的,当文件使用两种类型时,您不必处理特殊情况.

使用陈述

using Project1.General;  
using Project1.Image;  
using Project1.Window;  
using Project1.Window.Controls;  
using Project1.Shapes;  
using Project1.Input;  
using Project1.Data;  
Run Code Online (Sandbox Code Playgroud)

VS

using Project1;
Run Code Online (Sandbox Code Playgroud)

在编写代码时不必一直添加命名空间.这不是真正的时间,它是必须这样做的流程中断,只是用大量的使用语句来填充文件 - 为了什么?这值得么?

更改项目文件夹结构

如果文件夹映射到名称空间,则项目文件夹路径实际上硬编码到每个源文件中.这意味着项目中任何文件或文件夹的重命名或移动都需要更改实际文件内容.该文件夹中文件的名称空间声明以及在引用该文件夹中的类的一大堆其他文件中使用语句.虽然这些更改本身对于工具来说是微不足道的,但它通常会导致一个由许多文件组成的大型提交,这些文件的类甚至没有更改.

使用项目中的单个命名空间,您可以更改项目文件夹结构,但不需要修改任何源文件.

Visual Studio会自动将新文件的命名空间映射到其创建的项目文件夹

不幸的是,我发现纠正命名空间的麻烦不及处理它们的麻烦.此外,我养成了复制粘贴现有文件而不是使用Add-> New的习惯.

智能感知和对象浏览器

我认为在大型项目中使用多个名称空间的最大好处是在查看名称空间层次结构中的类的任何工具中查看类时具有额外的组织.甚至文件.显然,在项目中只有一个命名空间会导致所有类显示在单个列表中而不是分成类别.不过个人而言,由于缺乏这一点,我从来没有被困难或延迟,因此我认为没有足够的好处来证明多个命名空间的合理性.

虽然如果我正在编写一个大型公共类库,那么我可能会在项目中使用多个名称空间,以便程序集在工具和文档中看起来很整洁.

  • 老实说,这是我听过的最噩梦解决方案之一.如果你在小型hello world项目上工作,那么这个建议是有效的,但想象你有1000+ .cs文件.它会导致很多问题,我不知道从哪里开始. (22认同)
  • +1思考.我不认为我已经准备好将每个项目的命名空间减少到一个但是在处理大型框架之后我正在探索减少命名空间的数量以减少使用语句的数量并帮助扩展方法的可发现性.我认为这个答案给了一些好的思考.谢谢. (12认同)
  • "但想象你有1000多个.cs文件".我使用单个命名空间在那个大小的项目中工作过.没关系.你认为会发生什么灾难? (10认同)
  • 这是我见过的最好的建议之一.命名空间仅用于解决冲突,不用于组织类.仅在有意义的情况下使用名称空间,例如您希望与可能正在使用项目的其他项目发生命名冲突的位置,允许使用using语句包含或排除某些名称空间.有一个项目有3个或4个或更多经常使用的命名空间是很糟糕的,因为它总是导致需要添加和添加添加和添加的使用语句的数量太多.打破你的项目. (9认同)
  • @WeylandYutani我知道我迟到但我需要提一下这句话:"你可以通过使用Go To Definition或Visual Studio中的搜索解决方案资源管理器框找到它并不总是正确的.尝试一下很多继承和接口......祝你找到合适的文件. (3认同)
  • 相关:https://medium.com/@steve_verm/matching-namespaces-to-folders-is-an-anti-pattern-e8edb3a6b8e5 (3认同)
  • 这太可怕了。请考虑您的依赖管理重新考虑此决定。让文件夹和命名空间代表您的架构。使用它们来代表您的关注点分离。优先选择垂直分离而不是水平分离。 (3认同)
  • 我同意@BentOnCoding.你的帖子还有另外一点建议输入名称空间通常需要在不同名称空间中具有相同名称的类的详细程度,但是C#可以优雅地使用`using Foo as Bar`指令 (2认同)
  • 我提到过,我不认为它优雅,我认为这是一个黑客 (2认同)

Kar*_*uin 31

我认为.NET中的标准是尽可能地尝试这样做,但不要创建不必要的深层结构只是为了坚持它作为一个硬性规则.我的项目都没有100%的时间遵循命名空间==结构规则,有时它只是更清洁/更好地突破这些规则.

在Java中,您没有选择余地.我称之为理论与实践中有效的经典案例.

  • 我会说“当你真的希望某些东西位于它自己的命名空间中时就这样做”。这应该是一个有意识的决定。如果您的项目被正确隔离,则每个项目应该有一个命名空间。如果您的类位于命名空间中,则它应该位于具有该命名空间的文件夹中或*至少与命名空间一样具体*的子文件夹位置中。像 Car.Ford.Fusion 这样的类(如果 Car.Ford 是您唯一的命名空间)应该位于像 Car/Ford 这样的文件夹中,或者像 Car/Ford/Sedans 这样更深的文件夹中,这样该文件夹*至少*与命名空间一样具体。只是不要把它放在汽车/无关/福特中;这很令人困惑。 (2认同)

Jay*_*uzi 23

@lassevk:我同意这些规则,还有一个要添加.

当我有嵌套类时,我仍然将它们分开,每个文件一个.像这样:

// ----- Foo.cs
partial class Foo
{
    // Foo implementation here
}
Run Code Online (Sandbox Code Playgroud)

// ----- Foo.Bar.cs
partial class Foo
{
    class Bar
    {
        // Foo.Bar implementation here
    }
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*Dan 5

是的,他们应该这样做,否则只会导致混乱。

  • 有任何证据或参考资料来支持这一点吗? (2认同)

Ish*_*eel 5

我会说是的。

首先,通过遵循名称空间(例如,当有人通过电子邮件向您发送裸异常调用堆栈时)来查找实际的代码文件会更容易。如果让文件夹与名称空间不同步,那么在大型代码库中查找文件将变得很累人。

其次,VS将在与父文件夹结构相同的名称空间的文件夹中生成您创建的新类。如果您决定不这样做,那么添加新文件时,每天要做的只是一项繁琐的工作。

当然,这毋庸置疑,对于xis文件夹/命名空间层次结构的深入程度应该保持保守。