어설 션 사용시기 및 예외 사용시기


121

대부분의 경우 예외를 사용하여 코드의 조건을 확인합니다. 어설 션을 사용하기에 적절한시기가 언제인지 궁금합니다.

예를 들어

Group group=null;
try{
    group = service().getGroup("abc");
}catch(Exception e){
    //I dont log error because I know whenever error occur mean group not found
}

if(group !=null)
{
    //do something
}

여기서 주장이 어떻게 맞는지 말씀해 주시겠습니까? 어설 션을 사용해야합니까?

프로덕션 코드에서 어설 션을 사용하지 않고 단위 테스트에서만 어설 션을 보는 것 같습니다. 대부분의 경우 예외를 사용하여 위와 같은 검사를 수행 할 수 있다는 것을 알고 있지만 "전문적으로"수행하는 적절한 방법을 알고 싶습니다.

답변:


81

어설 션은 절대 발생해서는 안되는 사항을 확인하는 데 사용해야하며 예외는 발생할 수있는 사항을 확인하는 데 사용해야합니다.

예를 들어 함수는 0으로 나눌 수 있으므로 예외를 사용해야하지만 어설 션을 사용하여 하드 드라이브가 갑자기 사라지는 지 확인할 수 있습니다.

어설 션은 프로그램 실행을 중지하지만 예외로 인해 프로그램이 계속 실행됩니다.

참고 if(group != null)단지 조건부 즉, 주장하지 않습니다.


3
"하드 드라이브가 갑자기 사라 졌는지 확인하는 데 어설 션을 사용할 수 있습니다."-이것이 맞지 않다고 말하고 싶습니다. 왜 개발 중에는 처리되지만 프로덕션에서는 처리되지 않기를 원합니까 (일반적으로 어설 션이 비활성화 된 경우)?
herman 2014-09-14

71
하드 드라이브에 대한 설명이 잘못되었습니다. 어설 션은 코드 로직의 오류를 확인하기위한 것입니다. 제어 할 수없는 것을 확인하는 데 절대 사용하지 마십시오. 기억 주장은 그것이 당신의 코드가 잘못된 것을 의미합니다 실패하는 경우 .
Ian Goldby

1
@Marius 조건문은 다음과 같은 단언으로 대체 될 수 있습니다. assert group! = null
IgorGanapolsky

1
하드 드라이브 예가 자신의 철학과 모순되기 때문에 비추천했습니다. 하드 드라이브가 "사라지는"(코드 관점에서 볼 때) 실제로는 아무리 불가능하더라도 실제로 발생할 수 있습니다. @IanGoldby가 말했듯이 단언은 순전히 코드에 의해 제어되는 것에 의존해야합니다.
Vicky Chijwani 2011

Gregory Pakosz가 게시 한 경우 훨씬 더 나은 답변을 얻으려면 해당 게시물을 읽으십시오.
ormurin

169

내 마음에서 (목록이 불완전 할 수 있으며 주석에 맞기에는 너무 길 수 있음) 다음과 같이 말할 것입니다.

  • 공용 또는 보호 된 메소드 및 생성자에 전달 된 매개 변수를 확인할 때 예외 사용
  • 사용자와 상호 작용하거나 예외 상황에서 클라이언트 코드가 복구 될 것으로 예상 할 때 예외를 사용합니다.
  • 예외를 사용하여 발생할 수있는 문제 해결
  • 개인 / 내부 코드의 사전 조건, 사후 조건 및 불변성을 확인할 때 어설 션 사용
  • 자신이나 개발자 팀에 피드백을 제공하기 위해 어설 션 사용
  • 발생 가능성이 매우 낮은 일을 확인할 때 어설 션을 사용하십시오. 그렇지 않으면 응용 프로그램에 심각한 오류가 있음을 의미합니다.
  • 당신이 (아마도) 사실이라고 알고있는 것을 진술하기 위해 주장을 사용하라

