자바의 메소드에서 상태 플래그 및 메시지를 반환하는 가장 좋은 방법

StackOverflow https://stackoverflow.com/questions/356248

  •  21-08-2019
  •  | 
  •  

문제

기만적으로 간단한 시나리오가 있고 간단한 솔루션을 원하지만 "가장 정확한"또는 "대부분의 Java"는 분명하지 않습니다.

일부 클래스에는 작은 인증 (클라이언트 클라이언트) 메소드가 있다고 가정 해 봅시다. 인증은 여러 가지 이유로 실패 할 수 있으며 제어 흐름을 위해 간단한 부울을 반환하고 사용자에게 문자열 메시지를 반환하고 싶습니다. 이것들은 내가 생각할 수있는 가능성입니다.

  • 부울을 반환하고 StringBuilder를 통과하여 메시지를 수집하십시오. 이것은 C 스타일의 작업 방식에 가장 가깝습니다.
  • 거짓을 반환하는 대신 예외를 던지고 메시지를 포함하십시오. 실패는 예외적이지 않기 때문에 이것을 좋아하지 않습니다.
  • 부울과 문자열로 AuthenticaticStatus라는 새 클래스를 만듭니다. 이것은 하나의 작은 방법에 대한 과잉처럼 보입니다.
  • 회원 변수에 메시지를 저장하십시오. 이것은 잠재적 인 인종 조건을 도입 할 것이며, 나는 그것이 실제로 존재하지 않는 일부 상태를 암시한다는 것을 좋아하지 않습니다.

다른 제안이 있습니까?

편집하다 이 옵션을 놓쳤다

  • 성공을 위해 Null을 반환합니다 - 이것이 안전하지 않습니까?

편집하다 해결책:

나는 가장 OO 솔루션을 위해 갔고 작은 AuthenticationResult 클래스를 만들었습니다. 나는 다른 언어로는 이것을하지 않을 것이지만, 나는 Java에서 그것을 좋아합니다. 나는 또한 널 리턴과 같지만 더 안전하기 때문에 문자열을 반환한다는 제안을 좋아했습니다. 결과 클래스의 장점 중 하나는 필요한 경우 자세한 내용이있는 성공 메시지를 가질 수 있다는 것입니다.

도움이 되었습니까?

해결책

부울 깃발과 내부의 줄을 가진 작은 물체를 반환하는 것은 아마도 가장 oo와 같은 방법 일 것입니다.

또 다른 대안은 항상 문자열을 반환하고 NULL (또는 빈 문자열 - 선택)이 성공을 나타내는 것입니다. Javadocs에서 반환 값이 명확하게 설명되는 한 혼란이 없어야합니다.

다른 팁

예외를 사용할 수 있습니다 ....

try {
    AuthenticateMethod();
} catch (AuthenticateError ae) {         
    // Display ae.getMessage() to user..
    System.out.println(ae.getMessage());
    //ae.printStackTrace();    
}

그런 다음 AuthenticAtemethod에서 오류가 발생하면 새 AuthenticateError를 보냅니다 (Extences Exception).

"센티넬 값", 특히 NULL을 반환하지 마십시오. 구현을 읽지 않고 발신자가 메소드를 이해할 수없는 코드베이스로 끝납니다. NULL의 경우, 발신자는 메소드가 NULL을 반환 할 수 있다는 것을 잊거나 모르는 경우 NULLPOONETEREXCEPTIONS로 끝날 수 있습니다.

Bas Leijdekkers의 튜플 제안은 방법에서 둘 이상의 값을 반환하려면 항상 사용하는 좋은 제안입니다. 우리가 사용하는 것은입니다 P2<A, B> ~로부터 기능적 자바 도서관. 이러한 종류의 유형은 두 가지 다른 유형의 공동 결합입니다 (각 유형의 하나의 값이 포함되어 있음).

제어 흐름에 대한 예외를 던지는 것은 약간의 코드 냄새이지만, 점검 된 예외는 방법에서 하나 이상의 값을 얻는 방법 중 하나입니다. 다른 더 깨끗한 가능성이 존재합니다.

  1. 당신은 가질 수 있습니다 Option<T> 두 개의 서브 클래스가있는 초록 클래스 Some<T> 그리고 None<T>. 이것은 NULL에 대한 유형-안전한 대안과 비슷하며 부분 함수 (일부 인수에 대해 정의되지 않은 함수)를 구현하는 좋은 방법입니다. 그만큼 기능적 자바 도서관에는 완전한 기능이 있습니다 Option 구현하는 수업 Iterable<T>, 당신은 다음과 같은 일을 할 수 있습니다.

    public Option<String> authenticate(String arg) {
       if (success(arg))
          return Option.some("Just an example");
       else
          return Option.none();
    }
    
    ...
    
    for(String s : authenticate(secret)) {
       privilegedMethod();
    }
    
  2. 또는 두 가지 유형의 분리 연합을 사용할 수 있습니다. Either<L, R> 수업. 유형 중 하나 인 하나의 값이 포함되어 있습니다 L 또는 R. 이 수업은 구현됩니다 Iterable<T> 모두 L 그리고 R, 당신은 다음과 같은 일을 할 수 있습니다.

    public Either<Fail, String> authenticate(String arg) {
       if (success(arg))
          return Either.right("Just an example");
       else
          return Either.left(Fail.authenticationFailure());
    }
    
    ...
    
    Either<Fail, String> auth = authenticate(secret);
    for(String s : auth.rightProjection()) {
       privilegedMethod();
    }
    for(Fail f : auth.leftProjection()) {
       System.out.println("FAIL");
    }
    

