작업을 수행하고 부울을 상태로 반환하는 메서드 이름을 지정하는 방법은 무엇입니까?


33

방법이 있다면

bool DoStuff() {
    try {
        // doing stuff...
        return true;
    }
    catch (SomeSpecificException ex) {
        return false;
    }
}

오히려 호출해야 IsStuffDone()합니까?

사용자가 두 이름을 모두 잘못 해석 할 수 있습니다. 이름이 DoStuff()부울 인 이유는 무엇입니까? 이름이 IsStuffDone()확실하지 않은 경우, 메소드가 태스크를 수행하는지 또는 결과 만 확인하는지 명확하지 않습니다.

이 사건에 대한 협약이 있습니까? 또는 이것이 결함으로 간주되는 대체 접근법입니까? 예를 들어, C #과 같은 출력 매개 변수가있는 언어에서 부울 상태 변수는 메소드에 전달 될 수 있으며 메소드의 리턴 유형은입니다 void.

편집 : 내 특정 문제에서 메서드는 인터페이스 구현의 일부이기 때문에 예외 처리를 호출자에게 직접 위임 할 수 없습니다. 따라서 호출자는 다른 구현의 모든 예외를 처리해야 할 책임이 없습니다. 이러한 예외에는 익숙하지 않습니다. 그러나 호출자는 npinti의 answer and commentStuffHasNotBeenDoneForSomeReasonException 에서 제안한 것처럼 사용자 정의 예외를 처리 할 수 ​​있습니다 .


2
기능의 사용법과 수행중인 작업에 따라 다릅니다. 필요한 경우 물건을 올바르게 실행 해야하는 경우 함수의 사용자가 부울 플래그를 놓칠 수 있으며 예외에서 제공 한 정보가 없기 때문에이 접근법에 결함이 있다고 생각합니다.
Benni

7
대부분의 경우 boolean예외를 줄 바꿈하거나 전달 하는 대신 반환하는 것이 거의 항상 잘못되었으므로 "파손"이라고 부릅니다 .
maaartinus

2
이런 종류의 예외 처리기는 거의 좋은 생각이 아닙니다. 예상하지 못한 특정 예외 만 포착하십시오. 그리고 가능하면 처음에는 던지지 마십시오. 잡을 필요가 없습니다.
코드 InChaos

2
음 ... BadlyDesignedMethodInSeriousNeedOfRefactoring? 그리고 예외에 대한 귀하의 질문에 대답하기 위해-발신자가 예외를 처리하게하거나 잡은 다음 "이 방법은 그 일을 수행하지 않습니다"를 의미하는 사용자 정의 예외를 던지겠습니다. 공유하고 즐기십시오.
밥 자비스-복원 모니카

5
말하는 모든 사람들에게 : 예외를 던지거나 통과시키기 만하면,이 코드가 어떻게 사용되는지에 대한 근거없는 가정을하고 있습니다. 가능한 시나리오 중 하나는 비용이 증가함에 따라 더 큰 하위 클래스를 해결하는 다양한 휴리스틱 솔루션 방법으로 해결해야 할 문제가 있다는 것입니다. 와 같은 것을 쓰는 것이 합리적 if (FirstMethodSucceeds(problem) or SecondMethodSucceeds(problem) or ...) Hurray(); else UniversalSolve(problem);입니다. (사용자 정의?) 예외와 동일하게 수행하는 것은 쓸모 없게 복잡 할 것입니다.
Marc van Leeuwen 2016 년

답변:


68

.NET에는 종종 메소드 중 하나가 예외 ( DoStuff)를 발생 시키고 다른 메소드가 부울 상태를 리턴하고 실행에 성공하면 out 매개 변수 ( TryDoStuff) 를 통한 실제 결과를 리턴하는 메소드 쌍이 있습니다 .

(마이크로 소프트 의 가장 대표적인 예 는 다양한 프리미티브 유형 의 메소드 이기 때문에 Microsoft는 이것을 "Try-Parse Pattern" 이라고 부릅니다 TryParse.)

Try사용하는 언어에서 접두사가 드문 경우에는 사용하지 않아야합니다.


3
+1 이것이 내가 다른 곳에서 이런 종류의 일을 본 모습입니다. if (TryDoStuff()) print("Did stuff"); else print("Could not do stuff");제 생각에는 꽤 표준적이고 직관적 인 관용구입니다.
Karl Nicoll

12
또한 주목해야한다 TryDoStuff방법이 완전히 실패하고 거짓 복귀시에는 부작용이없는 것으로 가정한다.
트릴리언

참고로 Remove.NET 프레임 워크에는 예를 들어 데이터 구조에서 요소를 제거하고을 Dictionary반환하는 메소드도 bool있습니다. API 소비자는 API를 소비할지 또는 무시할지 결정할 수 있습니다. 그러나 오류는 예외로보고됩니다.
Omer Iqbal

