命名类的最佳方法是什么?

103

给类取个好、准确的名称是非常困难的。如果做得好,它可以使代码更加自我说明,并提供一个用于高层次抽象理解代码的词汇表。

实现特定设计模式的类可以根据其已知模式名称(例如 FooFactory、FooFacade)进行命名,而直接模拟领域概念的类可以从问题域中获取名称,但其他类如何处理呢?是否有像程序员同义词词典那样的东西,当我缺乏灵感时可以翻阅,避免使用通用类名称(例如 FooHandler、FooProcessor、FooUtils 和 FooManager)?


6
这是一个非常好的问题!关闭它在我看来是不合理的,更好的做法是将其迁移到程序员网站上。 - Timofey
1
我同意,应该重新开放或移动。 - ftl
1
我看到很多这样优秀的问题都被“casperOne”关闭了。也许他可以在维基百科上担任删除者? - Perlator
6个回答

67
我将引用Kent Beck的《实现模式》中的一些段落:

简单的超类名

"[...] 名称应该简短而有力。但是,为了使名称精确,有时似乎需要几个词。摆脱这种困境的方法是选择一个强大的计算机隐喻。有了隐喻,即使是单词也带来了丰富的联想、联系和含义。例如,在HotDraw绘图框架中,我对于绘图对象的第一个名称是DrawingObject。Ward Cunningham提出了排版隐喻:绘图就像一张印刷、布局好的页面。页面上的图形项是图形,因此该类变成了Figure。在隐喻的背景下,FigureDrawingObject同时更短、更丰富和更精确。"

限定子类名

"子类的名称有两个任务。它们需要传达它们所像和如何不同于哪个类。[...] 与层次结构根部的名称不同,子类名称在对话中使用的频率不高,因此它们可以以表达为代价而简洁。[...] 给作为层次结构根源的子类一个简单的名称。例如,HotDraw有一个名为Handle的类,当选择一个图形时,它提供了图形编辑操作。尽管扩展了Figure,但它被称为Handle。有一个完整的handles家族,它们最适合像StretchyHandle和TransparencyHandle这样的名称。 由于Handle是其自己层次结构的根,因此它比限定的子类名称更应该拥有一个简单的超类名称。 子类命名中的另一个问题是多级层次结构。[...] 不要盲目地将修饰符添加到直接超类,要从读者的角度考虑名称。他需要知道这个类像哪个类?以那个超类为子类名称的基础。"

接口

两种接口命名风格取决于您如何思考接口。将接口视为没有实现的类时,应该像类一样命名(Simple Superclass Name,Qualified Subclass Name)。这种命名风格的一个问题是,好的名称在你开始命名类之前就被用完了。名为“File”的接口需要一个叫做“ActualFile”、“ConcreteFile”或者(糟糕!)“FileImpl”的实现类(既有后缀又有缩写)。通常,传达一个对象是具体的还是抽象的很重要,无论抽象对象是作为接口还是超类实现都不那么重要。推迟接口和超类之间的区别可以很好地支持这种命名风格,如果必要的话,您可以随时改变主意。有时,命名具体类比隐藏接口的使用更重要。在这种情况下,使用“I”前缀来命名接口。如果接口称为IFile,则类可以简单地称为File。想要更详细的讨论,请购买本书!它值得一读! :)

2
有时,为了更好地进行沟通,命名具体类比隐藏接口的使用更重要。在这种情况下,可以在接口名称前加上“I”的前缀。如果接口称为IFile,则类可以简单地称为File。 - Cristian Ciobotea

41

始终选择MyClassA、MyClassB-它可以进行良好的按字母排序..

我开玩笑的!

这是一个好问题,也是我不久前遇到的问题。我正在重新组织我的工作代码库,并且在放置什么以及如何命名方面遇到了问题。

真正的问题是什么?

我的类做了太多事情。如果您尝试遵循单一职责原则,它将使所有内容更加协调。而不是一个臃肿的PrintHandler类,您可以将其拆分为PageHandlerPageFormatter(等等),然后有一个主Printer类将所有内容汇集在一起。

在我的重新组织中,我花费了一些时间,但最终处理了大量重复的代码,让我的代码库更加合理,并学会了在向类中添加额外方法之前先思考的东西:D

然而,我不建议将像模式名称之类的内容放入类名中。类的接口应该显而易见(例如隐藏单例构造函数)。如果类提供通用目的,则使用通用名称是没有问题的。

祝你好运!


同意不把模式名称放入类名中。如果在实现更改时模式发生变化怎么办? - thegreendroid
2
我宁愿在名称中放置模式的名称。为什么?因为如果我必须查看实现细节(如私有构造函数)才能发现它是单例,那么这会减慢我作为读者的速度,并且根据我的技能水平,我可能无法弄清楚它实际上是一般模式的一部分。单例和私有构造函数是一个值得怀疑的例子,但对于更复杂的模式(访问者、适配器等),情况就变得相当复杂了。如果模式发生变化,那么这些类可能就不存在了... - dragan.stepanovic

29

Josh Bloch的一次有关良好API设计的优秀演讲提供了以下几点建议:

  • 类应该只做一件事,并且要做得很好。
  • 如果一个类很难命名或解释,那么它可能没有遵循上一个标志点的建议。
  • 类名应立即传达出这个类是用来做什么的信息。
  • 好的命名能推动好的设计。

如果您的问题是如何为公开的内部类命名,也许您应该将它们合并成更大的类。

如果您的问题是为正在执行多种不同任务的类命名,则应考虑将其拆分成多个类。

如果这对于公共API是一个好主意,那么对于任何其他类都不会有坏处。


1
YouTube上的视频链接:http://www.youtube.com/watch?v=aAb7hSCtvGw - Andrew Harry

15
如果你卡在了命名上,有时候只要给它任何一个半靠谱的名字,并承诺稍后修改它,这是一个好策略。
不要陷入命名恐慌。是的,名称非常重要,但它们并不重要到值得浪费大量时间。如果你不能在10分钟内想出一个好名字,那就继续前进。

10
如果没有一个好的名称浮现在脑海中,我可能会质疑是否存在更深层次的问题——这个类是否起到了良好的作用?如果是的话,给它命名应该是非常简单的。

3
如果你的“FooProcessor”确实处理foos,那么不要因为你已经有了BarProcessor、BazProcessor等而不愿意给它这个名字。当你不确定时,显而易见是最好的选择。阅读你代码的其他开发人员可能没有使用和你相同的词库。
话虽如此,对于这个特定的例子来说,更具体的描述也不会有坏处。“Process”是一个非常广泛的词汇。例如,它真的是一个“FooUpdateProcessor”(可能会变成“FooUpdater”)吗?你不必过于“创造性”地命名,但如果你编写了这段代码,你可能已经非常清楚它的功能和限制。
最后,请记住,裸类名并不是你和代码读者所依赖的全部 - 通常还有命名空间在起作用。即使它的裸名相当普通,这些命名空间通常可以给读者足够的上下文来清楚地看到你的类真正的用途。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接