避免复杂if-else分支的最佳方法-Java

避免复杂if-else分支的最佳方法-Java,java,if-statement,null,Java,If Statement,Null,我有一个RESTAPI,它使用几个参数(如requestparams)来搜索实体。此搜索可能有多种变体。以下方法在结尾处获取调用,以搜索具有给定参数的实体 public List<Person> searchPerson(final String name, final String city, final String state, final String code) { if( name != null && city != nu

我有一个RESTAPI,它使用几个参数(如requestparams)来搜索实体。此搜索可能有多种变体。以下方法在结尾处获取调用,以搜索具有给定参数的实体

public List<Person> searchPerson(final String name, 
           final String city, final String state, final String code) {
    if( name != null && city != null && state != null && code != null ){
        //Search person in database with above all parameters
        //personRepositoy is spring data repository. 
        personRepositoy.findByNameAndCityAndStateAndCode(name, city, state, code);
    } else if( city != null && state != null && code != null){
        personRepositoy.findByCityAndStateAndCode(name, city, state, code)
    }
}
public List searchPerson(最终字符串名,
最终字符串城市、最终字符串状态、最终字符串代码){
if(name!=null&&city!=null&&state!=null&&code!=null){
//使用以上所有参数在数据库中搜索人员
//personRepositoy是spring数据存储库。
personRepositoy.FindBynameandCity和dStateandCode(姓名、城市、州、代码);
}如果(城市!=null&&state!=null&&code!=null){
personRepositoy.FindBycityandStates和code(名称、城市、州、代码)
}
}

这里有没有一种方法可以避免复杂的(容易出错,不容易重构)分支?可能正在使用集合或函数式编程概念?我真的不喜欢编写这种分支代码(因为它们很难维护)

您可以为此创建自己的实用程序,如下所示:

public static boolean requireNonNull(Object... objects) {
    for(Object obj : objects) {
        if(obj == null) return false;
    }
    return true;
}
示例用法

public List<Person> searchPerson(final String name, final String city, 
                                 final String state, final String code) {
    if(MyUtilityClass.requireNonNull(name, city, state, code)) {
        //Search person in database with above all parameters
        //personRepositoy is spring data repository. 
        personRepositoy.findByNameAndCityAndStateAndCode(name, city, state, code);
    } else if(MyUtilityClass.requireNonNull(city, state, code)) {
        personRepositoy.findByCityAndStateAndCode(city, state, code)
    }
}
public List searchPerson(最终字符串名称、最终字符串城市、,
最终字符串状态,最终字符串代码){
if(MyUtilityClass.requireNonNull(名称、城市、州、代码)){
//使用以上所有参数在数据库中搜索人员
//personRepositoy是spring数据存储库。
personRepositoy.FindBynameandCity和dStateandCode(姓名、城市、州、代码);
}else if(MyUtilityClass.requireNonNull(城市、州、代码)){
personRepositoy.findByCityAndStateAndCode(城市、州、代码)
}
}

您可以为此创建自己的实用程序,如下所示:

public static boolean requireNonNull(Object... objects) {
    for(Object obj : objects) {
        if(obj == null) return false;
    }
    return true;
}
示例用法

public List<Person> searchPerson(final String name, final String city, 
                                 final String state, final String code) {
    if(MyUtilityClass.requireNonNull(name, city, state, code)) {
        //Search person in database with above all parameters
        //personRepositoy is spring data repository. 
        personRepositoy.findByNameAndCityAndStateAndCode(name, city, state, code);
    } else if(MyUtilityClass.requireNonNull(city, state, code)) {
        personRepositoy.findByCityAndStateAndCode(city, state, code)
    }
}
public List searchPerson(最终字符串名称、最终字符串城市、,
最终字符串状态,最终字符串代码){
if(MyUtilityClass.requireNonNull(名称、城市、州、代码)){
//使用以上所有参数在数据库中搜索人员
//personRepositoy是spring数据存储库。
personRepositoy.FindBynameandCity和dStateandCode(姓名、城市、州、代码);
}else if(MyUtilityClass.requireNonNull(城市、州、代码)){
personRepositoy.findByCityAndStateAndCode(城市、州、代码)
}
}

为清晰起见,请按以下代码编写

if(name!=null)
{
  if(city!=null)
  {
    if(state!=null
    {
      if(code!=null)
      { 
        // do search using all
        }
        //search using name , city , code
        }
         // search using name , city
         } 
         //search using name only
         }

为清楚起见,代码如下所示

if(name!=null)
{
  if(city!=null)
  {
    if(state!=null
    {
      if(code!=null)
      { 
        // do search using all
        }
        //search using name , city , code
        }
         // search using name , city
         } 
         //search using name only
         }

城市!=空和状态!=空和空代码!=null
可能保存在变量中

boolean cityStateCodeGiven = city != null && state != null && code != null;

if(name != null && cityStateCodeGiven) {
    // name, city, state, code are given
} else if (cityStateCodeGiven) {
    // city, state, code are given
}
您不需要重新检查某些条件两次或更多次

例如,
cityStateCodeGiven
可能被拆分为
cityStateGiven+codeGiven
<代码>名称!=null&&cityStateCodeGiven可以分组为
nameCityStateCodeGiven

变量的名称将告诉变量检查哪些条件


此外,您可以将这些声明放在方法的开头。它将给出一些关于您稍后将在代码中使用的方法的提示

boolean cityStateCodeGiven = city != null && state != null && code != null;
boolean nameCityStateCodeGiven = cityStateCodeGiven && name != null;

城市!=空和状态!=空和空代码!=null
可能保存在变量中

boolean cityStateCodeGiven = city != null && state != null && code != null;

if(name != null && cityStateCodeGiven) {
    // name, city, state, code are given
} else if (cityStateCodeGiven) {
    // city, state, code are given
}
您不需要重新检查某些条件两次或更多次

例如,
cityStateCodeGiven
可能被拆分为
cityStateGiven+codeGiven
<代码>名称!=null&&cityStateCodeGiven可以分组为
nameCityStateCodeGiven

变量的名称将告诉变量检查哪些条件


此外,您可以将这些声明放在方法的开头。它将给出一些关于您稍后将在代码中使用的方法的提示

boolean cityStateCodeGiven = city != null && state != null && code != null;
boolean nameCityStateCodeGiven = cityStateCodeGiven && name != null;

如果不知道不同的检查是如何相互作用的,就很难判断

无论如何,以下文章为您提供了5种不同的解决方案(模式),以使if-else条件更具可读性:


希望您可以在代码中使用其中的一个检查。

如果不知道不同的检查是如何相互作用的,就很难判断

无论如何,以下文章为您提供了5种不同的解决方案(模式),以使if-else条件更具可读性:


希望您可以在代码中使用其中一个。我建议您更广泛地研究这个问题。我可以期待以下事情:

  • 您已经有4个不同的搜索属性来搜索一个人
  • 我可以期待你在未来有更多的搜索字段和更多不同的组合
  • 因此,我提议将所有这些字段组合成特殊对象
    SearchPersonRequest

    然后,您有了这个对象,它可能有一个特殊的行为,比如为搜索引擎创建搜索请求,即
    SpringData
    。当您有多个字段用于使用多个组合进行搜索时,使用
    JpaSpecificationExecutor
    非常灵活

    这是我的主要观点。作为一个例子,我给出了我的第一种方法(您可以看到
    Lombok
    annotations,它只是为了简化代码;不需要使用它):

    SearchPersonRequest

    @Builder
    public class SearchPersonRequest {
    
        private String name;
        private String city;
        private String state;
        private String code;
    
        public Specification<Person> createSpecification() {
            List<Specification<Person>> specifications = getSpecifications();
            Specifications<Person> spec = null;
    
            if (!specifications.isEmpty()) {
                Iterator<Specification<Person>> it = specifications.iterator();
                spec = where(it.next());
    
                while (it.hasNext()) {
                    spec = spec.and(it.next());
                }
            }
    
            return spec;
        }
    
        private List<Specification<Person>> getSpecifications() {
            return Arrays.stream(Field.values())
                         .filter(field -> field.isExists(this))
                         .map(field -> (Specification<Person>)(root, query, builder) -> builder.equal(root.get(field.id), field.get.apply(this)))
                         .collect(Collectors.toList());
        }
    
        @RequiredArgsConstructor(access = AccessLevel.PACKAGE)
        private enum Field {
            NAME("name", request -> request.name),
            CITY("city", request -> request.city),
            STATE("state", request -> request.state),
            CODE("code", request -> request.code);
    
            private final String id;
            private final Function<SearchPersonRequest, String> get;
    
            private boolean isExists(SearchPersonRequest request) {
                return StringUtils.isNotBlank(get.apply(request));
            }
        }
    
    }
    
    @Builder
    公共类SearchPersonRequest{
    私有字符串名称;
    私人城市;
    私有字符串状态;
    私有字符串码;
    公共规范createSpecification(){
    列表规格=getSpecifications();
    规格规格=空;
    如果(!specifications.isEmpty()){
    迭代器it=规范。迭代器();
    spec=where(it.next());
    while(it.hasNext()){
    spec=spec.and(it.next());
    }
    }
    返回规格;
    }
    私有列表getSpecifications(){
    返回Arrays.stream(Field.values())
    .filter(字段->字段.isExists(此))
    .map(field->(规范)(root、query、builder)->builder.equal(root.get(field.id)、field.get.apply(this)))
    .收集(