[java] Java의 True-way 솔루션 : 2 개 문자열에서 2 개의 숫자를 구문 분석 한 다음 합계를 반환합니다.

아주 어리석은 질문입니다. 주어진 코드 :

public static int sum(String a, String b) /* throws? WHAT? */ {
  int x = Integer.parseInt(a); // throws NumberFormatException
  int y = Integer.parseInt(b); // throws NumberFormatException
  return x + y;
}

좋은 Java인지 아닌지 말할 수 있습니까? 내가 말하는 NumberFormatException것은 확인되지 않은 예외입니다. 당신은 없는 의 일부로 지정 sum()서명. 또한 내가 이해하는 한, 검사되지 않은 예외의 개념은 프로그램의 구현이 잘못되었음을 알리는 것이며, 더 나아가 검사되지 않은 예외를 포착하는 것은 런타임에 잘못된 프로그램을 수정하는 것과 같기 때문에 나쁜 생각 입니다.

누군가 다음 사항을 명확히 하시겠습니까?

  1. NumberFormatException메소드 서명의 일부로 지정해야합니다 .
  2. 확인 된 예외 ( BadDataException)를 정의 NumberFormatException하고 메서드 내부를 처리 한 다음 BadDataException.
  3. 내 자신의 확인 된 예외 ( BadDataException)를 정의하고 정규 표현식과 같은 방식으로 두 문자열의 유효성을 검사하고 BadDataException일치하지 않으면 내 던져야 합니다.
  4. 당신의 생각은?

업데이트 :

어떤 이유로 사용해야하는 오픈 소스 프레임 워크가 아니라고 상상해보십시오. 메소드의 서명을보고 “좋아, 절대 던지지 않는다”라고 생각합니다. 그런 다음 언젠가 예외가 발생했습니다. 정상인가요?

업데이트 2 :

sum(String, String)디자인이 나쁘다는 의견이 있습니다 . 나는 절대적으로 동의하지만 우리가 좋은 디자인을 가지고 있다면 원래의 문제가 결코 나타나지 않을 것이라고 믿는 사람들을 위해 여기에 추가 질문이 있습니다.

문제 정의는 다음과 같습니다. 숫자가 Strings 로 저장되는 데이터 소스가 있습니다 . 이 소스는 XML 파일, 웹 페이지, 2 개의 편집 상자가있는 데스크톱 창 등이 될 수 있습니다.

당신의 목표는이 2를 취하고이를 Strings로 변환하고 int“합이 xxx”라는 메시지 상자를 표시 하는 논리를 구현하는 것 입니다.

이것을 설계 / 구현하기 위해 사용하는 접근 방식이 무엇이든 상관없이 다음과 같은 두 가지 내부 기능이 있습니다 .

  1. 당신이 변환 장소 Stringint
  2. 2 int초 를 추가하는 장소

내 원래 게시물의 주요 질문은 다음과 같습니다.

Integer.parseInt()올바른 문자열이 전달 될 것으로 예상 합니다 . 잘못된 문자열 을 전달할 때마다 프로그램 이 잘못 되었음을 의미합니다 ( ” 사용자 가 바보입니다”가 아님). MUST 시맨틱 이있는 Integer.parseInt ()가 있고 다른 한편으로는 입력이 올바르지 않은 경우에 대해 확인해야하는 코드 조각을 구현 해야합니다 -SHOULD 시맨틱 .

그래서, 간단히 : 나는 구현 어떻게 SHOULD 의미를 난 단지 경우 MUST 라이브러리를 .



답변

이것은 좋은 질문입니다. 더 많은 사람들이 그런 생각을했으면 좋겠어요.

IMHO, 쓰레기 매개 변수를 전달받은 경우 확인되지 않은 예외를 던지는 것은 허용됩니다.

일반적으로 말하면 BadDataException예외를 사용하여 프로그램 흐름을 제어해서는 안되므로 던지지 않아야합니다. 예외는 예외입니다. 메서드 호출자 는 문자열이 숫자인지 아닌지 호출 하기 전에 알 수 있으므로 쓰레기 전달을 피할 수 있으므로 프로그래밍 오류 로 간주 될 수 있습니다. 즉, 확인되지 않은 예외를 throw해도 괜찮습니다.

선언과 관련하여 throws NumberFormatException-이것은 유용하지 않습니다. NumberFormatException이 선택 해제되어 있기 때문에 거의 알 수 없기 때문입니다. 그러나 IDE는이를 활용하고 try/catch올바르게 래핑 할 수 있습니다 . 좋은 옵션은 다음과 같이 javadoc도 사용하는 것입니다.

/**
 * Adds two string numbers
 * @param a
 * @param b
 * @return
 * @throws NumberFormatException if either of a or b is not an integer
 */
public static int sum(String a, String b) throws NumberFormatException {
    int x = Integer.parseInt(a);
    int y = Integer.parseInt(b);
    return x + y;
}

수정 됨 :
댓글 작성자가 유효한 점수를 얻었습니다. 이것이 어떻게 사용 될지와 앱의 전반적인 디자인을 고려해야합니다.

메서드가 모든 곳에서 사용되고 모든 호출자가 문제를 처리하는 것이 중요하다면 메서드는 확인 된 예외 (호출자가 문제를 처리하도록 강요)를 던지지 만 코드를 try/catch블록으로 복잡하게 만드는 것으로 선언합니다 .

반면에 우리가 신뢰하는 데이터에이 방법을 사용하는 경우, 폭발하지 않을 것으로 예상되고 본질적으로 불필요한 try/catch블록 의 코드 혼란을 피할 수 있으므로 위와 같이 선언하십시오 .


