创建一次使用的变量是一种好习惯吗?

时间:2009-02-20 08:41:08

标签: variables refactoring coding-style

我的一位同事重构了这段代码:

private void btnGeneral_Click(object sender, RoutedEventArgs e)
{
    Button button = (Button)e.OriginalSource;
    Type type = this.GetType();
    Assembly assembly = type.Assembly;
    string userControlFullName = String.Format("{0}.{1}", type.Namespace, button.Name);
    UserControl userControl = (UserControl)assembly.CreateInstance(userControlFullName);
}

到此代码:

private void btnGeneral_Click(object sender, RoutedEventArgs e)
{
    Button button = (Button)e.OriginalSource;
    Type type = this.GetType();
    Assembly assembly = type.Assembly;
    UserControl userControl = (UserControl)assembly.CreateInstance(String.Format("{0}.{1}", type.Namespace, button.Name));
}

说如果只使用一次变量,则不需要创建变量。

我的回答是,制作曾经使用过的变量是很好的做法,因为它:

  • 用作和减少注释(很清楚“userControlFullName”是什么)
  • 使代码更易于阅读,即更多代码“读起来像英语”
  • 通过用明确的变量名替换部分语句来避免超长语句
  • 更容易调试,因为你可以将鼠标悬停在变量名称上,例如,没有调试器的PHP编程,更容易回显这些变量名来获取它们的值

反对这种方式的论据“更多代码行”,“不必要的变量”是使编译器生活更轻松但没有显着速度或资源节省的参数。

任何人都可以想到不应该创建曾经使用过的变量名的任何情况吗?

14 个答案:

答案 0 :(得分:26)

在这种情况下,我是你的意见。可读性是关键。我确信编译器在两种情况下都会生成相同的可执行文件,编译器就像现在一样智能。

但我不会声称“总是使用曾经使用过的变量”。例如:

String name = "John";
person.setName(name);

是不必要的,因为

person.setName("John");

读得同样好 - 如果不是更好。但是,当然,并非所有案例都是明确的。毕竟,“可读性”是一个主观的术语。

答案 1 :(得分:19)

你的所有理由似乎都对我有用。

