java - 使用哪种设计模式来避免验证类中的 if/else?

标签 java design-patterns hibernate-validator spring-validator

我目前正在使用 HibernateConstraintValidator 来实现我的验证。但我的审阅者不同意在代码中使用 if/else 或!运营商。我可以使用哪种设计模式来删除验证逻辑中的 if/else?

public class SomeValidatorX implements ConstraintValidator<SomeAnnotation, UUID> {

      @Autowired
      SomeRepository someRepository;
   
      @Override
      public boolean isValid(UUID uuid, ConstraintValidationContext context) {

             return !(uuid!=null && someRepository.existsById(uuid)); //The reviewer doesn't want this negation operator
      }
}

在下面的代码中,他不需要 if/else

public class SomeValidatorY implements ConstraintValidator<SomeAnnotation, SomeClass> {

      @Autowired
      SomeRepository someRepository;
   
      @Override
      public boolean isValid(SomeClass someObject, ConstraintValidationContext context) {
           if(someObject.getFieldA() != null) { //He doesn't want this if statement
                //do some operations
                List<Something> someList = someRepository.findByAAndB(someObject.getFieldA(),B);
                return !someList.isEmpty(); //He doesn't want this ! operator
           }
           return false; // He was not fine with else statement in here as well
      }
}

旁注:我们必须使用领域驱动设计(如果有帮助的话)

最佳答案

很久以前,在太初。有一项准则规定方法应该只有一个导出点。为了实现这一点,开发人员必须跟踪本地状态并使用 if/else 才能到达方法的末尾。

今天我们知道得更多了。通过尽早退出方法,在阅读代码时更容易将整个流程保留在我们的脑海中。更简单的代码意味着更少的错误。错误越少,错误就越少。

在我看来,这就是审阅者不喜欢该代码的原因。它并不像想象的那么容易阅读。

让我们看第一个例子:

 public boolean isValid(UUID uuid, ConstraintValidationContext context) {

         return !(uuid!=null && someRepository.existsById(uuid)); //The reviewer doesn't want this negation operator
  }

代码说的是“不是这个:(uuid 不应该为空并且必须存在)”。是不是很容易理解呢?我认为不是。

替代方案:“如果 uuid 不存在也没关系,但如果存在,该项目可能不存在”。

或者在代码中:

if (uuid == null) return true;
return !someRepository.existsById(uuid);

更容易阅读,对吧? (我希望我的意图是正确的;))

第二个例子

      if(someObject.getFieldA() != null) { //He doesn't want this if statement
            //do some operations
            List<Something> someList = someRepository.findByAAndB(someObject.getFieldA(),B);
            return !someList.isEmpty(); //He doesn't want this ! operator
       }
       return false; // He was not fine with else statement in here as well

好的。你在这里说的是:

  • 如果字段 A 不为空:
    • 构建一个包含 A 和 b 的列表
    • 如果该列表不为空则失败,否则成功。
  • 否则失败

得出这一结论的更简单方法是简单地说:

  • 字段A不指定也可以
  • 如果指定了字段 A,则它必须与 B 组合存在。

翻译成代码:

if (someObject.getFieldA() == null) 
    return true;

return !someRepository.findByAAndB(someObject.getFieldA(),B).isEmpty();

在 C# 中,我们有 Any() ,它与 isEmpty 相反,在这种情况下我更喜欢它,因为它删除了否定。

有时需要否定。在存储库中编写新方法来避免它是没有意义的。但是,如果仅使用 findByAAndB,我会将其重命名为 ensureCombination(a,b),以便它可以针对有效情况返回 true。

尝试一边说话一边编写代码,这样在脑海中创建代码的图像会更容易。你不会说“我还没吃饱,我们去吃午饭吧”,是吗? ;)

关于java - 使用哪种设计模式来避免验证类中的 if/else?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64980788/

相关文章:

java - 将列表作为值插入映射中

java - 尝试使用 Jsoup 从 Web 抓取动态数据到 Android 应用程序,但没有获取准确的数据

php - 库类或模型类?

java - 不兼容的类更改错误: Implementing class

java - Spring MVC 3 验证 - 找不到默认提供程序

java - 公共(public)与私有(private)

java - Libgdx FileHandle读写多行

design-patterns - Event sourcing, CQRS with Axon Server/Framework - Event Sourcing the entire application 是个好主意吗?

ruby - Sinatra API 功能切换

javax.validation.NotBlank 缺少 validator