【问题标题】:Java8 splitting long interface method into separate methodsJava8将长接口方法拆分为单独的方法
【发布时间】:2020-12-27 10:04:16
【问题描述】:

我在接口中有以下默认方法,由于许多 if-else 条件,它似乎相当复杂。

       default void validate() {
         Application application = application().get();
            if (StringUtils.isEmpty(application.name()) || application.data() == null) {
               throw new IllegalArgumentException());
            } else {
               for (Form form : application.data().forms) {
                   if (StringUtils.isEmpty(form.getId())) {
                        throw new IllegalArgumentException();
                   }
                     for (Question question : form.getQuestions()) {
                         if (StringUtils.isEmpty(question.getQuestion())
                            || StringUtils.isEmpty(question.getValue())) {
                               throw new IllegalArgumentException();
                         }
                      }
                }
            }
        }

我想将其拆分为不同的方法以降低复杂性。但是,由于项目配置为使用 Java8,因此无法在接口中使用私有方法。我还能如何分解它并降低复杂性?任何建议将不胜感激。

【问题讨论】:

  • default void validate() {Application application = application().get(); if (application.name().isEmpty() || application.data() == null) throw new IllegalArgumentException(); List<Form> forms = application.data().forms(); if (forms.stream().anyMatch(form -> Objects.isNull(form.getId()))) throw new IllegalArgumentException(); if (forms.stream().flatMap(form -> form.getQuestions().stream()) .anyMatch(question -> question.getQuestion().isEmpty() || question.getValue().isEmpty())) throw new IllegalArgumentException(); }

标签: if-statement java-8 interface refactoring access-modifiers


【解决方案1】:

为了重构更好的可读性并降低 validate 方法的复杂性,我将应用 Extract Method 重构。但根据可用的 Java 版本,默认接口方法有不同的选项。

Java 8Java 9 中有不同的选项。在这两种情况下,您当然可以提取方法来抽象需要由实现类实现的接口方法。但我想你也想在你的接口中保留提取的类的默认实现代码。所以我不会在这里讨论这个选项。

Java 8

如果您受限于 Java 8,您可以 - 除了已经提到的公共抽象方法 - 将方法提取为其他 公共默认值 接口的方法或 public static 方法。

这是一个简单的重构方法,用于将方法提取到公共默认接口方法中:

public interface ApplicationValidatorJava8WithDefaults {
    default void validate() {
        Application application = application().get();
        validateApplication(application);
        for (Form form : application.data().forms) {
            validateForm(form);
        }
    }

    default void validateApplication(Application application) {
        if (StringUtils.isEmpty(application.name()) || application.data() == null) {
            throw new IllegalArgumentException();
        }
    }

    default void validateForm(Form form) {
        if (StringUtils.isEmpty(form.getId())) {
            throw new IllegalArgumentException();
        }
        for (Question question : form.getQuestions()) {
            validateQuestion(question);
        }
    }

    default void validateQuestion(Question question) {
        if (StringUtils.isEmpty(question.getQuestion())
                || StringUtils.isEmpty(question.getValue())) {
            throw new IllegalArgumentException();
        }
    }

    Application application();
}

现在将方法提取到 public static 接口方法中也是如此:

public interface ApplicationValidatorJava8WithStatics {
    default void validate() {
        Application application = application().get();
        validateApplication(application);
        for (Form form : application.data().forms) {
            validateForm(form);
        }
    }

    static void validateApplication(Application application) {
        if (StringUtils.isEmpty(application.name()) || application.data() == null) {
            throw new IllegalArgumentException();
        }
    }

    static void validateForm(Form form) {
        if (StringUtils.isEmpty(form.getId())) {
            throw new IllegalArgumentException();
        }
        for (Question question : form.getQuestions()) {
            validateQuestion(question);
        }
    }

    static void validateQuestion(Question question) {
        if (StringUtils.isEmpty(question.getQuestion())
                || StringUtils.isEmpty(question.getValue())) {
            throw new IllegalArgumentException();
        }
    }

    Application application();
}

Java 9

如果您可以使用 Java 9,您可以 - 除了所有已经提到的选项方法 - 将方法提取为 私有实例 方法或接口的私有静态方法。

这是一个简单的重构方法,用于将方法提取到私有实例接口方法中:

public interface ApplicationValidatorJava9WithPrivateInstanceMethods {
    default void validate() {
        Application application = application().get();
        validateApplication(application);
        for (Form form : application.data().forms) {
            validateForm(form);
        }
    }

    private void validateApplication(Application application) {
        if (StringUtils.isEmpty(application.name()) || application.data() == null) {
            throw new IllegalArgumentException();
        }
    }

    private void validateForm(Form form) {
        if (StringUtils.isEmpty(form.getId())) {
            throw new IllegalArgumentException();
        }
        for (Question question : form.getQuestions()) {
            validateQuestion(question);
        }
    }

    private void validateQuestion(Question question) {
        if (StringUtils.isEmpty(question.getQuestion())
                || StringUtils.isEmpty(question.getValue())) {
            throw new IllegalArgumentException();
        }
    }

    Application application();
}

现在将方法提取到私有静态接口方法中也是如此:

public interface ApplicationValidatorJava9WithPrivateStaticMethods {
    default void validate() {
        Application application = application().get();
        validateApplication(application);
        for (Form form : application.data().forms) {
            validateForm(form);
        }
    }

    private static void validateApplication(Application application) {
        if (StringUtils.isEmpty(application.name()) || application.data() == null) {
            throw new IllegalArgumentException();
        }
    }

    private static void validateForm(Form form) {
        if (StringUtils.isEmpty(form.getId())) {
            throw new IllegalArgumentException();
        }
        for (Question question : form.getQuestions()) {
            validateQuestion(question);
        }
    }

    private static void validateQuestion(Question question) {
        if (StringUtils.isEmpty(question.getQuestion())
                || StringUtils.isEmpty(question.getValue())) {
            throw new IllegalArgumentException();
        }
    }

    Application application();
}

注意:我还删除了第一个 else 分支,因为它在第一个 if 子句中引发异常后已过时。好的 IDE(例如 IntelliJ)已经会通知您并使用单个命令将其删除。这已经提高了复杂性,因为方法的整体嵌套已经减少了一级。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-04
    • 1970-01-01
    • 1970-01-01
    • 2016-09-06
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    相关资源
    最近更新 更多