18

호출 코드에 예외를 던졌다면 어떨까요?

이렇게하면 코드를 사용하는 사람에게 예외 처리를 위임 할 수 있습니다. 향후에 다음을 수행하려면 어떻게합니까?

  • 예외가 발생하지 않으면 조치 A를 수행하십시오.
  • (예를 들어) a FileNotFoundException가 던져 지면 행동 B를 취하십시오.
  • 다른 예외가 발생하면 조치 C를 수행하십시오.

당신이 당신의 예외를 다시 던질 경우, 위의 변화는 것이 단순히 별도의 추가 수반 catch블록을. 그대로두면 메서드와 메서드가 호출되는 위치를 변경해야합니다.이 위치는 프로젝트의 복잡성에 따라 여러 위치에있을 수 있습니다.


1
위임 할 수없고 내부적으로 처리해야하는 예외가 발생하면 어떻게합니까?
Limbo Exile

2
@LimboExile : 내부적으로 처리 할 수 ​​있고 다른 예외를 던질 수도 있습니다. 이것은 발생해서는 안되는 일이 발생했음을 보여 주지만 동시에 실제로는 실제로 발생하는 일을 노출하지 않았으므로 내부적으로 예외를 처리하려는 이유라고 생각합니다.
npinti

6
예외를 던지는 것은 예외적 인 경우 라는 것을 명심할 가치가 있습니다 . DoStuff실패 하는 것이 일반적이거나 정상적인 경우 실패 사례에 대한 예외를 발생시키는 것은 잘못된 예외로 프로그램 흐름을 제어하는 ​​것과 유사합니다. 예외는 또한 고유 한 성능 비용이 있습니다. 경우 DoStuff실패가 오류로 인해 드문 경우이며, 다음 예외는 확실히 @npinti에서 알 수 있듯이 갈 수있는 방법입니다.
Karl Nicoll

1
@KarlNicoll 무언가가 "예외적"인지 여부는 완전히 주관적입니다. 주요 기준은 오류에 대해 아무 것도 수행하지 않으면 프로그램이 충돌하는지 여부와 함수 유형에 오류가 있는지 여부입니다. 또한 예외가 비싸다는 사실은 아닙니다. 언어와 언어에 따라 다릅니다. 파이썬에서는 예외가 저렴하며 스택 추적 정보를 제거하면 Java에서도 저렴할 수 있습니다. 성능 비용이 발생하더라도 프로파일 링 할 때까지 걱정하지 마십시오.
Doval

1
@Doval-나는 주관적이라는 것에 동의합니다. 이것이 OP가 최선의 조치가 될 수 있기 때문에 OP가 npinti의 답변을 완전히 할인해서는 안되는 이유입니다. 내 요점은 예외를 던지는 것이 항상 가장 좋은 길은 아니라는 것입니다. 실패로 인해 예외가 발생하여 응용 프로그램이 충돌 할 가능성이없는 경우가 많습니다. 예를 들어 DoStuff()내부 코드에서 예외가 발생한 후 OP의 메소드가 정리되고 메소드의 사후 조건이 여전히 올바른 경우 오류가 처리되었으므로 리턴 코드가 더 나은 옵션 일 수 있습니다.
Karl Nicoll

7

DoStuff() 충분하고 함수의 반환 값을 문서화해야하며 함수 이름에서 언급 할 필요가 없으며 사용 가능한 많은 API를 찾으십시오.

PHP

// this method update and return the number affected rows 
// called update instead of updateAndGetAffectedCount
$affected = $query->update(/* values */);

C- 샤프

// Remove item from the List
// returns true if item is successfully removed; otherwise, false.
public bool Remove( T item )

6

Java에서 Collection API 는 부울을 리턴 하는 add 메소드 를 정의 합니다 . 기본적으로 add가 컬렉션을 변경했는지 여부를 반환합니다. 따라서 List항목이 추가 Set되었으므로 일반적으로 true를 반환하지만 , 항목이 이미 있으면 false를 반환 Set할 수 있습니다. 각 고유 항목을 최대 한 번만 허용하기 때문 입니다.

즉, 컬렉션에서 허용하지 않는 항목 (예 : null 값)을 추가하면 NullPointerExceptionfalse를 반환 하는 대신 add가 발생 합니다.

사례에 동일한 논리를 적용 할 때 부울을 반환해야하는 이유는 무엇입니까? 예외를 숨기려면하지 마십시오. 예외를 던져라. 그렇게하면 무엇이 잘못되었는지 알 수 있습니다. 부울이 필요하지 않은 경우 (예외가 아닌 다른 이유로 인해 부울이 필요한 경우) DoStuff()동작의 이름 을 나타내는 메소드 이름을 지정하십시오 . 그것은 물건을한다.


1

예외, 정상적인 조건과 같은 다른 이유로 실패 할 수 있으므로 다음을 사용하십시오.

