【问题标题】:Is there a way to simplify a code with a repeating if-then pattern?有没有办法用重复的 if-then 模式来简化代码?
【发布时间】:2021-04-13 02:18:34
【问题描述】:

我已经使用 Spring Boot 创建了一个基本的 CRUD API,因为我已经为我的控制器创建了一个服务类。

以下是我的Controller的服务方法。

服务

public Customer updateCustomer(Customer newCustomer, Long customerId) throws ResourceNotFoundException {
        
        return customerRepo.findById(customerId)
                .map(customer -> {
                    if (newCustomer.getName() != null)
                        customer.setName(newCustomer.getName());
                    if (newCustomer.getGstin() != null)
                        customer.setGstin(newCustomer.getGstin());
                    if (newCustomer.getPhoneNumber() != null)
                        customer.setPhoneNumber(newCustomer.getPhoneNumber());
                    if (newCustomer.getAddress() != null)
                        customer.setAddress(newCustomer.getAddress());
                    if (newCustomer.getOutstandingBalance() != 0.0f)
                        customer.setOutstandingBalance(newCustomer.getOutstandingBalance());
                    return customerRepo.save(customer);
                }).orElseThrow(() -> new ResourceNotFoundException());

    }

我的问题是:是否可以简化使用多个 if 的代码?

如果有,任何人都可以建议简化处理这个逻辑..??

【问题讨论】:

  • 如果您关心不覆盖已设置的属性,请使用if。我可以将已经为空的属性设置为空,删除ifs
  • 就 Java 代码而言,没有其他结构可以更好地执行这种检查和设置的逻辑顺序。
  • 你可以使用 Optional.of(newCustomer.getName).ifPresent(String s -> customer.setName(s)) 这样的东西,这样你就可以避免这一切,并且代码更清晰.

标签: java spring-boot


【解决方案1】:

不是,我建议发送客户的前端/客户端作为完整客户发送,而您的方法只是保存。

您使用的那个可以正常工作,但不建议使用多个 if 语句,即使 IDE 至少给出警告也是一个好的 ide 应该的。

【讨论】:

  • 这个问题是以固执的方式提出的。我已经编辑了它,所以它现在更加客观。提问者想知道是否可以简化代码,以避免重复 if-then 模式。当您说这不是最好的方法时,您是对的,但从认识论上讲,您只有知道更好的方法才能知道这一点。但是,您的答案不包含替代方法。我建议使用反射。如果一个方法正在实现该模式,获取 customer 和 newCustomer 以及一个名称数组,则可以用于简化。
  • 因为在这种情况下,您只能传递一些参数并让逻辑在幕后展开。比我们在问题中看到的模式重复要好得多。简而言之,我同意你的看法,但除非你也提供解决方案,否则我无法支持你的答案。
【解决方案2】:

是的,有这样的简化。使用reflection,您可以调用类/实例的方法。假设您有一个以String[]为参数的方法,包含"Name"之类的值,您可以迭代该数组并调用newCustomer的getter,将其与null进行比较,如果它不为null,则可以调用@ 987654326@的setter,传递刚刚调用的getter的结果。

更多信息请看这篇文章:https://www.baeldung.com/java-method-reflection

【讨论】:

  • 在这里使用反射会使代码变得狂野。如果 OP 在其 bean 类中有超过 5 个属性,并且并非所有属性都应该被检查和复制怎么办?
  • @fluffy 确实,该项目可能存在多个问题。但是,操作员询问了一个单一模式,这个答案旨在解决这个问题。我建议将此答案中表示的想法用于问题中提出的问题,对于与问题中提出的问题非常不同的问题,我建议不要坚持此答案。
【解决方案3】:

另一种方法可能看起来像这样。

如果 Java 支持语言内的宏,我会很高兴,这样这些模式就可以封装在宏调用中,然后扩展为生成的源代码。没有宏,都可以放入方法中并在运行时执行检查复制模式:

public final class Patch {

    private Patch() {
    }

    public static <T> void nonNull(final Supplier<? extends T> get, final Consumer<? super T> set) {
        @Nullable
        final T value = get.get();
        if ( value != null ) {
            set.accept(value);
        }
    }

    public static void nonZero(final DoubleSupplier get, final DoubleConsumer set) {
        final double value = get.getAsDouble();
        if ( value != 0 ) {
            set.accept(value);
        }
    }

}

测试:

@Data
@AllArgsConstructor
final class Customer {

    private final String name;
    private String phoneNumber;
    private float outstandingBalance;

}

还有测试:

@Test
public void test() {
    final Customer customer = new Customer(null, "+123", 2);
    final Customer newCustomer = new Customer("john-doe", null, 0);
    Patch.nonNull(customer::getName, newCustomer::setName);
    Patch.nonNull(customer::getPhoneNumber, newCustomer::setPhoneNumber);
    Patch.nonZero(customer::getOutstandingBalance, value -> newCustomer.setOutstandingBalance((float) value));
    Assertions.assertEquals(new Customer("john-doe", "+123", 2), newCustomer);
}

请注意,像 Lombok 这样的工具在编译时生成 Java 代码,但作为 javac 插件(请参阅 @DataAllArgsConstructor 注释)是自己生成代码的黑盒子(@987654329 @、hashCode()toString()get***()set***() 方法 + 分别为 Customer 的全参数构造函数)仅限于它们当前的功能(+ 需要 IDE 支持才能使其看起来更好)。

如果您更喜欢(可能)具有更高运行时成本的 Java 反射,请查看似乎在运行时完成这项工作的 Apache Commons BeanUtils:Helper in order to copy non null properties from object to another


顺便说一句,不要对outstandingBalance 使用float -- 使用BigDecimal 或任何精确的东西。 Why not use Double or Float to represent currency?

【讨论】:

    猜你喜欢
    • 2020-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-16
    • 2019-04-03
    • 1970-01-01
    相关资源
    最近更新 更多