이 모든 수업, P2, Option, 그리고 Either 다양한 상황에서 유용합니다.

더 많은 옵션 :

  • 각 유형의 실패에 대해 별도의 열거 값을 반환하십시오. 열거적인 물체에는 메시지가 포함될 수 있습니다
  • int를 반환하고 배열에서 적절한 메시지를 찾는 별도의 메소드가 있습니다.
  • 두 값을 포함 할 수있는 일반적인 유틸리티 튜플 클래스를 만듭니다. 이러한 수업은 더 많은 곳에서 유용 할 수 있습니다.

간단한 튜플 예, 실제 구현에는 더 많은 것이 필요할 수 있습니다.

class Tuple<L, R> {

    public final L left;
    public final R right;

    public Tuple( L left, R right) {
        this.left = left;
        this.right = right;
    }
}

문제가 없음을 나타내는 오류 메시지 모음을 반환 할 수 있습니다. 이것은 세 번째 제안의 개선입니다.

나는 개인적으로 부울으로 AuthenticationStatus라는 새로운 클래스를 만드는 것이 가장 자바와 같은 방식이라고 생각합니다. 그리고 그것은 과잉처럼 보이지만 (잘 될 수 있습니다) 그것은 나에게 더 깨끗하고 이해하기 쉬운 것처럼 보입니다.

실패한 인증이 평범하다고해서 예외적이지 않다는 의미는 아닙니다.

제 생각에는 인증 실패가 포스터-자식 확인 된 예외에 대한 사용 사례. (글쎄 ... 아마도 존재하지 않는 파일은 표준 사용 사례이지만 인증 실패는 가까운 #2입니다.)

나는 "작은 클래스"를 직접 사용하고 보통 내부 수업을 사용합니다. 나는 인수를 사용하여 메시지를 수집하는 것을 좋아하지 않습니다.

또한 앱 서버 나 데이터베이스 계층에서 나오는 것처럼 실패 할 수있는 메소드가 "낮은 레벨"인 경우 리턴 상태가있는 열거를 반환 한 다음 GUI 레벨의 문자열로 변환하는 것이 좋습니다. 코드를 국제화하려는 경우 사용자 문자열을 낮은 수준으로 전달하지 마십시오. 앱 서버는 다른 언어로 다른 클라이언트를 사용하지 않고 한 번에 한 언어로만 응답 할 수 있기 때문입니다.

이것이 당신이 그러한 요구 사항이있는 유일한 방법입니까? 그렇지 않은 경우, issuccessful 플래그와 메시지 문자열로 일반 응답 클래스를 생성하고 어디에서나 사용하십시오.

또는 메소드가 NULL을 반환하여 성공을 보여줄 수 있습니다 (예쁘지 않으며 성공과 메시지를 반환 할 수 없습니다).

나는 아마도 아마도 다음과 같은 것을 갈 것입니다.


class SomeClass {
public int authenticate (Client client) {
//returns 0 if success otherwise one value per possible failure
}
public String getAuthenticationResultMessage (int authenticateResult) {}
//returns message associated to authenticateResult
}

이 "디자인"을 사용하면 인증이 실패 할 때만 메시지를 요청할 수 있습니다 (99,99%의 시간이 발생하는 시나리오가되기를 바랍니다.)))).

메시지 해결을 다른 클래스에 위임하는 것도 좋은 관행 일 수도 있습니다. 그러나 응용 프로그램 요구에 따라 다릅니다 (대부분 i18n이 필요합니까?)

이것은 다른 프로그래밍 언어에서 일반적인 관용구처럼 보이지만 어느 것이 어느 쪽을 찾을 수는 없습니다 (내가 질문에서 읽은 것처럼 추측).

거의 같은 질문이 게시됩니다 여기 그리고 여기

