那么,当你编写一个布尔方法时,你在返回方法命名中使用时态,比如“has”或“was”,还是只使用“is”?
以下是我最近写的一种Java方法,非常简单..
boolean recovered = false;
public boolean wasRecovered()
{
return recovered;
}
在这种情况下,恢复是一种状态,在代码中此时可能已经已经已经发生,因此语法上“是”是有意义的。但它在代码中是否有同样的意义,“is”命名约定通常是标准的?
答案 0 :(得分:7)
我更喜欢使用IsFoo()
,无论时态如何,只是因为这是一个众所周知的惯例,非母语人士通常仍会理解。非英语母语人士在当今的全球行业中经常被考虑。
答案 1 :(得分:4)
我使用适合值的含义的时态。否则实际上创建了一种读取单向并且表现另一种方式的代码。让我们看一下.Net Framework中的一个真实世界的例子:Thread.IsAlive
此属性以现在时呈现。这意味着值引用了当前的值并使得代码如下所示
if (thread.IsAlive ) {
// Code that depends on the thread being alive
...
这里的问题是该属性不代表它代表过去状态的对象的当前状态。一旦将值计算为true
,相关线程就可以立即退出并使值无效。因此,该值只能安全地用于标识线程的过去状态,并且过去时态属性更合适。现在让我们重温一下阅读方式不同的样本
if ( thread.WasAlive ) {
// Code that depends on the thread being alive
...
它们的行为相同,但其中一个读取非常差,因为它实际上代表了糟糕的代码。
以下是其他一些罪犯的名单
File.Exists
Directory.Exists
DriveInfo.IsReady
WeakReference.IsAlive
答案 2 :(得分:2)
isXxx
前缀是一种广泛的命名惯例,因此它通常是最佳选择。
对于对订单敏感的操作, wasXxx
是合适的。例如,在JDBC中,当字段实际为NULL(未设置)时,检索数据库列的值可能会返回零;在这种情况下,对wasNull
的后续调用确定在执行实际检索后它是。
要检索属性设置, hasXxx
可能更合适。这是语法偏好,如“对象的标志是设置”与“对象具有属性”。
然后有能力测试 canXxx
。例如,调用canWrite
以查看文件是否可写。但是这些名称可能会重命名为isXxx
表单,例如isWritable
。
答案 3 :(得分:1)
我倾向于,是的。例如,在错误检查中:
$errors = false;
public function hasErrors()
{
return $this->errors;
}
答案 4 :(得分:1)
我不介意wasRecovered
那么多。恢复是过去可能发生或未发生的事件 - 这会告诉您它是否发生了。但是如果你因为恢复的一些后果而使用它,我更喜欢isCached
,isValid
,或者其他对这些后果实际上是什么的描述。仅仅因为你已经恢复了某些东西并不意味着你从未失去过它。
始终要注意,在英语中,使用过去分词作为形容词在传递和不及物动词之间(可能在主动和被动语态之间)是不明确的。 isRecovered
可能表示对象已被其他内容恢复,或者可能意味着对象已恢复。如果您的对象代表医院的患者,“isRecovered”是否意味着患者身体健康,或者有人从X光部门取回患者?因此wasRecovered
对后者可能更好。
答案 5 :(得分:1)
我不确定你是否正确地考虑过这个问题。使用Recovered
属性的原因是因为这是对象在现在中的状态,而不是因为那是对象曾经处于的状态。可能有一些进程在过去(恢复)现在已经完成,但我们现在访问这个属性的事实意味着有一些关于已完成的过程改变了当前状态,并且当前状态很重要。对我来说,“恢复”捕捉了那个国家的本质。对于此示例(以及大多数类似情况),我将使用IsRecovered
来命名指示此情况的谓词。 (这也符合普通英语:“这是一份已恢复的文件。”)
我很少使用现在时以外的任何东西来命名程序中的谓词(IsDirty
,HasCoupon
)或布尔函数(IsPrime(x)
)。
例外情况是指示可能需要恢复的状态(DocumentWindow.WasMaximizedAtLastExit
)。
我通常会使用不定式来表示将来时(ToBeCopied
而不是WillBeCopied
),因为最好的软件计划有时会被更改(或取消)。
答案 6 :(得分:1)
为了尝试简化语义,要意识到有一些场景会使IsXXX形式存在争议,并且有一些非常常见的场景,其中IsXXX表单是唯一有用的场景。
下面是Thread.IsAlive()的'真值表',它基于线程随时间的可能状态。忘记为什么线程可能会触发翻转状态,我们需要关注使用的语言。
Past Present Future
===== ======= =======
1. alive alive alive
2. alive alive dead
3. alive dead dead
4. dead dead dead
5. dead dead alive
6. dead alive alive
7. dead alive dead
8. alive dead alive
注意:我将在下面讨论Future状态以保持一致性。了解线程是否会死亡很可能不可知作为The Halting Problem的一个子集
当我们通过调用方法询问一个对象时,有一个共同的假设是“这个线程是否存活,在我问时?对于这些情况,”Present“列中的答案是我们所关心的并且使用IsXXX表格工作正常。
场景#1 (永远活着)和#4 (总是死的)是最简单和最常见的。 IsAlive()
的答案不会在通话之间发生变化。对出现的语言的争论是由于其他6个案例,调用IsAlive()
的结果取决于何时调用。
情景#2 (将会死亡)和#3 (已经死亡)从生存转为死亡。
场景#5 (将开始)和#6 (已开始)从死亡过渡到活着。
对于这四个(2,3,5,6),IsAlive()
的答案并不是一成不变的。问题变成了,我是否关心现状,IsAlive()
,还是我对过去/未来状态WasAlive()
和WillBeAlive()
感兴趣?除非你可以预测未来,否则WillBeAlive()
调用对于除了最具体的设计之外的所有设计都将毫无意义。
在处理线程池时,我们可能需要重新启动处于“死”状态的线程来为连接请求提供服务,并且它们是否还活着并不重要,只是它们当前已经死了。在这种情况下,我们可能实际上想要使用WasDead()
。当然,我们应该尽量保证不重新启动刚刚重启的线程,但这是一个设计问题,而不是语义问题。假设没有其他人可以重新启动该线程,我们使用IsAlive() == false
还是WasDead() == true
并不重要。
现在是最后两个场景。场景#7 (已死,活着,将死)与#6 几乎相同。你知道何时将会死吗?在10秒,10分钟,10小时?在决定做什么之前你要等吗?不,你只关心当前(现在)的状态。我们在谈论命名,而不是多线程设计。
场景#8 (活着,已死,将活着),几乎与#3 相同。如果您正在重用线程,那么它们可以循环遍历alive / dead状态几次。担心#3 和#8 之间的区别会回到暂停问题,因此可以忽略不计。
IsAlive()
适用于所有情况。 IsAlive() == false
适用于#5 和#6 ,而不是添加WasAlive()
。
答案 7 :(得分:0)
方法命名的自负是您正在检索有关对象的信息。要以过去时态命名,它必须是关于对象的先前状态的信息,而不是其当前状态。
我能想到使用过去时的唯一原因是,如果我检查以前发生的事情的缓存结果,但不再是这种情况。对于一个人为的例子,也许可以在swap()
调用之后回复之前的值。它可能在原子设计的操作中很有用。虽然不是真的可能在野外。
答案 8 :(得分:0)
由于您的问题特定于Java,因此如果您的类是JavaBean并且该方法是属性的访问器方法,则方法名称应以“is”开头。
http://download.oracle.com/javase/tutorial/javabeans/properties/properties.html