[英]Best way to avoid complicated if else branching - Java
我有rest API,它使用幾個參數(作為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 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)
}
}
city != null && state != null && code != 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
。 name != null && cityStateCodeGiven
可以分組為nameCityStateCodeGiven
。
變量的名稱將告訴變量檢查哪些條件。
此外,您可以將這些聲明放在方法的開頭。 它將為您稍后在代碼中使用的方法提供一些提示。
boolean cityStateCodeGiven = city != null && state != null && code != null;
boolean nameCityStateCodeGiven = cityStateCodeGiven && name != null;
為清楚起見,代碼如下
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
}
在不知道不同支票如何相互作用的情況下,很難說出來。
無論如何,下面的文章為您提供5種不同的解決方案(模式),以使if-else條件更易讀: Anti-If:缺少的模式
希望您可以在代碼中使用其中之一。
我提議更廣泛地研究這個問題。 我可以期待以下事情:
因此,我提供將所有這些字段組合到特殊對象SearchPersonRequest
。
然后,您有了這個對象,它可能會有特殊的行為, 例如為搜索引擎創建搜索請求,即SpringData
。 當您有多個文件要使用多個組合進行搜索時,使用JpaSpecificationExecutor
會非常靈活。
這是我的重點。 舉例來說,我為您提供了這方面的第一種方法(您會看到Lombok
批注,它只是為了簡化代碼;不需要使用它):
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));
}
}
}
人控者
@RestController
@RequiredArgsConstructor
public class PersonController {
private final PersonService personService;
public List<Person> searchPerson(@RequestParam String name,
@RequestParam String city,
@RequestParam String state,
@RequestParam String code) {
SearchPersonRequest searchPersonRequest = SearchPersonRequest.builder()
.name(name)
.city(city)
.state(state)
.code(code)
.build();
return searchPerson(searchPersonRequest);
}
public List<Person> searchPerson(@RequestBody SearchPersonRequest searchPersonRequest) {
return personService.searchPerson(searchPersonRequest);
}
}
人員服務
@Service
@RequiredArgsConstructor
public class PersonService {
private final PersonRepository personRepository;
public List<Person> searchPerson(SearchPersonRequest searchPersonRequest) {
Specification<Person> spec = searchPersonRequest.createSpecification();
return spec != null ? personRepository.findAll(spec) : Collections.emptyList();
}
}
人員資料庫
public interface PersonRepository extends JpaSpecificationExecutor<Person> {
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.