즉, 예외는 애플리케이션의 견고성을 해결하는 반면 어설 션은 정확성을 해결합니다.

어설 션은 작성 비용이 저렴하도록 설계되었으며 거의 ​​모든 곳에서 사용할 수 있으며이 경험 법칙을 사용합니다. 어설 션 문이 어리석게 보일수록 더 가치 있고 더 많은 정보가 포함됩니다. 올바른 방식으로 작동하지 않는 프로그램을 디버깅 할 때 경험을 바탕으로보다 명백한 실패 가능성을 확실히 확인할 수 있습니다. 그런 다음 발생할 수없는 문제를 확인합니다. 바로 이것이 어설 션이 많은 도움이되고 시간을 절약 할 때입니다.


53
나는 당신이 이것을 표현한 방식이 마음에 든다. 예외는 애플리케이션의 견고성을 다루고 어설 션은 정확성을 다룬다 .
M. Dudley


C ++ 커스텀 어설 션 라이브러리를 찾으면 github.com/gpakosz/Assert
Gregory Pakosz

26

어설 션은 매개 변수를 사용하여 런타임에 비활성화 할 수 있으며 기본적으로 비활성화되어 있으므로 디버깅 목적을 제외하고는 신뢰하지 마십시오.

또한 assert 를 사용하거나 사용하지 않는 더 많은 경우를 보려면 assert대한 Oracle 기사를 읽어야합니다 .


Hue hue hue 내 코드가 Eclipse에서 실패했지만 명령 줄에서 잘 실행되는 이유가 궁금합니다.
Steve

15

일반적으로 :

  • 누군가가 꺼져도 전혀 중요하지 않은 내부 일관성 검사를 위해 어설 션을 사용하십시오. (이 java명령은 기본적으로 모든 어설 션을 해제합니다.)
  • 끄면 안되는 모든 종류의 검사에 정기적 인 테스트를 사용하십시오. 여기 에는 버그로 인한 잠재적 손상과 사용자 또는 외부 서비스가 제공하는 모든 유효성 검사 데이터 / 요청을 방지 하는 방어 검사가 포함됩니다 .

귀하의 질문에서 다음 코드는 잘못된 스타일 이며 잠재적으로 버그가 있습니다.

try {
    group = service().getGroup("abc");
} catch (Exception e) {
    //i dont log error because i know whenever error occur mean group not found
}

문제는 예외가 그룹을 찾을 수 없다는 것을 의미한다는 것을 모른다는 것입니다. 이는 것도 가능하다 service()호출 예외를 던지거나 반환 된 null후 발생한다 NullPointerException.

"예상 된"예외를 포착하면 예상 하는 예외 포착해야합니다 . 포착 java.lang.Exception(특히 로깅하지 않음)하면 문제를 진단 / 디버그하기가 더 어려워지고 앱이 더 많은 피해를 입힐 수 있습니다.


4

음, Microsoft로 돌아와서, 공개적으로 사용할 수있는 모든 API에서 예외를 발생시키고 내부 코드에 대한 모든 종류의 가정에서 Assert를 사용하는 것이 좋습니다. 약간 느슨한 정의이지만 선을 그리는 것은 각 개발자에게 달려 있다고 생각합니다.

예외의 사용과 관련하여 이름에서 알 수 있듯이 그 사용법은 예외적이어야하므로 위에 제시 한 코드의 경우 서비스가 없으면 getGroup호출이 반환되어야 null합니다. 예외는 네트워크 링크가 다운되거나 그와 비슷한 경우에만 발생해야합니다.

결론은 어설 션 대 예외의 경계를 정의하는 것은 각 애플리케이션의 개발 팀에 약간 맡겨져 있다는 것입니다.


IMHO, 그런 종류의 권장 사항의 문제는 API의 공개 부분과 비공개 부분 사이의 경계가 꽤 고정되어있는 한 괜찮다는 것입니다. 새 코드를 개발하는 경우 그 경계는 종종 매우 유동적입니다 ...
Len Holgate

