如何避免抽象类的通用名称?


10

通常,最好避免将诸如“ handle”或“ process”之类的单词作为例程名称和类名称的一部分,除非您要处理(例如)文件句柄或(例如)unix进程。但是,抽象类通常并不真正知道它们除了处理之外还打算做什么。在当前情况下,我有一个“ EmailProcessor”,它可以登录到用户的收件箱并处理来自该收件箱的消息。尽管我注意到出现了以下样式问题,但我仍然不清楚如何给它一个更精确的名称:

  • 更好地将派生类视为客户端,并通过其实现的功能的一部分来命名基类?给它更多的含义,但会违反is-a。例如,EmailAcquirer是一个合理的名称,因为它是为派生类获取的,但是派生类将不会为任何人获取。
  • 或只是名字含糊不清,因为谁知道派生类将做什么。但是,“处理器”仍然过于笼统,因为它正在执行许多相关的操作,例如登录和使用IMAP。

摆脱这种困境有什么办法吗?

对于抽象方法,问题更加明显,在抽象方法中,您不能真正回答“这是做什么的”问题。因为答案仅仅是“客户想要的任何东西”。


您是否有“一般”声明的来源(和某些上下文)?此外,该列表还有一个附加的命名规则-不要浪费时间寻找可能不存在的完美名称。如果有疑问,请给它尽可能的最好的名称,在必要时在定义的地方添加更长的描述作为注释,但是如果有人不喜欢您的选择或者当您突然出现完美的名字时,您可以稍后进行重构。在做其他事情。
2012年

3
@ Steve314-是的,Steve McConnell,代码完成,第1版,例程的第4或5章。在这些章节中对命名进行了广泛的讨论,从根本上得出结论,如果您没有好名字,您可能就没有很好的功能。
djechlin 2012年

找不到好名字似乎是一个不好的信号,但是IMO您应该根据功能本身知道该功能是否不好。仅仅因为英语不是为您的项目定制设计而进行重构有点愚蠢。不,这不是日常问题,但是您已经确定自己遇到了问题。
2012年

1
@ Steve314编程完全是关于管理复杂性的,如果您的大脑不能为某个事物想出一个词,那么很有可能它将无法管理它的复杂性,而必须执行诸如使用它的操作。更大的句子或更大系统的一部分。说不能找到好名字是引起担忧的主要原因,这并不是一个大胆的声明。但这在麦康奈尔进行了广泛的讨论,我建议至少阅读这两章,尽管整本书值得从头至尾阅读。
djechlin 2012年

“代码完整”中的声明不一定是受信任的。我知道这本书的声誉,但是我也知道这一点。此外,多年来,我一直在很好地管理复杂性-会发生错误,会导致错误,但是当事情出错时,有时问题是一个如此简单的函数,显然不会出错,但是无论如何都是如此
2012年

Answers:


10

问题不在于名称,而在于您在一堂课中投入过多。

在您的示例类中,某些部分非常具体(如何获得邮件)。其他部分则非常抽象(您将如何处理邮件)。

最好是使用单独的类,而不要使用继承。

我建议:

  • 一个抽象的MessageIterator,由POPMailBoxDownloader子类化

  • 另一个拥有POPMailBoxDownloader并处理消息的类。


这听起来完全正确。听起来,如果您发现自己在命名“ processEvent”或类“ MessageProcessor”,则很有可能可以对合成进行设计而不是派生。在这种情况下,这是一个折衷,因为维护者的灵活性可能是有用的,但是客户端会因为确切地想知道每个函数的功能(而不是维护者)而烦恼。
djechlin 2012年

6

如果找不到类的好名字,请为该类编写内联代码文档。它以一种气味描述了课堂的目的。通常,我可以从此描述中为该类派上好名字。这对抽象类也很有帮助。

如果类的描述为“登录到用户的收件箱并处理来自它的消息”,则建议使用“ InboxProcessor”作为类名。如果派生类具有“登录用户的收件箱并将垃圾邮件移动到垃圾邮件文件夹”作为描述,我将选择“ InboxSpamMover”作为名称。

使用“处理器”之类的通用名称时,如果它反映了抽象类的通用用途,则不会出现问题。

如果您在用一种或两种香气描述一门课程的目的时遇到问题,那么您可能会遇到设计问题。也许课堂做得太多,违反了“ 单一责任原则”。这也适用于抽象类。


2

用弗兰克·扎帕(Frank Zappa)来解释,它就是它的名字,应该这样命名。您的示例只是没有深入研究正在进行的处理。是EmailToTroubleTicketProcessoran EmailGrammarCorrector或an EmailSpamDetector吗?

对于抽象方法,问题更加明显,在抽象方法中,您不能真正回答“这是做什么的”问题。因为答案仅仅是“客户想要的任何东西”。

那不是真的。对于抽象的东西您无法回答的问题是“ 它是如何做到的?” 因为那是特定于实现的。如果一个EmailSender类有一个DeliveryStatus deliver(Email e)方法,则有一个隐含的约定,即实现将接收一封电子邮件,尝试传递它,并返回有关其运行方式的某些状态。您不必关心它是连接到SMTP服务器还是将其打印出来绑在归巢的鸽子上,只要实现能够实现所承诺的目标即可。摘要只是量化了承诺,因此实现可以说:“是的,我做到了。”


那么当end函数在某种意义上是终端时,那么抽象类会说:“而这在这里,您想用它做什么呢?” 例如,该方法无权访问状态,返回类型无效,不抛出。
djechlin 2012年

还是一样。即使您的方法是void doWhatYouDoWith(Email e),您仍然可以将类称为an EmailDisposer,该类足以说明其作用,但又足够笼统,取决于实现方式。尽管我认为@KrisVanBael对此表示赞同:如果您诉诸于一些含糊不清的内容,那么在一个屋顶下可能有太多东西。
Blrfl 2012年

0

考虑一下为什么使用这样的单词不好。它们是描述性的吗?那里用什么词来描述课程?EmailBaseClass?比说EmailManager或类似的东西更具描述性吗?关键是要深入了解所讨论的类,因此要找到适当的动词或名词。像对待诗歌一样对待您的代码。


“ EmailBaseClass”就像命名int age“ ageInteger”一样,甚至更糟,因为我希望从中获取纯文本电子邮件,MIME电子邮件等。无需首先描述该词的开头abstract(这是Java)。您对本课程的基础部分有什么特别的见解吗?而且,更多的洞察力仍不能解决为某个将要穿越is-a关系的事物命名的问题,我可能会感到有些含糊不清或太笼统,除非有拥有更多洞察力的更多洞察力。
djechlin 2012年

@djechlin-在极少数情况下,ageInteger实际上是合适的。匈牙利语表示法是上下文的缩写形式,它在其中经常发生。当然,有些时候你可能需要沿着线的东西ageNumeric,并ageString在同一范围内,与在名称为消除歧义的最简单和最清晰的方式类型的指示。
2012年

@djechlin我个人觉得使用代码最简单,我可以偷看一下以获得理解。也就是说,名字告诉我我在做什么。无需知道systemController抽象基类还是庞大层次结构中的叶。当然,这可以通过IDE来解决(我想大多数Java开发都是这种情况),它可以立即通知用户类的内容和结构,因此实际上有见识的名称不能以类似的方式被证明是正确的。
zxcdw 2012年
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.