什么被认为是更好的风格?一个大循环还是多个小循环?

Luk*_*sen 2 coding-style

我目前正在使用一个大容器,我需要迭代它来做很多事情。以下哪个被认为是更好的风格?

a) 大循环:

for (container::iterator it = myContainer.begin(); it < myContainer.end(); ++it) {
    // do thing a with *it

    // do thing d with *it

    // do thing c with *it

    // do thing b with *it
}
Run Code Online (Sandbox Code Playgroud)

b) 小循环:

for (container::iterator it = myContainer.begin(); it < myContainer.end(); ++it) {
    // do thing a with *it
}

for (container::iterator it = myContainer.begin(); it < myContainer.end(); ++it) {
    // do thing b with *it
}

for (container::iterator it = myContainer.begin(); it < myContainer.end(); ++it) {
    // do thing c with *it
}

for (container::iterator it = myContainer.begin(); it < myContainer.end(); ++it) {
    // do thing d with *it
}
Run Code Online (Sandbox Code Playgroud)

我发现 b) 更好读,因为 a) 会变得笨重,非常容易且难以理解。但是 a) 我认为会跑得更快。那么哪一个是更好的风格呢?myContainer 将包含多达 10.000 个元素,并且必须重复此过程,因此性能很重要。

Jar*_*ran 5

将单独的任务拆分为不同的循环还有进一步的重构优势。

在处理大数据集时,循环性能并不总是很直接,因此您通常应该从可读性开始,并在需要时返回到单循环。

这是Martin Fowler的Split Loop 重构示例

您经常会看到循环同时做两种不同的事情,因为它们可以通过一次循环来完成。事实上,大多数程序员会对这种重构感到非常不舒服,因为它迫使你执行两次循环——这是双倍的工作。

但是像许多优化一样,在一个循环中做两件不同的事情比单独做更不清晰。它还会给进一步重构带来问题,因为它引入了阻碍进一步重构的临时变量。因此,在重构时,不要害怕摆脱循环。优化时,如果循环很慢,则会出现这种情况,此时将循环重新组合在一起是正确的。您可能会惊讶于循环不是瓶颈的频率,或者后来的重构如何开启另一个更强大的优化。

原码

void printValues() {
  double averageAge = 0;
  double totalSalary = 0;
  for (int i = 0; i < people.length; i++) {
    averageAge += people[i].age;
    totalSalary += people[i].salary;
  }
  averageAge = averageAge / people.length;
  System.out.println(averageAge);
  System.out.println(totalSalary);
}
Run Code Online (Sandbox Code Playgroud)

成为最初

void printValues() {
  double totalSalary = 0;
  for (int i = 0; i < people.length; i++) {
    totalSalary += people[i].salary;
  }

  double averageAge = 0;
  for (int i = 0; i < people.length; i++) {
    averageAge += people[i].age;
  }
  averageAge = averageAge / people.length;

  System.out.println(averageAge);
  System.out.println(totalSalary);
}
Run Code Online (Sandbox Code Playgroud)

提取方法后清理代码

void printValues() {
  System.out.println(averageAge());
  System.out.println(totalSalary());
}

private double averageAge() {
  double result = 0;
  for (int i = 0; i < people.length; i++) {
    result += people[i].age;
  }
  return result / people.length;
}

private double totalSalary() {
  double result = 0;
  for (int i = 0; i < people.length; i++) {
    result += people[i].salary;
  }
  return result;
}
Run Code Online (Sandbox Code Playgroud)