【问题标题】:for-loop + Arrow Anti Pattern VS for-loop + continue [closed]for-loop + Arrow Anti Pattern VS for-loop + continue [关闭]
【发布时间】:2015-09-23 08:58:25
【问题描述】:

你认为下面的代码片段(for-loop + continue)

for (Identity fileIdentity : fileIdentities) {
      totalFileCount++;
      if (!forceTheStatus(params, fileIdentity))
        continue;
      updatedFileCount++;
      if (!params.shouldUpdateLinkedEntity())
        continue;
      Optional<Identity> batchIdentity = getLinkedBatchIdentity(fileIdentity);
      if (!batchIdentity.isPresent())
        continue;
      totalBatchCount++;
      if (!getRemittanceProcessor().forceTheStatus(params, batchIdentity.get()))
        continue;
      updatedBatchCount++;
}

比这个更好(for-loop + Arrow Anti Pattern)?为什么?

for (Identity fileIdentity : fileIdentities) {
      totalFileCount++;
      if (forceTheStatus(params, fileIdentity)) {
        updatedFileCount++;
        if (params.shouldUpdateLinkedEntity()) {
          Optional<Identity> batchIdentity = getLinkedBatchIdentity(fileIdentity);
          if (batchIdentity.isPresent()) {
            totalBatchCount++;
            if (getRemittanceProcessor().forceTheStatus(params, batchIdentity.get()))
              updatedBatchCount++;
          }
        }
      }
}

对我来说 continue 的解决方案看起来更难理解,但另一方面我们有一个反模式:(

【问题讨论】:

  • antipattern,恕我直言,是一个更难阅读维护支持的工作人员> 等等。在你的情况下,它是第一个块。 ifs 的数量(及其级别)没有任何意义。

标签: java design-patterns anti-patterns


【解决方案1】:

这两种解决方案都不可读。不要使用 continue 并且不要在一种方法中创建过多的嵌套 if。

我建议:

  1. 拆分您的代码为更小的部分
  2. 记录您的代码
  3. 尝试使用有意义的名称

当然我不明白你的方法和变量的作用,但我试图创建一个虚构的例子,说明重组后的文档代码可能是什么样子:

import java.util.Arrays;
import java.util.Optional;

public class Snippet {

    /** The total number of all files, that were inspected */
    private int totalFileCount;

    /** The number of files that have been modified in any kind of way */
    private int updatedFileCount;

    /** The number of files, that were put into batch processing */
    private int totalBatchCount;

    /** The number of files, that have successfully been processed by the batch */
    private int updatedBatchCount;

    /** inspects all files, processes them, if required */
    private void processFiles(Parameters params, Iterable<Identity> fileIdentities) {
        for (Identity fileIdentity : fileIdentities)
            processFile(params, fileIdentity);
    }

    /** inspects a single file, processes it, if required */
    private void processFile(Parameters params, Identity fileIdentity) {
        totalFileCount++;
        if (forceTheStatus(params, fileIdentity))
            updateFile(params, fileIdentity);
    }

    /** updates the file, and - if necessary - updates the linked entity */
    private void updateFile(Parameters params, Identity fileIdentity) {
        updatedFileCount++;
        if (params.shouldUpdateLinkedEntity())
            updateLinkedEntity(params, fileIdentity);
    }

    /** puts the linked entity into the batch processing queue (if any exists) */
    private void updateLinkedEntity(Parameters params, Identity fileIdentity) {
        Optional<Identity> batchIdentity = getLinkedBatchIdentity(fileIdentity);
        if (batchIdentity.isPresent())
            batchUpdateLinkedEntity(params, batchIdentity);
    }

    /**
      * puts the linked entity into the batch processing queue
      * and uses the remittance processor
      */
    private void batchUpdateLinkedEntity(Parameters params, Optional<Identity> batchIdentity) {
        totalBatchCount++;
        if (getRemittanceProcessor().forceTheStatus(params, batchIdentity.get()))
            updatedBatchCount++;
    }

    // Dummy implementations to make the code compilable

    public static class Parameters {
        public boolean shouldUpdateLinkedEntity() {
            return false;
        }
    }

    public static class Identity {
    }

    public static void main(String[] args) {
        Iterable<Identity> fileIdentities = Arrays.asList(new Identity());
        new Snippet().processFiles(new Parameters(), fileIdentities);
    }

    private Snippet getRemittanceProcessor() {
        return null;
    }

    private Optional<Identity> getLinkedBatchIdentity(Identity fileIdentity) {
        return null;
    }

    private boolean forceTheStatus(Object params, Identity fileIdentity) {
        return false;
    }
}

【讨论】:

  • 这个解决方案没问题,我也喜欢它,但是,我的同事说它引入了很多代码,导致可读性降低......
  • 我不明白“继续”有什么不好。我看到的唯一问题是缺少“{”、“}”。
  • 我个人不喜欢方法的深度,它会失控。方法调用不应超过 depth=3。
【解决方案2】:

我投票支持继续。但也许你可以将状态映射到一个枚举,然后使用 switch/case?

【讨论】:

  • 在我的情况下,很难将状态映射到枚举...我也认为这样的更改会导致可读性降低。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-12
  • 2021-09-04
  • 1970-01-01
相关资源
最近更新 更多