引入其他局部变量作为注释替换


12

使用其他技术上多余的局部变量来描述正在发生的事情是一种好风格吗?

例如:

bool easyUnderstandableIsTrue = (/* rather cryptic boolean expessions */);

if(easyUnderstandableIsTrue)
{
    // ...
}

当涉及到技术开销时,我希望编译器能够优化此附加功能。但这是否被认为是不必要的代码膨胀?在我看来,它减少了陈旧评论的风险。


10
“使用附加的,技术上多余的局部变量来描述正在发生的事情是一种好风格吗?”。是。真的,这里不能说太多。
David Arno

3
在以后阅读代码时,我发现这种样式(即使用具有描述性名称的许多中间变量)非常有用。当然,您可以编写复杂的表达式并通过不引入中间变量来保存一些名称,但是为什么要这么做呢?即使代码编写得比较好,阅读代码也可能是一个很大的挑战,因此我认为不必要地使代码更加复杂不是明智的选择。
Mael

我相信这在Martin Fowler的重构目录中称为“合并条件表达式” 。
布兰丁

Answers:


16

拥有附加变量的成本是多少?在大多数语言中,无论是编译语言还是解释语言,都没有。

这有什么好处?

  • 与将隐式布尔表达式提取到单独的方法类似,您正在减少重复代码的风险,但比单独方法的情况要少。如果条件表达式在方法本身内部被重用,则可以重用该变量;如果表达式以其他方法出现,则不会。

    请注意,除非您的编程语言允许您拥有不可变的局部变量,否则除非您有一种方式强制实施任何变量都没有重新分配的方法,否则从长远来看,这种重构可能会有风险。如果变量的值被更改,则可能很难对代码进行推理。

  • 您正在减少文档与代码不同步的风险。开发人员往往比注释更容易更新变量和方法的名称。¹因此,看到诸如以下代码的情况并不少见:

    // Find if the user is an actual author in order to allow her to edit the message.
    if (currentUser.isAdministrator || (message.author == currentUser && !message.locked))

该表达式可能以开头if (message.author == currentUser),然后演变为处理锁定消息的情况,而管理员不必是作者,也不必关心锁定的东西。但是,该评论并未反映出任何这些变化。

这两个优点并不是特别重要,但是鉴于其他变量的成本较低,您确实可以考虑使用它们。

请注意,如果您的布尔表达式变得过于复杂:²

  • 将其提取为单独的方法,然后:
  • 将其重构为多个简单的布尔表达式。

上面的示例变为:

class Message
{
    ...
    public boolean canBeEditedBy(User user)
    {
        ...
        if (user.isAdministrator) {
            return true;
        }

        return this.author == user && !this.locked;
    }
}

...
if (message.canBeEditedBy(currentUser)) // See? Much more readable now!
{
    ...
}

¹资料来源:我对同龄人主要开发商业软件的观察;YMMV。真正的研究可能会显示不同的结果。我个人认为,当开发人员阅读代码时,他们将重点放在代码上,注释是文档,而不是代码。因此,他们通常不阅读评论,因此很难指望他们进行更新。

²过于复杂的阈值是用一个简单的公式定义的:如果一半查看您代码的开发人员表达了谋杀您的意图,那么就达到了阈值。上面的布尔表达式很简单,需要重构。但是,连续四部分if ((a && b) || (c && d))将使其具有潜在的可重构性。请注意,如果表达式为平面,则零件的数量几乎无关紧要:if (a || b || c || d || ... || z)足够可读。

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.