boolean doStuff() - returns true when successful

부울의 의미를 문서화하는 것이 중요합니다.


1

나는 보통 메소드가 OperationResult(또는 OperationResult<T>)을 반환 IsSuccess하고 OperationResult적절하게 속성을 설정합니다 . 'usual'메소드가 void이면 return OperationResult, 'usual'메소드가 오브젝트를 리턴 OperationResult<T>하면 Item특성 을 리턴 하고 OperationResult적절하게 설정하십시오 . 또한 메소드 가진 좋을 것 OperationResult같은 .Failed(string reason).Succeeded(T item). OperationResult시스템에서 빠르게 익숙한 유형이되고 개발자는이를 처리하는 방법을 알게됩니다.


0

실제로 사용중인 언어에 따라 다릅니다. 일부 언어와 마찬가지로 많은 언어 나 다른 언어에는 실제로 존재하지 않는 규칙과 프로토콜이 있습니다.

예를 들어, Objective-C 언어 및 iOS / Mac OS X SDK 메소드 이름에서 일반적으로 다음 행을 따릅니다.

- (returndatatype) viewDidLoad {
- (returndatatype) isVisible {
- (returndatatype) appendMessage:datatype variablename with:datatype variablename {

보시다시피 viewDidLoad라는 메소드가 있습니다. 본인의 응용 프로그램을 만들 때마다이 유형의 명명을 사용하는 것을 선호합니다. 이것은 당신이 말한대로 어떤 일이 발생했는지 확인하는 데 사용될 수 있습니다. 나는 그것이 당신이 당신의 방법의 이름을 무엇에 대해 너무 깊이 생각하고 있다고 생각합니다. 대부분의 메소드는 관계없이 자신이하는 일의 상태를 리턴합니다 (예 :

PHP에서 연결이 실패하면 mysql_connect ()는 false를 반환합니다. 그것은 그렇다고 말하지는 않지만 설명서는 그렇게하므로 프로그래머에게 잘못 해석 할 수는 없습니다.


아, 그러나 viewDidLoad는 더 많은 콜백 알림입니다. 사용자는 뷰를로드하기 위해 호출하지 않습니다. 오히려 뷰가로드 된 후에 호출됩니다. 마찬가지로 isVisible은 가시성을 설정하지 않고 현재 값을 반환합니다. 그것은하지 않습니다 것을.
lilbyrdie

0

'Try'접두사를 사용하고 싶습니다. 이는 방법이 성공할 수있는 상황에 대해 잘 알려진 패턴입니다. 이 명명 패턴은 Microsoft에서 .NET Framework (예 : TryParseInt)에서 사용했습니다.

그러나 이것은 아마도 명명에 관한 것이 아닙니다. 분석법의 입력 / 출력 매개 변수를 설계하는 방법에 관한 것입니다.

내 생각은 메서드에 반환 값이있는 경우 해당 메서드를 호출하는 목적은 해당 반환 값을 얻는 것입니다. 따라서 리턴 상태를 사용하여 조작 상태를 표시하지 않아야합니다.

C #에서는 out 매개 변수를 사용하는 것을 선호합니다. 출력을 사용하여 매개 변수를 측면 매개 변수로 표시하고 있습니다. 특히 C # 6은 인라인 변수 선언을 지원합니다.

DoStuff(out var isStuffDone); // The out parameter name clearly states its purpose.
DoStuff(out var _); // I use _ for naming parameters that I am ignoring.

0

이 방법의 주요 역할에 따라 이름을 선택합니다. 사실,이 메서드는 부울 값을 반환 할 때 'Is'접두사를 요구하지 않습니다. 'Is'접두사를 상당히 광범위하게 사용하는 Java 코드를 만들어 봅시다. 를보십시오 java.io.File.delete(). 이 반환 boolean되지만 호출되지 않습니다 isFileDeleted(). 그 이유는 metod의 주요 역할이 파일을 삭제하기 때문입니다. 누군가 파일을 삭제하려는 의도로이 메소드를 호출합니다.

부울은 작업 결과를 다시 전달하기 위해 존재합니다. 반면에을 보자 java.util.Map.isEmpty(). 분명히, 당신은 컬렉션이 비어 있는지 확인하기 위해 그러한 메소드를 호출합니다. 당신은 어떤 일도하고 싶지 않습니다. 현재 상태가 무엇인지 알고 싶습니다.

그래서 개인적으로, 나는 확실히 붙어 있습니다 DoStuff().

이것은 나에게 다소 중요한 문제입니다. 레거시 코드를 유지할 때는 여러 번 개인적으로 "거짓말 방법"이라고 부르는 것을 우연히 발견합니다. 이름은 조치 A를 제안하지만 본문은 조치 B를 수행합니다. 데이터베이스의 데이터를 변경하는 게터 메소드 인 가장 기괴한 예입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.