Пример рефакторинга лесенки операторов IF в коде подготовки и выполнения запроса


Исходный код

public String find(String request) {
    String result="";
    status.setState(Status.STATUS_IN_PROGRESS);
    status.setMessage("search start");   
    buildTokens(request);
    if (buildWords()) {
        if (buildSynonyms()) {
            if (buildValues()) {
                if (buildProperties()) {
                    if (buildParameters()) {
                        result = buildCondition();
                        status.setParameters(newArrayList(parameters));
                        status.setState(Status.STATUS_SUCCESS);
                        status.setMessage("search done successfully");
                    } else {
                        status.setState(Status.STATUS_FAIL);
                        status.setMessage("can't build parameters");
                    }
                } else {
                    status.setState(Status.STATUS_FAIL);
                    status.setMessage("can't build properties");
                }
            } else {
                status.setState(Status.STATUS_FAIL);
                status.setMessage("can't build values");
            }
        } else {
            status.setState(Status.STATUS_FAIL);
            status.setMessage("can't build synonyms");
        }
    } else {
        status.setState(Status.STATUS_FAIL);
        status.setMessage("can't build words");
    }
    return result;
}

Как можно отрефакторить исходный код

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

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

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

public String find(String request) {
    String result="";
    status.setInProgress("search start");   

    buildTokens(request);
    if (!buildWords()) {
        status.setFail("can't build words");
        return result;
    }
    if (!buildSynonyms()) {
        status.setMessage("can't build synonyms");
        return result;
    }
    if (!buildValues()) {
        status.setMessage("can't build values");
        return result;
    }
    if (!buildProperties()) {
        status.setMessage("can't build properties");
        return result;
    }
    if (!buildParameters()) {
        status.setMessage("can't build parameters");
        return result;
    }

    result = buildCondition();
    status.setParameters(newArrayList(parameters));
    status.setSuccess("search done successfully");

    return result;
}

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

Этот рефакторинг касается только лесенки операторов if, однако же здесь больше сомнений вызывает выбранный способ обработки ошибок.

Я бы всё-таки посмотрел в сторону исключений, и бросать их должны сами методы buildWordsbuildSynonyms и т.д.