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


92

众所周知,要为班级提供好而精确的名称非常困难。如果做得正确,它将使代码更具自记录性,并为在更高抽象级别上进行代码推理提供了词汇。

可以基于众所周知的模式名称(例如FooFactory,FooFacade)为实现特定设计模式的类命名,而直接为领域概念建模的类可以从问题域中获取其名称,但是其他类呢?当我缺乏灵感并且想要避免使用通用类名(例如FooHandler,FooProcessor,FooUtils和FooManager)时,是否可以找到类似于程序员词库的东西?


6
这是一个很好的问题!关闭它是恕我直言的,没有道理,最好是迁移程序员网站。
Timofey 2014年

1
我同意,应该重新开放或搬迁
ftl


我已经看到很多这些很好的问题,“被casperOne关闭”。也许他可以担任Wikipedia的删除主义者?
Perlator

Answers:


58

我会引用肯特·贝克(Kent Beck)的《实现模式》中的一些段落:

简单的超类名称

“ [...]名称应该简短而有力。但是,要使名称精确,有时似乎需要几个单词。摆脱这种困境的一种方法是为计算选择一个强有力的隐喻。单个单词带来了丰富的联系,联系和含义网络,例如,在HotDraw绘图框架中,我在绘图中使用的对象的名字是 DrawingObject。页面上的图形项目是图形,因此该类变为图形。在隐喻的上下文中,图形DrawingObject更短,更丰富,更精确。”

合格的子类名称

“子类的名称有两个工作。它们需要传达自己喜欢的类以及它们之间的区别。[...]与层次结构根源的名称不同,子类名称在会话中的使用频率几乎没有,因此它们可以以简洁为代价来表现。[...]

给充当层次结构根源的子类自己的简单名称。例如,HotDraw具有一个Handle类,当选择图形时,该类提供图形编辑操作。 尽管扩展了Figure,它仍被简单称为Handle。有一个完整的句柄家族,它们最合适的名称是 StretchyHandleTransparencyHandle。因为Handle是其自身层次结构的根,所以它比合格的子类名称更值得一个简单的超类名称。

子类命名的另一个难题是多层次层次结构。[...]不要盲目地将修饰符放在直接的超类之前,而应该从读者的角度考虑名称。他需要知道什么课程?使用该超类作为子类名称的基础。”

接口

界面的两种命名方式取决于您对界面的看法。作为没有实现的类的接口应像它们是类一样被命名(Simple Superclass NameQualified Subclass Name)。这种命名方式的一个问题是,在命名类之前,好名字就被用完了。名为File的接口需要一个实现类,该实现类的名称为 ActualFileConcreteFile或(讨厌FileImpl(后缀和缩写)。通常,交流一个对象是要处理具体对象还是抽象对象很重要,而抽象对象是实现为接口还是超类则不太重要。这种命名方式很好地支持了延迟接口和超类之间的区别,如果有必要的话,稍后您可以自由地改变主意。

有时,命名具体的类对通信来说比隐藏接口的使用更重要。在这种情况下,请使用“ I”作为接口名称的前缀。如果接口称为IFile,则该类可以简称为File

如需更详细的讨论,请购买本书!这很值得!:)


1
“有时,对具体的类命名对通信而言比隐藏接口的使用更为重要。在这种情况下,为接口名称加上“ I”前缀。如果该接口称为IFile,则该类可以简称为File。这很有趣,因为在Robert C. Martin的书Clean Code中,我发现我们宁愿将实现命名为FileImpl,而不是将接口命名为IFile,因为我们不希望客户端知道我们正在为他们提供服务。接口。书中的^就是您所引用的书中的引文:)
Cristian Ciobotea

38

总是选择MyClassA,MyClassB-它允许进行很好的alpha排序。

我在开玩笑!

这是一个很好的问题,我不久前就经历过。我在工作时重新组织我的代码库,遇到了在哪里放置什么以及如何称呼它的问题。

真正的问题?

我的课做得太多。如果您尝试遵循单一职责原则,那么它将使所有内容都变得更好。.除了一个整体的PrintHandler类,您可以将其分解为PageHandlerPageFormatter(等等),然后拥有一个主Printer类。汇集所有。

在我的组织中,这花了我一些时间,但是最终我对很多重复的代码进行了分箱,使我的代码库更加逻辑化,并且在将额外的方法扔给类之前想了很多事情:D

但是,我建议将模式名称之类的内容放入类名称中。classes接口应该使这一点变得显而易见(例如隐藏单例的构造函数)。如果该类用于通用目的,则通用名称没有任何问题。

祝好运!


同意不将模式名称放入类名称。如果模式在以后的实现发生更改时又发生了变化,该怎么办?
thegreendroid 2014年

2
我宁愿在名称中添加模式名称。为什么?因为如果我必须查看实现细节(例如私有构造函数)以发现它是一个单例,这会使我作为阅读器的速度变慢,并且取决于我的技能水平,所以我可能不会弄清楚它实际上是一个类的一部分一般模式。Singleton和private构造函数是一个值得怀疑的示例,但是对于更复杂的模式(Visitor,Adapter等),它变得相当复杂。如果模式发生变化,则可能是这些类不再存在了……
dragan.stepanovic

28

Josh Bloch关于好的API设计的精彩演讲有一些不错的建议:

  • 班级应该做一件事并且做得很好。
  • 如果一个班级很难命名或解释,那么它可能不遵循上一个要点的建议。
  • 班级名称应立即传达班级的含义。
  • 好的名字驱动好的设计。

如果您的问题是要公开内部类的名字,也许您应该将它们合并为一个更大的类。

如果您的问题是命名一个执行许多不同工作的类,则应考虑将其分为多个类。

如果这对于公共API来说是个好建议,那么对于其他任何类都不会受到伤害。


1
youtube上的视频链接youtube.com/watch?v=aAb7hSCtvGw
Andrew Harry,

12

如果您坚持使用某个名称,有时只是给它一个半明智的名称并承诺以后再修改它是一个好策略。

不要让命名麻痹。是的,名称很重要,但它们的重要性还不足以浪费大量时间。如果您无法在10分钟内想到一个好名字,那就继续吧。


9

如果没有想到好名声,我可能会质疑是否存在更深层的问题-课堂是否有良好的目的?如果是这样,则命名应该非常简单。


3

如果您的“ FooProcessor”确实处理foo,那么不要仅仅因为您已经拥有BarProcessor,BazProcessor等而就给它起这个名字。如有疑问,最好是显而易见的。其他必须阅读您的代码的开发人员可能没有使用与您相同的同义词库。

就是说,对于这个特定的例子,更多的特异性不会受到损害。“过程”是一个相当宽泛的词。例如,它真的是“ FooUpdateProcessor”(可能会变成“ FooUpdater”)吗?您不必对命名有太大的“创意”,但是如果您编写了代码,则可能对它的作用和不作用有一个很好的了解。

最后,请记住,裸类名称并不仅限于您,您的代码读者也必须继续这样做-通常还存在名称空间。这些通常可以为读者提供足够的上下文,以清楚地了解您的课程的真正目的,即使其裸名是相当通用的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.