Чистый код — поиск конечной точки с помощью одного или нескольких фильтров с определенными правилами: Как избежать множества «если»?

#java #spring #performance #if-statement #coding-style

#java #весна #Производительность #if-statement #стиль кодирования

Вопрос:

если вы разрабатывали конечную точку поиска, которая может иметь один или несколько фильтров, и существуют определенные правила для объединения этих фильтров, как избежать использования нескольких «если»?

 private void addCriteria(ProductFilter filter, Query query) {
//user does not fill anything, throws exception

        if (ObjectUtils.isEmpty(filter.getIds()) amp;amp; !validateComboFilters(filter)) {
            throw new RequiredFilterException();
        }

//user does not fill id filter but fills other filters

        if (ObjectUtils.isEmpty(filter.getIds()) amp;amp; validateComboFilters(filter)) {

            query.addCriteria(Criteria.where(Constants.CREATED_AT)
                    .gte(filter.getFromDate())
                    .lte(filter.getToDate()));

            query.addCriteria(Criteria.where(Constants.STATUS).in(filter.getStatus()));
        }

//user fills id filter and one or more other filters

        if (ObjectUtils.isNotEmpty(filter.getIds())) {

            query.addCriteria(Criteria.where(Constants.ID)
                    .is(filter.getIds()));

            if (filter.filterByRangeDate()) {
                query.addCriteria(Criteria.where(Constants.CREATED_AT)
                        .gte(filter.getFromDate())
                        .lte(filter.getToDate()));
            }
            if (filter.filterByStatus()) {
                query.addCriteria(Criteria.where(Constants.STATUS).in(filter.getStatus()));
            }
        }
    }
 

Ответ №1:

Это может выглядеть так. Я не проверял это для компиляции, но я думаю, что общий подход более или менее правильный.

 private static final BiFunction<ProductFilter, Query, Boolean> ADD_CRITERIA_IDS = (filter, query) -> {
    boolean res = ObjectUtils.isNotEmpty(filter.getIds());
    if (res)
        query.addCriteria(Criteria.where(Constants.ID).is(filter.getIds()));
    return res;
};

private static final BiFunction<ProductFilter, Query, Boolean> ADD_CRITERIA_STATUS = (filter, query) -> {
    boolean res = filter.filterByStatus();
    if (res)
        query.addCriteria(Criteria.where(Constants.STATUS).in(filter.getStatus()));
    return res;
};

private static final BiFunction<ProductFilter, Query, Boolean> ADD_CRITERIA_DATE_RANGE = (filter, query) -> {
    boolean res = filter.filterByRangeDate();
    if (res)
        query.addCriteria(Criteria.where(Constants.CREATED_AT)
                                  .gte(filter.getFromDate())
                                  .lte(filter.getToDate()));
    return res;
};

private void addCriteria(ProductFilter filter, Query query) {
    boolean added = ADD_CRITERIA_IDS.apply(filter, query);
    added |= ADD_CRITERIA_STATUS.apply(filter, query);
    added |= ADD_CRITERIA_DATE_RANGE.apply(filter, query);

    if (!added)
        throw new RequiredFilterException();
}