Подтвердить что ты не робот

Как избежать дублирования сложных блоков catch

У меня есть этот код:

try {
    do_stuff();
    return do_more_stuff();
} catch (UnsupportedEncodingException e) {
    throw CustomException.programmer_error(e);
} catch (ProtocolException e) {
    throw CustomException.programmer_error(e);
} catch (MalformedURLException e) {
    throw CustomException.programmer_error(e);
} catch (SocketTimeoutException e) {
    throw new CustomException(e);
} catch (IOException e) {
    throw CustomException.unexpected_error(e);
}

Теперь мне нужно иметь все эти блоки catch в другой подобной функции. Каков наилучший способ избежать дублирования здесь?

Обратите внимание, что код внутри двух блоков try не очень похож.

Также я не могу поставить набор уловов выше.

Заметьте, я бы предпочел избежать:

try {
    do_stuff();
    return do_more_stuff();
} catch (Exception e) {
    handle_exception_via_rtti(e);
}
4b9b3361

Ответ 1

Лично я попытаюсь сделать

do_stuff();
return do_more_stuff();

соответствуют более общему формату, чтобы применить Стратегию (как шаблон).

Затем вы можете реорганизовать все места, где вы называете этот блок, чтобы они могли вызвать более обобщенный блок (где уловы выложены только один раз).

Ответ 2

Заметьте, я бы предпочел избежать:

Затем либо просто живите с ним, либо дождитесь, пока JDK7 будет поставляться с Multicatch, чтобы вы могли переписать как:

try {
    do_stuff();
    return do_more_stuff();
} catch (UnsupportedEncodingException | ProtocolException | MalformedURLException e) {
    throw CustomException.programmer_error(e);
} catch (SocketTimeoutException e) {
    throw new CustomException(e);
} catch (IOException e) {
    throw CustomException.unexpected_error(e);
}

Вы также можете переместить это в конструктор CustomException и сделать (неприятный) глобальный catch, но тогда вам нужно будет добавить кучу (противный) if/else блоков, чтобы определить тип исключения причина. Все со всеми, я просто предпочел бы придерживаться того, как вы это делали.

Обновить. Другой альтернативой является разделение/рефакторинг строк, которые потенциально могут генерировать исключение в виде отдельных задач в другой метод, блокирующий throw CustomException. Например.

try {
    do_stuff_with_encoding();
    do_stuff_with_url();
    do_stuff_with_ws();
    // ...
    return do_more_stuff();
} catch (SocketTimeoutException e) {
    throw new CustomException(e);
} catch (IOException e) {
    throw CustomException.unexpected_error(e);
}

...

public SomeObject do_stuff_with_encoding() throws CustomException {
    try {
        do_stuff();
    } catch (UnsupportedEncodingException e) {
        throw CustomException.programmer_error(e);
    }
}  

public SomeObject do_stuff_with_url() throws CustomException {
    try {
        do_stuff();
    } catch (MalformedURLException e) {
        throw CustomException.programmer_error(e);
    }
}  

public SomeObject do_stuff_with_ws() throws CustomException {
    try {
        do_stuff();
    } catch (ProtocolException e) {
        throw CustomException.programmer_error(e);
    }
}  

Ответ 3

Это зависит от того, почему do_stuff и do_more_stuff выбрасывают отмеченные исключения. Они делают это, чтобы заставить пользователя обрабатывать исключение? Если да, то вы пытаетесь избежать:

try {
    do_stuff();
    return do_more_stuff();
} catch (Exception e) {
    handle_exception_via_rtti(e);
}

- хорошая вещь.

Если ваш код просто ловит Exception, а do_stuff и do_more_stuff позже добавляют дополнительные исключения, вы, вероятно, никогда не узнаете об изменениях и о том, что ваш код теперь может быть неправильным.

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

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

Ответ 4

Как ввести общий класс Action, который может быть подклассифицирован:

public class Action {
    public void runWithHandlers() throws Exception {
        try {
           run();
        } catch (UnsupportedEncodingException e) {
            throw CustomException.programmer_error(e);
        } catch (ProtocolException e) {
            throw CustomException.programmer_error(e);
        } catch (MalformedURLException e) {
            throw CustomException.programmer_error(e);
        } catch (SocketTimeoutException e) {
            throw new CustomException(e);
        } catch (IOException e) {
            throw CustomException.unexpected_error(e);
        }
    }
    public void run() throws Exception {
        // TODO subclasses of Action must implement this
    }
}

Затем где-то еще в вашем коде вы создаете экземпляр одного из подклассов Action и вызываете runWithHandlers():

new MyAction().runWithHandlers();