在某些情况下,您有效地拥有以避免使用中间变量,您需要单个表达式(例如,用于Java / C#中的成员变量初始化),但为了清晰起见引入额外的变量绝对没问题它适用的地方。显然不要为 每个方法的每个参数执行此操作,但在适度的情况下,它可以提供很多帮助。

调试参数特别强大 - 能够逐步过去为方法“准备”参数的行,并直接进入方法本身,看到了调试器中的参数很容易。

答案 2 :(得分:16)

你的同事似乎不一致。

一致的解决方案如下所示:

private void btnGeneral_Click(object sender, RoutedEventArgs e)
{
    UserControl userControl = ((UserControl)type.Assembly).CreateInstance(String.Format("{0}.{1}", this.GetType().Namespace, ((Button)e.OriginalSource).Name));
}

答案 3 :(得分:6)

我完全和你在一起。

如果方法需要很多布尔值,我特别使用它,即

public void OpenDocument(string filename, bool asReadonly, bool copyLocal, bool somethingElse)

对我而言,这更具可读性:

bool asReadonly = true;
bool copyLocal = false;
bool somethingElse = true;

OpenDocument("somefile.txt", asReadonly, copyLocal, somethingElse);

..比:

OpenDocument("somefile.txt", true, false, true);

答案 4 :(得分:4)

由于我使用的编程语言通常不会告诉我在异常堆栈跟踪中什么是null我通常会尝试使用变量,这样每行不超过一个项可以为null。我实际上发现这是我想要在一行中放置多少语句的最重要的限制因素。

如果您从生产日志中获得此声明中的nullpointerexception,那么您确实遇到了麻烦:

GETCUSTOMER()。getOrders()。迭代器()。下一个()。getItems()。迭代器()。下一个()。getProduct()。的getName()

虽然我同意你的想法,但添加一个额外的变量可能会在方法中引入一个额外的概念,这个概念可能并不总是与方法的总体目标相关。因此,过多添加变量也会增加方法的复杂性并降低可读性。请注意过度的用法。

答案 5 :(得分:2)

两个代码完全相同。当然,你的更具可读性,可维护性和可调试性,但是,如果这是你同事的意思,那么他的代码就不会减少消费者的记忆。

答案 6 :(得分:2)

我认为这是一个基于您希望代码整洁程度的判断。我也认为你和你的同事都是正确的。

在这种情况下,我会根据您提供的代码与您的同事一起(出于性能原因),但正如我之前所说,它确实取决于它将被使用的环境,我认为您的立场是完全可以接受的。

我想指出,为一次使用的参数创建变量可能毫无意义,除非它们是常量变量或需要在很多地方使用的东西。

我认为声明曾经使用过的变量可能会在调试时产生更多的混乱,如果有很多很多这样的,但是这里有一个可能没问题。

答案 7 :(得分:2)

我猜在某些情况下会对性能产生影响。特别是在这个例子中:

for (int i1 = 0; i1 < BIG_NR; i1++)
{
  for (int i2 = 0; i2 < BIG_NR; i2++)
  {
    for (int i3 = 0; i3 < BIG_NR; i3++)
    {
      for (int i4 = 0; i4 < BIG_NR; i4++)
      {
        int amount = a + b;
        someVar[i1][i2][i3][i4] = amount;
      }
    }
  }
}

......额外的任务可能会对绩效产生太大的影响。 但总的来说,你的论点是100%正确的。

答案 8 :(得分:2)

我原则上完全与你的同事在一起,但在这种情况下不是。

一次性变量的问题在于它们引入了状态,而更多的状态意味着代码更难理解,因为你不知道它可能对程序的流程产生什么影响。功能编程完全没有变量,正是出于这个原因。所以变量越少越好。消除变量是好的。

然而,在这种特殊情况下,方法在变量仅被使用之后结束,具有它的缺点是最小的,并且您提到的优点可能更大。

答案 9 :(得分:1)

努力想出一个反对引入新变量的论据我会说当你读代码时(至少是第一次),你不会知道这个变量被使用不止一次。因此,您将立即让您的眼睛扫描代码,看看它是否在更多地方使用。功能越长,您就越需要查看是否可以找到它。

这是反对的最佳论点,我可以提出来! : - )

答案 10 :(得分:1)

创建一个新变量意味着读者可以追踪的另一个概念。 (考虑极端情况:int b = a; c = b;)如果一个方法如此复杂 - 需要分解 - 额外的概念是值得付出的代价,那么你应该去整个生猪和分裂它分为两种方法。这样,您将获得有意义的名称和较小的大小。 (原来的方法比较小:如果你说的话,那么人们通常不需要阅读辅助方法。)

这是一种概括,特别是在一种有很多用于添加新方法的样板的语言中,但是你不会经常不同意这种泛化,以使其值得忽略你的风格指南。

答案 11 :(得分:0)

我在这里与大多数人一致,代码可读性是关键。

这是一个罕见的行数十字军,它实际上编写了高度可读,高度可维护的代码。

此外,无论如何都将编译为MSIL,编译器将为您进行优化。

在以下示例中,编译器仍将优化代码:

List<string> someStrings = new List<string>();
for (int i = 0; i < 1000; i++)
{
    string localString = string.Format("prefix{0}", i);
    someStrings.Add(localString);
}

而不是:

List<string> someStrings = new List<string>();
string localString = string.Empty;
for (int i = 0; i < 1000; i++)
{
    localString = string.Format("prefix{0}", i);
    someStrings.Add(localString);
}

因此,在许多情况下,没有任何表现理由不适合它。

答案 12 :(得分:0)

这就是我以前编码的方式。如今我试图最小化中间变量。如果它是不可变的,那么使用中间变量是完全正确的。

答案 13 :(得分:-1)

同意

  

“使代码更易于阅读,即更多代码”读起来像英语“

我认为这是最重要的因素,因为大多数现代托管语言的性能或功能没有差异

毕竟我们都知道代码比写代码更难阅读。

卡尔