단일 함수에서 두 값을 반환하려고 시도하는 것은 오해의 소지가있을 수 있습니다. 그러나 그렇게하려는 시도로 입증되었으므로 매우 유용 할 수 있습니다.

이전에 게시 된대로 앱의 일반적인 흐름이라면 결과로 확실히 생성하고 작은 클래스가 진행할 수있는 올바른 방법이어야합니다.

다음은 함수에서 두 값을 반환하는 것에 대한 인용문입니다.

프로그래밍 스타일의 문제로,이 아이디어는 객체 지향 프로그래밍 언어로 매력적이지 않습니다. 계산 결과를 나타내는 객체를 반환하는 것은 다음과 같습니다 그만큼 여러 값을 반환하기위한 관용구. 일부는 관련없는 값에 대해 클래스를 선언 할 필요가 없지만 단일 방법에서 관련없는 값을 반환해서는 안된다고 제안합니다.

Java가 허용하는 기능 요청에서 찾았습니다. 다중 반환 값

"평가"섹션을보십시오 : 2005-05-06 09:40:08

성공적인 인증은 "정상적인"사례이어야하므로 인증 실패가 예외적 인 경우입니다.

어쨌든 사용자의 다른 상태 문자열은 무엇입니까? 나는 두 개의 성공 또는 실패 만 볼 수 있습니다. 추가 정보는 잠재적 인 보안 문제입니다. 예외가있는 솔루션의 또 다른 장점은 잘못된 방식으로 호출 할 수없고 실패 사례가 더 분명하다는 것입니다. 예외없이, 당신은 다음을 씁니다.

if (authenticate()) {
  // normal behaviour...
}
else {
  // error case...
}

실수로 반환 값을 무시하는 메소드를 호출 할 수 있습니다. 그런 다음 "정상 행동"코드는 성공적인 인증없이 실행됩니다.

authenticate();
// normal behaviour...

예외를 사용하는 경우 발생할 수 없습니다. 예외를 사용하지 않기로 결정한 경우, 적어도 메소드의 이름을 지정하여 상태를 반환한다는 것이 명확합니다.

if (isAuthenticated()) {
//...
}

여기에는 좋은 답변이 많이 있으므로 짧게 유지하겠습니다.

사용자를 인증하지 못하는 것은 점검 된 예외에 대한 유효한 사례로 간주 될 수 있다고 생각합니다. 귀하의 프로그래밍 스타일이 예외를 선호하는 경우이를 수행하지 않을 이유가 없습니다. 또한 "메소드에서 여러 값을 반환하는 방법을 제거하고 내 메소드는 사용자를 인증하는 한 가지를 수행합니다".

여러 값을 반환하려면 10 분 동안 일반 쌍을 만드는 데 10 분을 소비합니다 (또한 쌍 삼중 여가 이상일 수도 있고 위에 나열된 예제를 반복하지 않음). 나는 작은 DTO 스타일 객체를 갖는 것이 싫어 다양한 여러 값을 반환합니다.

문자열을 반환하는 것은 어떻습니까. 성공을 위해 비어 있거나 null. 실패의 경우 오류 메시지. 효과가 더 간단합니다. 그러나 그것이 잘 읽는지 확실하지 않습니다.

물체를 반환하십시오. 필요하면 추가 기능을 수업에 넣을 수 있습니다. Java의 짧은 살아있는 물건은 신속하게 만들고 수집 할 수 있습니다.

먼저 예외 옵션을 선택합니다.

그러나 두 번째로, 나는 C 스타일 기술을 선호합니다.

public boolean authenticate(Client client, final StringBuilder sb) {
    if (sb == null)
        throw new IllegalArgumentException();
    if (isOK()) {
        sb.append("info message");
        return true;
    } else {
        sb.append("error message");
        return false;
    }
}

이것은 그렇게 이상하지 않으며 프레임 워크의 많은 곳에서 이루어집니다.

리턴 유형에 대한 특수 객체를 만드는 대신 일반적으로 반환 된 모든 정보가 저장된 배열을 반환합니다. 이점은 새로운 유형과 혼란을 만들지 않고 새로운 요소 로이 배열을 확장 할 수 있다는 것입니다. 배열이 특정 메소드에서 반환 될 때 어떤 요소가 제시 해야하는지 정확히 알아야합니다. 일반적으로 나는 특정 구조에 동의합니다. 첫 번째 요소는 항상 부울 표시 성공, 두 번째는 설명이있는 문자열이고 나머지는 선택 사항입니다. 예시:

public static void main(String[] args)
{
    Object[] result = methodReturningStatus();
    if(!(Boolean)result[0])
        System.out.println("Method return: "+ result[1]);
}

static Object[] methodReturningStatus()
{
    Object[] result = new Object[2];

    result[0] = false;
    result[1] = "Error happened";

    return result;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top