IT박스

Java에서 메소드 당 큰 try-catch를 사용하는 것이 알려진 좋은 방법입니까?

itboxs 2020. 12. 24. 23:27
반응형

Java에서 메소드 당 큰 try-catch를 사용하는 것이 알려진 좋은 방법입니까?


최근에 인터뷰를했는데 면접관이 제 지식을보기 위해 기술 테스트를 해달라고 요청했습니다. 내가 그 일을 마친 후 그는 내가 어떻게했는지에 대한 피드백을 주었는데, 내가 기대하지 않았고 고맙게 생각했다. 당신을 고용하고 싶지 않은 면접관이 거의 ​​없기 때문이다.

그가 내 코드에 대해 좋지 않다고 말한 것 중 하나는 내가 작성한 각 메소드 내에서 하나 이상의 try-catch 블록을 사용했다는 것입니다. 흥미로워 서 내 관심을 불러 일으킨다.

나는 잡히기 위해 필요한 예외를 던질 수있는 하나 이상의 메소드를 가진 의미 상 구별 가능한 코드 블록이있는 곳에 try-catch 블록을 만들어야한다고 생각합니다. 내가 따랐던 유일한 예외는 두 메서드가 동일한 예외 유형을 throw하는 경우 다른 try-catch 블록에 배치하여 예외가 throw 된 위치와 이유를 명확하게 구분할 수 있다는 것입니다.

이것은 면접관이 저에게 원했던 것과는 크게 다릅니다. 그렇다면 메서드 당 하나의 try-catch 블록 만 사용하는 것이 알려진 모범 사례입니까? 알려진 모범 사례 인 경우이를 수행하면 어떤 이점이 있습니까?

편집 : 이것에 대한 귀하의 생각에 크게 감사드립니다. 이것은 매우 좋습니다. 그것이 알려진 좋은 관행인지 묻고 있음을 유의하십시오. 이것은 대부분의 프로그래머가 이것에 동의하고 어떤 책에 좋은 관행으로 쓰여진 경우입니다.


나를 위해 두 개의 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 );
}

'Clean Code'의 Robert C. Martin은 다음과 같이 제안합니다.

키워드 'try'가 함수에 존재하는 경우, 함수의 맨 처음 단어 여야하며 catch / finally 블록 뒤에는 아무것도 없어야합니다.

두 개의 개별 try / catch 블록을 사용하여 메서드를 더 작은 메서드로 리팩터링 할 것입니다.


두 개의 개별 코드 블록을 래핑하는 경우 try/catch해당 블록을 별도의 메서드로 리팩토링하는 것을 고려해야합니다. 이것이 면접에서 사용한 패턴이라면 면접관을 오해했을 것입니다.

try/catch알고리즘에 필요한 경우 두 개의 블록 을 사용 하는 것이 좋습니다. 나는 종종 try/catch안전한 정리를 위해 catch 블록에서 새로운 것을 사용 하여 포괄적 인 진술이 불가능합니다.


귀하의 질문에 답하기 위해 실제로 코드에 많은 최적화를 적용하는 현대 JVM에 대해 이야기 할 때 비효율적 인 코드를 작성하면 JVM이 자동으로 최적화를 도입합니다.

( Java : "try-catch"블록을 입력 / 사용하는 오버 헤드? ) 의 답변을 참조하십시오 .

따라서 모범 사례는 그다지 중요하지 않습니다.

개인적으로, 나는 그 하나에서해야 캡슐화하지 아무것도 생각 try-catch, static, synchronized등 블록 해제 필요.

이 작업을 수행 할 사람들이 코드를 더 읽기 쉽게 만들도록합시다. 예외가 잡히면 어떤 코드에서 예외가 발생하는지 명시 적으로 눈에 띄게 만드는 것이 좋습니다.

독자가 추측 할 필요가 없기 때문에 JVM이 스마트하고, 원하는대로 작성하고, 인간에게 더 좋게 만들고, JVM이 최적화 부분을 처리합니다.

편집 : 나는 많은 책을 읽었으며 하나의 큰 시도가 여러 개의 작은 것보다 낫다는 것을 말하는 곳을 찾지 못했습니다.

또한 개발자 커뮤니티의 많은 사람들은 그 반대를 믿습니다.


나는 catch 블록에서 중복을 피하려고합니다. 메서드의 모든 예외가 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);
}

(이 코드는 순전히 예외 포착에 대한이 요점을 설명하기 위해 존재합니다. 다른 방식으로는 완전히 끔찍하다는 사실을 무시해 주시기 바랍니다)


As for me, it's clearer to have just one try-catch block wrapping all the 'hazardous' code in a method. Regarding who to blame when two lines throw the same exception, you'll always have the stacktrace.

Besides, having more than one try-catch inside a method usually means having more than one return lines (which can also make hard to follow code execution at a sight), as chances are that if something goes wrong in the first try-catch, it won't make sense to keep running the rest of the code.

Here you can find some 'standard' best practices, just in case you may find them useful.-

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


This is another thing that often starts Java-flamewar... ;-)

Basically, for the performance matters only throwing exceptions. So using few try-catch blocks shouldn't affect a performance at all. In some opinion writing code that way obfuscates the code and does not even recall "clean code", in others opinion it's better to use try only for lines which can actually throw any exception.

It's up to you decide (or the team convention).


It's also important to consider the context of the code. If you're writing code with heavy IO then you may need to know which parts of the code are failing. I didn't see anywhere yet a point that try...catch is meant to give you a chance to recover from a problem.

So if you get an IO exception in reading from one file, you may want to retry reading. Same with writing. But if you had one large try...catch you wouldn't know which to retry.

ReferenceURL : https://stackoverflow.com/questions/18784549/is-it-a-known-good-practice-to-use-a-big-try-catch-per-method-in-java

반응형