Как избежать дублирования сложных блоков catch - PullRequest
18 голосов
/ 16 февраля 2010

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

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);
}

Ответы [ 5 ]

7 голосов
/ 16 февраля 2010

Лично я бы попробовал сделать

do_stuff();
return do_more_stuff();

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

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

5 голосов
/ 16 февраля 2010

Обратите внимание, я бы предпочел избегать:

Тогда либо просто живите с этим, либо подождите, пока 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 и сделать (неприятный) глобальный улов, но затем вам нужно будет добавить кучу (неприятных) блоков if/else, чтобы определить тип исключения причина. В общем, я бы предпочел придерживаться того же пути, что и вы.

Обновление : другой альтернативой является разделение / рефакторинг строк, которые потенциально могут генерировать исключение как отдельные задачи в блоки другого метода, бросая 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);
    }
}  
2 голосов
/ 16 февраля 2010

Зависит от того, почему 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 позже добавляют дополнительные исключения, вы, вероятно, никогда не узнаете об изменении и о том, что ваш код теперь может быть неправильным.

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

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

1 голос
/ 16 февраля 2010

Как насчет введения общего класса 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();
0 голосов
/ 16 февраля 2010

Если вы можете позволить себе Scala, проверьте это: вы можете сопоставить шаблон с исключением в блоке catch. См. Scala для Java-беженцев. Часть 4. Сопоставление с образцом и исключения .

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