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

Является ли хорошей практикой использовать большой метод try-catch для каждого метода в java?

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

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

Я считаю, что в настоящий момент я должен создать блоки try-catch, где есть семантически различимый блок кода, который имеет один или несколько методов, которые могут генерировать исключения, которые необходимо поймать. Единственным исключением из этого, что я последовал, было то, что если два метода используют один и тот же тип исключения, я бы лучше поместил их в разные блоки try-catch, чтобы четко различать, когда отладка где и почему было выбрано исключение.

Это сильно отличается от того, что хотел сделать интервьюер. Таким образом, используется только один блок try-catch для каждого метода - известная хорошая практика? Если это хорошая практика, каковы преимущества этого?

EDIT: Я очень ценю ваши мысли по этому поводу, это очень хорошо. Хотя обратите внимание, что я спрашиваю, является ли это известной хорошей практикой. Это, если большинство программистов согласятся на это, и это написано как хорошая практика в какой-то книге

4b9b3361

Ответ 1

Для меня два блока try-catch делают большинство методов слишком длинными. Он запутывает намерение, если метод делает много вещей.

С двумя блоками try-catch он делает по крайней мере четыре вещи, если быть точным

  • два случая для основного потока (два блока try)
  • два случая для обработки ошибок (блоки блокировки)

Я предпочел бы сделать короткие и понятные методы из каждого блока try-catch

private getHostNameFromConfigFile(String configFile, String defaultHostName) {
    try {
        BufferedReader reader = new BufferedReader(new FileReader(configFile));
        return reader.readLine();
    } catch (IOException e) {
        return defaultHostName;
    }
}
public Collection<String> readServerHostnames(File mainServerConfigFile, File  backupServerConfigFile) {
    String mainServerHostname=getHostNameFromConfigFile(mainServerConfigFile,"default- server.example.org");
    String backupServerHostName=getHostNameFromConfigFile(backupServerConfigFile,"default- server.example.ru")
    return Arrays.asList(mainServerHostname,backupServerHostName );
}

Роберт К. Мартин в "Чистом коде" выводит его на следующий уровень, предлагая:

если ключевое слово "try" существует в функции, оно должно быть самым первым словом в функции и что после блоков catch/finally ничего не должно быть.

Я бы определенно реорганизовал метод с двумя отдельными блоками try/catch на более мелкие методы.

Ответ 2

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

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

Ответ 3

Чтобы ответить на ваш вопрос, когда мы говорим о современных JVM, которые на самом деле применяют много оптимизаций в коде, когда вы пишете какой-то код, который неэффективен, JVM автоматически вводит оптимизацию.

Пожалуйста, ответьте на ответ в (Java: накладные расходы на ввод/использование блоков "try-catch" ?).

Поэтому хорошая практика не имеет большого значения.

В личном примечании я считаю, что не нужно инкапсулировать что-либо в try-catch, static, synchronized и т.д. блоки необязательно.

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

Отсутствие угадывания для читателя, поэтому JVM являются умными, пишут по вашему желанию, делают их лучше для людей, а JVM заботится о части оптимизации.

РЕДАКТИРОВАТЬ: Я прочитал много книг, и я не нашел ни одного места, в котором говорится, что одна большая попытка поймать лучше, чем несколько небольших.

Кроме того, многие в сообществе разработчиков считают, что наоборот.

Ответ 4

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

Например, здесь мы можем объединить все исключения, потому что любое исключение означает, что весь метод не выполняется:

public PasswordAuthentication readAuthenticationDetails(File authenticationFile) {
    try {
        BufferedReader reader = new BufferedReader(new FileReader(authenticationFile));
        String username = reader.readLine();
        String password = reader.readLine();
        return new PasswordAuthentication(username, password.toCharArray());
    } catch (IOException e) {
        return null;
    }
}

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

public Collection<String> readServerHostnames(File mainServerConfigFile, File backupServerConfigFile) {
    String mainServerHostname;
    try {
        BufferedReader reader = new BufferedReader(new FileReader(mainServerConfigFile));
        mainServerHostname = reader.readLine();
    } catch (IOException e) {
        mainServerHostname = "default-server.example.org";
    }

    String backupServerHostname;
    try {
        BufferedReader reader = new BufferedReader(new FileReader(backupServerConfigFile));
        backupServerHostname = reader.readLine();
    } catch (IOException e) {
        backupServerHostname = "default-server.example.ru";
    }

    return Arrays.asList(mainServerHostname, backupServerHostname);
}

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

Ответ 5

Что касается меня, то яснее будет иметь только один блок try-catch, который обертывает весь "опасный" код в методе. Что касается того, кто виноват, когда две линии бросают одно и то же исключение, у вас всегда будет стек.

Кроме того, наличие более одного try-catch внутри метода обычно означает наличие более чем одной строки return (что также может затруднить выполнение кода при просмотре), так как есть вероятность, что если что-то пойдет не так в сначала try-catch, не будет смысла продолжать работу с остальной частью кода.

Здесь вы можете найти некоторые "стандартные" лучшие практики, на случай, если вы найдете их полезными.

http://howtodoinjava.com/2013/04/04/java-exception-handling-best-practices/

Ответ 6

Также важно рассмотреть контекст кода. Если вы пишете код с тяжелым IO, вам может понадобиться знать, какие части кода терпят неудачу. Я еще нигде не видел точки, которые пытаются... catch предназначен для того, чтобы дать вам возможность оправиться от проблемы.

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

Ответ 7

Это еще одна вещь, которая часто запускает Java-flamewar...; -)

В принципе, для производительности важно исключать только исключения. Поэтому использование нескольких блоков try-catch не должно влиять на производительность вообще. В некотором мнении писать код таким образом запутывает код и даже не вспоминает "чистый код", в других случаях лучше использовать try только для строк, которые могут фактически вызывать любое исключение.

Это вам решать (или соглашение команды).