매개변수를 기반으로 예외를 던지거나 던지지 않음 - 왜 이것이 좋은 생각이 아닌가?

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

문제

MSDN을 뒤지다가 발견한 내용입니다. 이 기사 흥미로운 조언이 하나 있었습니다. 일부 옵션에 따라 예외를 발생시키거나 발생시키지 않을 수 있는 공개 멤버가 없습니다.

예를 들어:

Uri ParseUri(string uriValue, bool throwOnError)

물론 99%의 경우 이것이 끔찍할 것이라는 점을 알 수 있지만 가끔 사용하는 것이 정당합니까?

제가 본 한 가지 사례는 데이터베이스나 구성 파일의 데이터에 액세스할 때 "AllowEmpty" 매개변수를 사용하는 것입니다.예를 들어:

object LoadConfigSetting(string key, bool allowEmpty);

이 경우 대안은 null을 반환하는 것입니다.그러나 호출 코드는 널 참조 검사로 가득 차게 됩니다.(또한 이 방법은 원하는 경우 null을 구체적으로 구성 가능한 값으로 실제로 허용하는 기능도 배제합니다.)

당신의 생각은 무엇입니까?이것이 왜 큰 문제가 될까요?

도움이 되었습니까?

해결책

나는 부울에 근거한 던지기 / 던지기 결정을 내리는 것이 확실히 나쁜 생각이라고 생각합니다. 즉, 부울의 의미를 결정하기 위해 API에 대한 기능적 지식을 갖도록 코드를보고있는 개발자가 필요하기 때문입니다. 이것은 자체적으로 나쁘지만 기본 오류 처리를 변경하면 코드를 읽는 동안 개발자가 실수를하기가 매우 쉽습니다.

이 경우 2 개의 API를 갖는 것이 훨씬 더 좋고 읽기 쉬울 것입니다.

Uri ParseUriOrThrow(string value);

bool TryParseUri(string value, out Uri uri);

이 경우이 API가하는 일이 100% 명확합니다.

부울이 매개 변수로 나쁜 이유에 대한 기사 : http://blogs.msdn.com/jaredpar/archive/2007/01/23/boolean-parameters.aspx

다른 팁

일반적으로 하나의 오류 처리 메커니즘을 선택하고 일관되게 고수하는 것이 가장 좋습니다. 이러한 종류의 플립 플롭 코드를 허용하면 개발자의 수명이 실제로 향상 될 수 없습니다.

위의 예에서 구문 분석이 실패하고 ThrowOnerror가 False이면 어떻게됩니까? 이제 사용자는 귀환 될 경우 NULL이 있는지 추측해야합니다.

사실 예외와 반환 값 사이에는 더 나은 오류 처리 방법으로 진행중인 토론이 있지만, 나는 당신이 선택하는 어떤 선택을 일관성 있고 고수하는 것에 대한 합의가 있다고 확신합니다. API는 사용자를 놀라게 할 수 없으며 오류 처리는 인터페이스의 일부 여야하며 인터페이스만큼 명확하게 정의되어야합니다.

그것은 재가성 관점에서 불쾌한 것입니다. 개발자는 모든 방법이 예외를 던지기를 기대하는 경향이 있으며, 예외를 무시하려면 스스로 잡을 것입니다. '부울 플래그'접근 방식을 사용하면 모든 단일 방법은이 예외 억제 시맨틱을 구현해야합니다.

그러나 MSDN 기사는 'ThrowOnerror'플래그를 엄격히 언급하고 있다고 생각합니다. 이 경우 메소드 자체 내부에서 오류가 무시됩니다 (숨겨져 있기 때문에 불량) 또는 어떤 종류의 NULL/오류 객체가 반환됩니다 (오류를 처리하기 위해 예외를 사용하지 않기 때문에 불일치하고 오류 자체가 오류가 발생하지 않기 때문입니다. -프론).

당신의 모범은 나에게 괜찮아 보인다. 예외는 방법이 의무를 수행하지 못한다는 것을 나타냅니다. 반환 값은 없습니다. 그러나 '허용'깃발 의미론을 변경합니다 이 방법 중 - 예외는 무엇입니까 ( '빈 가치')는 이제 예상되고 합법적입니다. 게다가, 당신이 가졌다 예외를 던지면 구성 데이터를 쉽게 반환 할 수 없습니다. 이 경우 괜찮아 보입니다.