네 말이 맞아. 가이드 라인이지만 결국 프로그래머의 감수성에 맡겨져 있습니다. 나는 이것들에 대한 궁극적 인 정의 라인이 있다고 생각하지 않으므로 다른 코드의 부하를 읽음으로써 당신이 옳다고 생각하는 것을 사용한다고 생각합니다.
rui

3

이 문서 http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#design-faq-general 에 따르면 "assert 문은 비공개 전제 조건, 사후 조건 및 클래스 불변에 적합합니다. 검사. 공용 전제 조건 검사는 IllegalArgumentException 및 IllegalStateException과 같이 특히 문서화 된 예외를 발생시키는 메서드 내부 검사에 의해 수행되어야합니다. "

전제 조건, 사후 조건 및 클래스 불변에 대해 자세히 알고 싶다면 http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#usage-conditions 문서를 확인 하십시오 . 또한 어설 션 사용 예제도 포함되어 있습니다.


1

null에 대한 테스트는 문제를 일으키는 null 만 포착하는 반면 try / catch는 오류 를 포착 합니다 .

대체로 try / catch가 더 안전하지만 약간 느리므로 발생할 수있는 모든 종류의 오류를 포착하도록주의해야합니다. 그래서 저는 try / catch를 사용한다고 말할 것입니다. 언젠가는 getGroup 코드가 변경 될 수 있으며 더 큰 그물이 필요할 수 있습니다.


1

이 간단한 차이점을 염두에두고 사용하는 동안 사용할 수 있습니다. 예외는 확인 된 오류와 확인되지 않은 오류라고하는 예상 오류와 예상치 못한 오류를 확인하는 데 사용되며, 어설 션은 주로 런타임에서 가정의 유효성을 확인하는지 여부를 확인하기 위해 디버깅 목적으로 사용됩니다.


1

나는 당신의 질문에 약간 혼란 스럽습니다. 어설 션 조건이 충족되지 않으면 예외가 발생합니다. 혼란스럽게도이를 AssertionError 라고 합니다. 매우 유사한 상황에서 발생하는 (예를 들어) IllegalArgumentException 과 같이 선택 해제 되어 있습니다.

따라서 Java에서 어설 션 사용

  1. 조건 / 던지기 블록을 작성하는보다 간결한 수단입니다.
  2. JVM 매개 변수를 통해 이러한 검사를 켜거나 끌 수 있습니다. 일반적으로 런타임 성능에 영향을 미치거나 유사한 패널티가 발생하지 않는 한 이러한 검사를 항상 유지합니다.

AssertionError는 RuntimeException이 아닌 Error의 하위 클래스입니다.
Stephen C

아. 물론이야. 나는 체크 / 비 체크를 생각하고 있었다. 이제 수정 됨
Brian Agnew

논란의 여지가있는 관점에서 주장이 무엇인지 설명하지만 정확히 언제 사용해야하는지는 설명하지 않습니다.
Karl Richter

1

다음 링크에서 Sun 설명서의 섹션 6.1.2 (Assertions vs. Other Error Code)를 참조하십시오.

http://www.oracle.com/technetwork/articles/javase/javapch06.pdf

이 문서는 어설 션을 사용할 때 내가 본 최고의 조언을 제공합니다. 문서에서 인용 :

"좋은 경험 법칙은 잊고 싶은 예외적 인 경우에 대해 단정을 사용해야한다는 것입니다. 단언은 필요하지 않을 것으로 예상되는 조건이나 상태를 처리하고 잊는 가장 빠른 방법입니다. 다루다."


0

불행히도 어설 션을 비활성화 할 수 있습니다. 프로덕션에서 예상치 못한 것을 추적 할 때 얻을 수있는 모든 도움이 필요하므로 스스로 자격을 박 탈당합니다.

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