在 C# 中防止 helper 类 命名污染的推荐方法?
Recommended way to prevent naming pollution by helper classes in C#?
我经常遇到这样的模式,即我有一个主 class 和几个较小的助手 class es 或结构。
我希望这些结构的名称尽可能简洁。因此,当我有一个名为 CarFinder
的 class 大量使用一些仅(或主要)在内部使用的特殊密钥 object 时,我想称其为 object Key
而不是 CarFinderKey
。
一切都删除了所有额外的 fuzz,当我在阅读它时试图理解 class 时会分散我的注意力。
当然,我不想用一个名为 Key
的小帮手 class 污染其余代码 - 它很可能会发生冲突和混淆。
在一个完美的世界中,我希望有一个像 internal to this namespace
这样的关键字,但由于它不存在,所以我可以想到以下选项:
- 使用
internal
并将 class 放在不同的项目中。
优点:完美封装
缺点:大量的组织开销和不必要的复杂依赖关系。
注意:我说的不是真正的大型独立系统,它们无疑值得自己组装。
- 将其放在不同的 child 命名空间中,例如
CarFinding.Internal
优点:易于实现
缺点:不小心导入命名空间时仍然会造成污染
- 将助手 class 作为 child class 放入
CarFinder
.
优势 内部不污染,甚至可以提升为public helper struct,暴露于外界CarFinder.Key
缺点 必须将助手 class 放在同一个文件中,或者将其封装在外部文件中并用 public partial class
围绕它。第一个使文件变得不必要的长,第二个感觉真的很丑。
- 随便叫吧
CarFinderKey
优点易于实施。
缺点 在我看来增加了太多 fuzz 到 CarFinder
。仍然不必要污染命名,只是用一个不太可能冲突的名字。
推荐的指南是什么?
我会把 class 和它们的 "helpers" 放在它们自己的命名空间中 MyNamespace.CarFinding,
所以你有:
MyNamespace.CarFinding.CarFinder
MyNamespace.CarFinding.Key
我会把这个命名空间放在项目的子文件夹中。
这不会阻止内部助手 class 在项目的其他地方使用,但您可以从父名称空间引用您的助手 CarFinding.Key
就个人而言,我不介意 CarFinderKey 造成的额外 "fuzz",原因如下:曾经在一个非常大的项目上工作,我们试图使用名称空间来消除名称歧义。
因此,当您扩展系统时,您很容易在代码编辑器中打开 10 个选项卡,所有选项卡都命名为 "Key.cs"。那真的不好玩。
这是基于意见的。无论如何,我会:
尝试使其成为 CarFinder
的私有嵌套 class,这通常会失败,因为 Key
需要传递给 CarManager
, 你知道我的意思。 Public 不鼓励嵌套 class。
我会将其放入名为 Core
的子命名空间中,这是内部内容的通用名称。对我来说,Core
按照命名约定是 "namespace internal"。
项目越大,名称越长。 CarFinderKey
仍然是一个有效的选项。
我永远不会为此创建额外的程序集。就是感觉不对。
我多次遇到同样的困境,个人使用(3)和(4)的变体。
(3):我既不将嵌套的 class/struct 放在同一个文件中(如果它很小并且确实与父 class 相关),也不使用单独的文件在 partial ParentClass
声明中——唯一的缺点是它多了一层缩进,但我可以接受。我对违反 FxCop 规则或其他建议也没有问题——毕竟,它们只是建议,而不是强制性的。但是很多人确实对所有这些或其中的一些有问题,所以让我们继续吧。
(4):您已经描述了缺点。我要分享的是我是如何克服它们的。同样,它是个人的,可能喜欢也可能不喜欢,但就是这样。
首先,假设我们为密钥 class 使用一个单独的文件,并将 class 命名为 CarFinderKey
。
然后,在 CarFinder
class 的代码文件中,我们将以下行放在 的末尾(或内部的任何位置)using
部分:
using Key = CarFinderKey;
这样,只在CarFinder
class代码文件里面,任何需要CarFinderKey
的地方,我们可以简单的引用一下作为 Key
,目标是什么。同时我们保留了所有的优势,没有冲突。智能工作 w/o 任何问题。在 VS2015 中,灯泡甚至会在文件中找到 CarFinderKey
的任何地方为您建议 "simplify the name"。
您的决定应取决于您的设计。你的钥匙 class 真的只是 CarFinder 的钥匙,还是也可以用来找摩托车或房子什么的。
著名的四人帮制定的第一个规则是 "Design for change"。如果你真的认为在不久的将来你的钥匙也可以用来找房子或摩托车,那么把你的钥匙 class 设为私有以致其他人无法使用它并不是一个好主意。
既然你说的是私人助手 classes,我想你的钥匙只对 CarFinders 有用。
如果是这种情况,并且您的设计规定密钥仅对 CarFinders 有用,或者甚至:如果它的设计甚至在 CarFinders 之外也没有用,那么密钥 class 应该成为 CarFinders class 的一部分。将此与您将在 CarFinders class 中使用的简单整数进行比较,您会在 CarFinders class 中将其声明为私有,不是吗?
给您留下一个大文件或部分定义的问题。从设计的角度来看没有区别。对于编译器也没有区别。唯一的区别在于必须阅读它的人。如果您认为 class 的用户很少需要阅读您的密钥 class 的定义,那么最好将其定义在一个单独的文件中。但是,如果您在阅读 CarFinder class 时经常需要阅读密钥 class,您应该尽可能轻松地访问密钥 class。如果您的开发环境是完全面向文件而不是面向 class,那么我认为在那种情况下,大文件的缺点小于必须在文件之间切换的缺点。
我经常遇到这样的模式,即我有一个主 class 和几个较小的助手 class es 或结构。
我希望这些结构的名称尽可能简洁。因此,当我有一个名为 CarFinder
的 class 大量使用一些仅(或主要)在内部使用的特殊密钥 object 时,我想称其为 object Key
而不是 CarFinderKey
。
一切都删除了所有额外的 fuzz,当我在阅读它时试图理解 class 时会分散我的注意力。
当然,我不想用一个名为 Key
的小帮手 class 污染其余代码 - 它很可能会发生冲突和混淆。
在一个完美的世界中,我希望有一个像 internal to this namespace
这样的关键字,但由于它不存在,所以我可以想到以下选项:
- 使用
internal
并将 class 放在不同的项目中。
优点:完美封装
缺点:大量的组织开销和不必要的复杂依赖关系。
注意:我说的不是真正的大型独立系统,它们无疑值得自己组装。
- 将其放在不同的 child 命名空间中,例如
CarFinding.Internal
优点:易于实现
缺点:不小心导入命名空间时仍然会造成污染
- 将助手 class 作为 child class 放入
CarFinder
.
优势 内部不污染,甚至可以提升为public helper struct,暴露于外界CarFinder.Key
缺点 必须将助手 class 放在同一个文件中,或者将其封装在外部文件中并用 public partial class
围绕它。第一个使文件变得不必要的长,第二个感觉真的很丑。
- 随便叫吧
CarFinderKey
优点易于实施。
缺点 在我看来增加了太多 fuzz 到 CarFinder
。仍然不必要污染命名,只是用一个不太可能冲突的名字。
推荐的指南是什么?
我会把 class 和它们的 "helpers" 放在它们自己的命名空间中 MyNamespace.CarFinding,
所以你有:
MyNamespace.CarFinding.CarFinder
MyNamespace.CarFinding.Key
我会把这个命名空间放在项目的子文件夹中。
这不会阻止内部助手 class 在项目的其他地方使用,但您可以从父名称空间引用您的助手 CarFinding.Key
就个人而言,我不介意 CarFinderKey 造成的额外 "fuzz",原因如下:曾经在一个非常大的项目上工作,我们试图使用名称空间来消除名称歧义。
因此,当您扩展系统时,您很容易在代码编辑器中打开 10 个选项卡,所有选项卡都命名为 "Key.cs"。那真的不好玩。
这是基于意见的。无论如何,我会:
尝试使其成为
CarFinder
的私有嵌套 class,这通常会失败,因为Key
需要传递给CarManager
, 你知道我的意思。 Public 不鼓励嵌套 class。我会将其放入名为
Core
的子命名空间中,这是内部内容的通用名称。对我来说,Core
按照命名约定是 "namespace internal"。项目越大,名称越长。
CarFinderKey
仍然是一个有效的选项。
我永远不会为此创建额外的程序集。就是感觉不对。
我多次遇到同样的困境,个人使用(3)和(4)的变体。
(3):我既不将嵌套的 class/struct 放在同一个文件中(如果它很小并且确实与父 class 相关),也不使用单独的文件在 partial ParentClass
声明中——唯一的缺点是它多了一层缩进,但我可以接受。我对违反 FxCop 规则或其他建议也没有问题——毕竟,它们只是建议,而不是强制性的。但是很多人确实对所有这些或其中的一些有问题,所以让我们继续吧。
(4):您已经描述了缺点。我要分享的是我是如何克服它们的。同样,它是个人的,可能喜欢也可能不喜欢,但就是这样。
首先,假设我们为密钥 class 使用一个单独的文件,并将 class 命名为 CarFinderKey
。
然后,在 CarFinder
class 的代码文件中,我们将以下行放在 的末尾(或内部的任何位置)using
部分:
using Key = CarFinderKey;
这样,只在CarFinder
class代码文件里面,任何需要CarFinderKey
的地方,我们可以简单的引用一下作为 Key
,目标是什么。同时我们保留了所有的优势,没有冲突。智能工作 w/o 任何问题。在 VS2015 中,灯泡甚至会在文件中找到 CarFinderKey
的任何地方为您建议 "simplify the name"。
您的决定应取决于您的设计。你的钥匙 class 真的只是 CarFinder 的钥匙,还是也可以用来找摩托车或房子什么的。
著名的四人帮制定的第一个规则是 "Design for change"。如果你真的认为在不久的将来你的钥匙也可以用来找房子或摩托车,那么把你的钥匙 class 设为私有以致其他人无法使用它并不是一个好主意。
既然你说的是私人助手 classes,我想你的钥匙只对 CarFinders 有用。
如果是这种情况,并且您的设计规定密钥仅对 CarFinders 有用,或者甚至:如果它的设计甚至在 CarFinders 之外也没有用,那么密钥 class 应该成为 CarFinders class 的一部分。将此与您将在 CarFinders class 中使用的简单整数进行比较,您会在 CarFinders class 中将其声明为私有,不是吗?
给您留下一个大文件或部分定义的问题。从设计的角度来看没有区别。对于编译器也没有区别。唯一的区别在于必须阅读它的人。如果您认为 class 的用户很少需要阅读您的密钥 class 的定义,那么最好将其定义在一个单独的文件中。但是,如果您在阅读 CarFinder class 时经常需要阅读密钥 class,您应该尽可能轻松地访问密钥 class。如果您的开发环境是完全面向文件而不是面向 class,那么我认为在那种情况下,大文件的缺点小于必须在文件之间切换的缺点。