공개 API에서 오류 상태를 확인하는 두 가지 방법을 갖는 것은 실제로 나쁜 생각입니다. 오류가 발생하면 어떤 일이 일어날지 불분명해지기 때문입니다.코드만 보는 것만으로는 도움이 되지 않습니다.플래그 매개변수의 의미를 이해해야 합니다(그리고 그것이 표현식이 되는 것을 방해하는 것은 아무것도 없습니다).

null을 확인하는 것이 옵션이 아니고 이 특정 오류에서 복구해야 하는 경우 나중에 이를 포착하고 적절하게 처리할 수 있도록 특정 예외를 생성하는 것을 선호합니다.다른 경우에는 일반적인 예외를 발생시킵니다.

이와 관련된 또 다른 예는 일부 값 유형에 대한 tryparse 메소드 세트 일 수 있습니다.

bool DateTime.TryParse(string text, out DateTime)

DontThrowException 매개 변수를 갖는 것은 예외의 요점 (모든 언어로)을 물리칩니다. 호출 코드가 원하는 경우 :

public static void Main()
{
        FileStream myFile = File.Open("NonExistent.txt", FileMode.Open, FileAccess.Read);
}

그들은 환영합니다 (C#은 예외를 확인하지 않았습니다). Java에서는 다음과 같은 일을 수행 할 것입니다.

public static void main(String[] args) throws FileNotFoundException
{
        FileInputStream fs = new FileInputStream("NonExistent.txt");
}

어느 쪽이든, Callee의 것이 아니라 예외를 처리하는 방법을 결정하는 것은 발신자의 직업입니다.

링크 된 기사에는 제어 흐름에 예외가 사용되어서는 안된다는 점이 있습니다. 예제 퀘스트에서 암시되는 것 같습니다. 예외는 방법 레벨 고장을 반영해야합니다. 오류를 던지는 것이 좋다는 서명을 갖는 것은 디자인이 생각되지 않는 것처럼 보입니다.

Jeffrey Richters는 C#을 통해 CLR을 예약합니다.

그의 책은 또한 매우 일반적인 오류를 지적했습니다. 사람들은 모든 것을 잡기 위해 코드를 작성하는 경향이 있습니다 (그의 말은 예외의 적절한 사용에 대해 제대로 훈련되지 않은 개발자들의 유비쿼터스 실수는 어획 블록을 너무 자주 그리고 부적절하게 사용하는 경향이 있습니다. 예외를 포착 할 때, 당신은 그것을 말하고 있습니다. 당신은이 예외를 기대했고, 그것이 발생한 이유를 이해하고 그것을 다루는 방법을 알고 있습니다. ")

그것은 내가 기대할 수 있고 내 논리에서 처리 할 수있는 예외를 코딩하려고 시도했지만 그렇지 않으면 오류가되어야합니다.

당신의 주장을 검증하고 예외를 방지하고, 당신이 처리 할 수있는 것을 잡을 수 있습니다.

실패로 인해 예외가 발생해야 하는지 아니면 단순히 오류 표시를 반환해야 하는지를 나타내는 매개 변수가 있으면 유용할 때가 많다고 단언합니다. 이러한 매개 변수는 외부 루틴에서 내부 루틴으로 쉽게 전달될 수 있기 때문입니다.다음과 같은 것을 고려해보세요:

byte [] readpacket (bool dontthrowifnone) // returning null로 문서화 {int len ​​= readbyte (dontthrowifnone);// returning -1로 문서

데이터를 읽는 동안 TimeoutException과 같은 예외가 발생하는 경우 ReadByte() 또는 ReadMultiBytesbytes() 내에서 이러한 예외가 발생해야 합니다.그러나 이러한 데이터 부족이 정상적인 것으로 간주되어야 하는 경우 ReadByte() 또는 ReadMultiBytesbytes() 루틴은 예외를 발생시키지 않아야 합니다.단순히 do/try 패턴을 사용한 경우 ReadPacket 및 TryReadPacket 루틴은 거의 동일한 코드를 가져야 하지만 하나는 Read* 메서드를 사용하고 다른 하나는 TryRead* 메서드를 사용해야 합니다.이키.

부울보다는 열거형을 사용하는 것이 더 나을 수도 있습니다.

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