Оптимизация нескольких условий if-else в Java - PullRequest
0 голосов
/ 13 июня 2018

У меня есть REST API, который будет предоставлять результаты поиска на основе определенных критериев поиска.Пользователь может выполнять поиск, используя идентификатор отдела, идентификатор пользователя и дату регистрации.Таким образом, здесь пользователь может искать в 7 различных комбинациях.

  1. Поиск только по идентификатору Dept
  2. Поиск только по идентификатору пользователя
  3. Поиск только по дате регистрации
  4. Поиск по идентификатору отдела и идентификатору пользователя
  5. Поиск по идентификатору пользователя и дате регистрации
  6. Поиск по идентификатору отдела и дате регистрации
  7. Поиск будет выполнен по всем 3 критериям (идентификатор отдела, Идентификатор пользователя и Дата регистрации)

В соответствии с текущим дизайном нашего приложения, Для каждого критерия мне придется вызывать различные службы в разном порядке для получения информации.

Например: У нас естьсуществующая служба пользователя, в которой есть данные пользователя, служба отдела, в которой есть данные.Так что, если пользователь ищет только идентификатор пользователя, я бы сразу перейти к UserService.Если пользователь выполняет поиск с идентификатором Dept ID & User, мне сначала нужно будет запросить службу Dept, а затем службу User.

Мой текущий код:

if(Util.hasOnlyUserId(searchCriteria)) {
        searchResponse = searchWithUserId(searchRequest);
    } else if(Util.hasOnlyJoinedDate(searchCriteria)) {
        searchResponse = searchWithDate(searchRequest);
    } else if (Util.hasOnlyDeptID(searchCriteria)) {
        searchResponse = searchWithDeptId(searchRequest);
    } else if (Util.hasUserIdAndDeptId(searchCriteria)) {
        searchResponse = searchWithUserIdAndDeptId(searchRequest);
    } else if (Util.hasUserIdAndDate(searchCriteria)){
        searchResponse = searchWithUserIdAndDate(searchRequest);
    } else if (Util.hasDeptIdAndDate(searchCriteria)) {
        searchResponse = searchWithDeptIdAndDate(searchRequest);
    } else if (Util.hasAllCriteria(searchCriteria)) {
        searchResponse = searchWithAllCriteria(searchRequest);
    }

Здесь searchCriteria является моим объектом запроса (POJO), который имеет эти элементы поиска как частные члены.

searchResponse здесь - это тип объекта SearchResponse, который является фактическим ответом API, и он содержит такие детали пользователя, как name, id, position, lastSalaryDrawn, CommuteType,MaritalStatus и дата последнего продвижения

Я пытался оптимизировать это множественное условие if-else, другими словами, чтобы избежать этого множественного условия.Я попытался отделить каждого из них и поместить их в разные методы.Но это просто не удовлетворяет меня, и кажется, что оно находится в неоптимизируемом состоянии.

Буду очень признателен за любые идеи о том, как я могу это сделать.

Редактировать:Мы используем JPA для взаимодействия с MySQL.Проблема здесь в том, что я не получу информацию прямым способом из БД.Поэтому построение динамического запроса может не сработать.Информация должна быть получена из нескольких микросервисов, которые, в свою очередь, сделают вызов своей собственной БД и отправят необходимую информацию в ответ.Я надеюсь, что это имеет смысл.

Ответы [ 3 ]

0 голосов
/ 13 июня 2018

Здесь можно использовать различные шаблоны, и вы должны выбрать один из них в зависимости от того, как выглядит код поиска.Некоторые люди уже упоминали о стратегиях и цепочках ответственности.Другой пример, который вы можете посмотреть - это шаблон Builder .Это позволяет вам иметь необязательные детали, которые указываются только при необходимости, для построения конечного объекта.

Таким образом, у вас может быть класс SearchBuilder, который обновляет информацию о поиске по мере добавления дополнительных критериев фильтрации.У него могут быть такие методы, как setUserId(...), setDeptId(...) и т. Д.

Например: если поиск переводился в простой SQL-запрос в PreparedStatement, то, когда установлено одно из полей фильтрации,строитель будет хранить их (они будут начинаться как null).Так что если бы в вашем компоновщике вы вызывали setUserId () и setDeptId (), они не были бы null внутри компоновщика, и вы генерируете запрос со строкой (добавляя AND ... для каждого дополнительного поля, с которым вы хотите фильтровать):select * from users where id=? AND dept_id=?

SearchBuilder может предложить метод build(), который затем возвращает объект Search, который несет запрос и, возможно, даже предлагает метод, который выполняет запрос, или все, что вам нужно сделать.

0 голосов
/ 13 июня 2018

Вы можете переместить код в место, где выполняются критерии, и динамически построить запрос:

public SearchResponse searchWithCriteria(Criteria searchCriteria) {
    StringBuilder query = new StringBuilder("SELECT * FROM ... WHERE ...");
    if (util.hasUserId(searchCriteria))
        query.append(" AND userId = :userId");
    if (util.hasJoinedDate(searchCriteria))
        query.append(" AND joinedDate = :joinedDate");
    ...
    PreparedStatement stmt = connection.prepareStatement(query);
    if (util.hasUserId(searchCriteria))
        stmt.setString("userId", searchCriteria.getUserId());
    if (util.hasJoinedDate(searchCriteria))
        stmt.setDate("joinedDate", searchCriteria.getJoinedDate());
    ...
    ResultSet res = stmt.executeQuery();
    ...
}
0 голосов
/ 13 июня 2018

Код можно оптимизировать с помощью Шаблон стратегии .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...