답변

제 생각에는 예외 논리를 가능한 한 많이 처리하는 것이 좋습니다. 따라서 나는 서명을 선호합니다

 public static int sum(int a, int b);

귀하의 메서드 서명으로 나는 아무것도 변경 하지 않을 것입니다. 당신은

  • 잘못된 값을 프로그래밍 방식으로 사용하여 대신 생산자 알고리즘의 유효성을 검사 할 수 있습니다.
  • 또는 예를 들어 사용자 입력에서 값을 전송합니다.이 경우 해당 모듈은 유효성 검사를 수행해야합니다.

따라서이 경우 예외 처리는 문서 문제가됩니다.


답변

번호 4. 주어진대로이 메소드는 정수를 가져야하는 매개 변수로 문자열을 가져서는 안됩니다. 어떤 경우 (자바가 오버플로 대신 래핑되기 때문에) 예외가 발생할 가능성이 없습니다.

 x = sum(Integer.parseInt(a), Integer.parseInt(b))

무엇을 의미하는지에 대해 훨씬 더 명확합니다.
x = sum(a, b)

가능한 한 소스 (입력)에 가깝게 예외가 발생하기를 원합니다.

옵션 1-3과 관련하여 호출자가 그렇지 않으면 코드가 실패 할 수 없다고 가정하기 때문에 예외를 정의하지 않습니다. 예외를 정의하여 방법에 고유 한 알려진 실패 조건에서 발생하는 일을 정의합니다. 즉, 다른 객체를 감싸는 래퍼 인 메서드가 있고 예외를 throw 한 다음 전달합니다. 예외가 메서드에 고유 한 경우에만 사용자 지정 예외를 throw해야합니다 (예에서 frex, 합계가 긍정적 인 결과 만 반환하도록되어있는 경우, 그 결과를 확인하고 예외를 던지는 것이 적절할 것입니다. 래핑하는 대신 오버플로 예외를 던지면 서명에 정의하거나 이름을 바꾸거나 먹지 않고이를 전달합니다.

질문 업데이트에 대한 응답으로 업데이트 :

간단히 말해서, MUST 라이브러리 만있는 경우 SHOULD 의미론을 어떻게 구현합니까?

이에 대한 해결책은 MUST 라이브러리를 래핑하고 SHOULD 값을 반환하는 것입니다. 이 경우 Integer를 반환하는 함수입니다. 문자열을 취하고 Integer 객체를 반환하는 함수를 작성하세요. 작동하거나 null을 반환합니다 (구아바의 Ints.tryParse처럼). 작업과 별도로 유효성 검사를 수행하십시오. 작업은 int를 취해야합니다. 잘못된 입력이있을 때 작업이 기본값으로 호출되는지 또는 다른 작업을 수행하는지 여부는 사양에 따라 달라집니다. 대부분의 경우 해당 결정을 내릴 장소가 작업에있을 가능성이 거의 없다는 것입니다. 방법.


답변

1. 메서드 서명의 일부로 NumberFormatException을 지정해야합니다.

나도 그렇게 생각해. 좋은 문서입니다.

2. 확인 된 예외 (BadDataException)를 정의하고 메서드 내에서 NumberFormatException을 처리 한 다음 BadDataException으로 다시 throw해야합니다.

어쩔 땐 그래. 확인 된 예외는 경우에 따라 더 나은 것으로 간주되지만 작업은 상당히 PITA입니다. 이것이 많은 프레임 워크 (예 : Hibernate)가 런타임 예외 만 사용하는 이유입니다.

3. 내 자신의 확인 된 예외 (BadDataException)를 정의하고 정규 표현식과 같은 방식으로 두 문자열의 유효성을 검사하고 일치하지 않으면 BadDataException을 throw해야합니다.

못. 더 많은 작업, 더 적은 속도 (예외가 규칙이 될 것으로 예상하지 않는 한), 전혀 이득이 없습니다.

4. 당신의 생각은?

전혀.


답변

Nr 4.

나는 방법을 전혀 바꾸지 않을 것이라고 생각합니다. 예외에서 비즈니스 논리를 사용하여 정상적으로 복구 할 수있는 컨텍스트에있는 스택 추적에서 호출 메서드 또는 그 이상을 시도해 보겠습니다.

나는 그것이 과잉이라고 생각하기 때문에 # 3을 확실하게하지 않을 것입니다.


답변

작성중인 내용이 다른 사람에 의해 소비 될 것이라고 가정하면 (예 : API로) 1로 이동해야합니다. NumberFormatException은 특히 그러한 예외를 전달하기위한 목적이며 사용해야합니다.


답변

  1. 먼저 자신에게 물어볼 필요가 있습니다. 제 방법의 사용자가 잘못된 데이터를 입력하는 것에 대해 걱정할 필요가 있는지, 아니면 적절한 데이터 (이 경우 문자열)를 입력해야하는지에 대해 걱정해야합니다. 이러한 기대는 계약에 의한 설계로도 알려져 있습니다.

  2. 그리고 3. 예, 아마도 BadDataException을 정의하거나 NumberFormatException과 같은 일부 예외를 사용하는 것이 좋지만 표준 메시지를 표시하도록 남겨 두는 것이 좋습니다. 메서드에서 NumberFormatException을 잡아서 원래 스택 추적을 포함하는 것을 잊지 않고 메시지와 함께 다시 던집니다.

  3. 상황에 따라 몇 가지 추가 정보와 함께 NumberFormatException을 다시 던질 수 있습니다. 또한 예상되는 값에 대한 javadoc 설명이 있어야합니다.String a, String b