2010-05-03 9 views
25

질문을 둘러 보면서 최근에 자바에서 assert 키워드를 발견했습니다. 처음에는 흥분했습니다. 내가 모르는 뭔가 유용한 정보! 입력 매개 변수의 유효성을 검사하는보다 효율적인 방법! 예!Java가 어설 션되어 있습니까?

는하지만 나는 면밀한 관찰을했다, 나의 열정 "쉬어 아웃 완전히"하나의 간단한 사실로 "강화"순전히이었다. 당신이 주장을 해제 할 수 있습니다 *

이 악몽 같은 소리

. 입력 listOfStuffnull 인 경우 코드를 계속 사용하지 않기를 바란다면 왜이 주장을 무시하고 싶습니까? 프로덕션 코드를 디버깅하고 있는데 을 잘못 전달했을 수도 있지만 그 애매 트의 로그 파일 증거가 표시되지 않는다고 의심되는 것처럼 들리 겠지만, 나는 listOfStuff이 실제로 유효하다고 보냈습니다. 값; 또한 어설 션이 완전히 해제되었을 가능성에 대해 설명해야합니다.

그리고이 코드를 디버깅하는 것으로 가정합니다. 어설 션에 익숙하지 않은 사람은이를 볼 수 있으며 어설 션 메시지가 로그에 나타나지 않으면 listOfStuff은 문제가되지 않는다고 가정합니다. assert과의 첫 번째 만남이 야생에 있었다면 완전히 꺼져있을 수도 있습니다. 결국 try/catch 블록을 사용하지 않도록 설정할 수있는 명령 행 옵션이있는 것과는 다릅니다. (! 내가 약속이 질문이 아닌 호언 장담에 대한 변명입니다!)

모두의 내 질문에 날을 제공합니다 : 나는 무엇을 놓치고

?

assert의 Java 구현을 렌더링하는 데 약간의 미묘한 차이가 있습니까? 명령 줄에서 활성화/비활성화하는 기능이 실제로 일부 컨텍스트에서 믿을 수 없을만큼 가치가 있습니까? if (listOfStuff == null) barf();과 같은 구문 대신 프로덕션 코드에서 사용하는 것을 상상할 때 나는 그것을 어떻게 든 오해하고 있습니까?

나는 여기에 중요한 것이있어 보이지 않는다고 느낍니다.

* 기술적으로 말하자면, 실제로는 기본적으로 해제되어 있습니다. 그 (것)들을 켜기 위하여 당신의 방법에서 나가야한다. 그러나 여전히, 당신은 그들을 완전히 제압 할 수 있습니다.


편집 : Enlightenment requested, enlightenment received.

가장 중요한 것은 assert이라는 디버깅 도구가 길어서 먼 길을 간다는 개념입니다.

개발자는 잘못된 입력이 불가능하다고 생각하기 때문에 프로덕션 환경에서 중요하지 않은 개인 메소드에 대한 입력 확인을 사용 중지해야한다는 개념에 여전히 문제가 있습니다. 내 경험에 따르면, 성숙한 생산 코드는 다양한 수준의 온전한 정도의 요구 사항을 급변하는 사람들을 대상으로 다양한 수준의 기술을 가진 사람들이 수년간 개발 한 미친 거대한 물건입니다. 나쁜 입력이 실제로 불가능하더라도 6 개월 후에 코딩하는 지루한 유지 보수가이를 바꿀 수 있습니다. The link gustafc provided (! 감사) 예를 들어이 포함되어

assert interval > 0 && interval <= 1000/MAX_REFRESH_RATE : interval;

생산 같은 간단한 검사를 비활성화하면 나 같은 바보 낙관적 친다. 그러나 이것은 코딩 철학의 차이이며 깨진 기능이 아닙니다.

또한, 나는 확실히이 같은 값 볼 수 있습니다 날이 기능을 이해하는 데 도움이 할 수있는 시간이 걸렸습니다 모두에게

assert reallyExpensiveSanityCheck(someObject) : someObject;

내 감사; 그것은 대단히 감사합니다.

+10

이것은 호언 장담처럼 보입니다. 전혀 질문이 아닙니다. –

+3

C 또는 C++에서 ASSERT를 사용한 적이 있습니까? 혹시 손가락으로 스냅을 켜거나 끌 수 있기를 바랬습니까? –

+1

@ Joachim : 이해하지만 진지하게, 나는 깨달음을 찾고 있습니다. 이 기능은 실제로 나에게 부러진 것처럼 보입니다.하지만 "나는 내 코드에 어떤 문제가 있는지 보지 못하므로 컴파일러가 깨져야합니다!"라고 말하면서 비슷한 수준으로 느껴집니다. 나는 뭔가를 놓치고있는 것 같아. 내가 당신에게 호언 장담하지 않으면서도 그 기능이 나를 부러 뜨리는 이유를 표현할 수있는 방법을 제안 할 수 있다면, 나는 듣고있다. – BlairHippo

답변

21

assert계약의 유용한 부분입니다. 계약 :. 이러한 맥락에서 어설 션은 다음에서 사용될 수 있습니다.

  • 사전 조건 검사.
  • 사후 조건 검사.
  • 중간 결과 검사.
  • 클래스 불변성 검사.

어설 션은 평가하는 데 많은 비용이 소요될 수 있습니다 (예 : 클래스의 public 메소드를 호출하기 전과 후에 보유해야하는 클래스 불변). 어설 션은 일반적으로 디버그 빌드 및 테스트 용으로 만 필요합니다. 당신은 일어날 수없는 것들을 주장합니다 - 버그를 가지고있는 것의 동의어입니다. 어서션은 코드를 자체 의미에 맞게 검증합니다.

어설 션은 입력 유효성 확인 메커니즘이 아닙니다. 프로덕션 환경, 즉 입출력 계층에서 입력이 실제로 올 바르거나 틀릴 수있는 경우 예외 또는 오래된 오래된 조건부 검사와 같은 다른 방법을 사용하십시오.

0

어설 션은 코드에서 복구 할 수있는 문제를 나타내거나 디버깅을 돕는 것입니다. 프로그램을 중지하는 등 더 심각한 오류에 대해서는 더 파괴적인 메커니즘을 사용해야합니다.

나중에 응용 프로그램이 디버깅 및 테스트 시나리오에서 실패하기 전에 복구 할 수없는 오류를 catch하여 문제의 범위를 좁히는 데에도 사용할 수 있습니다. 그 이유 중 하나는 무결성 검사가 프로덕션에서 잘 테스트 된 코드의 성능을 저하시키지 않도록하기 위해서입니다.

또한 리소스 누출과 같은 경우에는 상황이 바람직하지 않을 수도 있지만 프로그램을 중지 한 결과가 계속 발생하는 결과보다 나쁩니다.

+0

프로덕션 환경에서 발생할 것으로 예상되는 복구 가능한 오류에 어설 션을 사용해야한다는 것에 동의하지 않습니다. 일반적으로 검사 예외가있는 것입니다. 그러나 어떤 경우에는 예외 나 어설 션이 적절하지 않습니다. –

4

나는 어설 션 사용법이 해석되고 생각되는 방식이라고 생각합니다.

실제 생산 코드에 수표를 추가하려면 직접 또는 다른 조건문을 사용하십시오.

어설 션의 개념은 개발자가 이미이 조건이 발생할 것으로 기대하지 않는 경우에만 개발자가 주장을 추가하는 것입니다.

예를 들어 객체가 null인지 검사하면 개발자가 private 메소드를 작성하여 두 곳에서 호출한다고 가정합니다 (이상적인 예는 아니지만 private 메소드에서 작동 할 수 있음). 객체가 아닌 오늘 불필요한 검사를 추가하는 대신에 객체가 null이 될 방법이 없다는 것을 알고 있기 때문에 내일 누군가가 null 인수로이 메소드를 호출하면 개발자의 단위 테스트에서 주장의 존재로 인해 잡힐 수 있습니다. 최종 코드는 여전히 if 체크를 필요로하지 않습니다.

+0

이것은 단위 테스트의 완성도 (또는 존재!)가 현명하다고 생각하는 것보다 더 믿음을 둡니다. 그럼에도 불구하고 나는 그것의 논리를 봅니다. :-) 고맙습니다. – BlairHippo

4

어설 션으로 본 모든 언어에는 해당 언어를 종료 할 수있는 기능이 있습니다. 당신이 주장을 쓸 때 당신은 "이것은 바보 같아요. 우주 에선 결코 틀릴 수는 없습니다"라고 생각해야합니다. 만약 그것이 틀릴 수 있다고 생각한다면, 그것은 오류 검사 여야합니다. 그 주장은 무언가가 끔찍하게 잘못 될 경우 개발하는 동안 당신을 도울 것입니다. 프로덕션 코드를 빌드 할 때 시간을 절약하고 불필요한 검사를 피할 수 있습니다.

+1

나는 그것이 나를 위로했던 철학의 차이라고 생각한다. 나를 위해, 입력 매개 변수를 점검하는 것이 온전한 지 여부에 대한 논평이 아닙니다. 이 방법은 잘못하지 않아야한다고 말하는 것입니다. 물론, 나쁜 입력이 불가능하다고 생각할 수도 있지만, 내가 아는 것은 무엇입니까? 코드베이스가 거대하고 내 이해가 불완전하고 미래의 어떤 시점에서 나쁜 입력을 다시 가능하게 할 수있는 바보가 있습니다. 그러나 그렇게 말하면서 값 비싼 수표를 켜거나 끌 수 있다는 가치를 느낍니다. – BlairHippo

+0

"오류 검사가되어야합니다": 프로그램 자체의 오류가 아닌 프로그램 입력 데이터의 오류입니까? – Raedwald

19

Java의 어설 션은 실제로 인수 유효성 검사를 위해 만들어지지 않았습니다. -이 코드는 specifically stated that assertions are not to be used instead of dear old IllegalArgumentException입니다 (둘 다 C-ish에서 사용되는 방법도 아닙니다. 언어). 그들은 내부 검증을 위해 더 많이 사용합니다. 코드를 보면서 명백하지 않은 코드에 대해 가정 할 수 있습니다.

끄기에 대해서는 C (++)에서도 그렇게합니다. 누군가가 어설트없는 빌드를 가지고 있다면, 켜는 방법이 없습니다. Java에서는 적절한 VM 매개 변수로 앱을 다시 시작하기 만하면됩니다.

+1

링크가 말하는 것은 아닙니다. PUBLIC 메서드에서 인수 유효성 검사에 사용해서는 안된다고 명시되어 있습니다. PRIVATE 메서드에서 인수 유효성 검사에 사용하는 예제를 명시 적으로 제공합니다. 그리고 명백하지 않은 코드에 대한 가정을하기 위해 일반적으로 주석 작업이 아닌가? C/C++에 대해 알지 못했습니다. 필자는 커맨드 라인 스위치를 통해 어떻게 켜는 것이 전체 재 컴파일을하는 것보다 더 매력적인지를 확실히 봅니다. – BlairHippo

+0

예, 특정 개인 메소드에 대해 어설 션을 사용할 수 있습니다. 그러나 프로덕션에서 이러한 개인 메소드에 대한 잘못된 호출이 없어야합니다 (보장 할 수 없으면 예외 또는 다른 메커니즘 사용). 이 페이지는 명시 적으로 어설 션을 주석이 아닌 가정을 문서화하는 데 사용해야한다고 명시합니다. 'i % 3 == 2' 예제를보십시오. –

1

이 질문에 대한 답변이 assert인데 Preconditions 클래스를/google-collections으로 체크 아웃하는 것이 좋습니다.그것은 (고정 수입을 사용)이 같은 좋은 물건을 쓸 수 있습니다 : 당신이 원하는 (그리고 그것을 해제 할 수 없습니다) 무엇을 할 수있는이 같은 것 같다

// throw NPE if listOfStuff is null 
this.listOfStuff = checkNotNull(listOfStuff); 

// same, but the NPE will have "listOfStuff" as its message 
this.listOfStuff = checkNotNull(listOfStuff, "listOfStuff"); 

.

1

어설 션은 최종 사용자가 볼 수있는 것이 아닙니다. 프로그래머를위한 것이므로 코드가 개발되는 동안 코드가 올바른 작업을 수행하는지 확인할 수 있습니다. 테스트가 끝나면 성능상의 이유로 어설 션이 해제됩니다.

listOfStuff가 null 인 것과 같이 프로덕션 환경에서 문제가 발생할 것으로 예상되는 경우 코드가 충분히 테스트되지 않았거나 코드를 작성하기 전에 입력 내용을 살균하지 않을 수 있습니다 . 어느 쪽이든, "if (나쁜 물건) {예외를 던져라}"가 더 좋을 것입니다. 어설 션은 테스트가 아닌 개발을위한 것이지 생산을위한 것이 아닙니다.

4

어설 션은 코드가 실제로 충족되었다고 확신하는 것을 보장하기위한 것입니다. 제품 개발 단계에서 디버깅을 돕는 기능이며 코드가 공개 될 때 일반적으로 생략됩니다.

무엇이 누락 되었습니까?

어설 션을 사용하는 방식대로 사용하지 않습니다. 당신은 "입력 매개 변수의 유효성을 확인하십시오."라고 말했습니다. 바로 당신이 수행하는 일들입니다. 이 아니라은 어서션으로 확인하고 싶습니다.

어설 션이 실패하면 100 % 코드에 버그가있는 것입니다. 어설 션은 다른 경우보다 먼저 버그를 식별하는 데 자주 사용됩니다.

+1

"코드에 100 % 버그가 있습니다": 코드 자체 또는 어설 션 확인 코드. – Raedwald

3

소리가 잘 들립니다. 어설 션은 코드 디버깅에 유용한 도구 일 뿐이며, 특히 프로덕션 코드에서 항상 켜져 있으면 안됩니다.

예를 들어 C 또는 C++에서 릴리스 빌드에서 어설 션을 사용할 수 없습니다.

+1

... 및 Java에서 기본적으로. – DJClayworth

3

어설 션은 코드 유지 관리 담당자에게 실제로 훌륭하고 간결한 문서 도구입니다.

foo는가 null 및 0

보다 커야 또는 프로그램의 몸으로이를 넣어 :

예를 들어 내가 쓸 수

assert foo != null; 
assert foo.value > 0; 

원래의 프로그래머 불변성을 표현하기 위해 private/package private 메소드를 문서화하는 데 매우 유용합니다.

보너스를 추가하면 하위 시스템이 비정상적으로 작동 할 때 어설 션을 켜고 즉시 추가 유효성 검사를 추가 할 수 있습니다.

2

어설 션을 해제 할 수없는 경우에도 어설 션이 존재해야하는 이유는 무엇입니까? 당신이 입력에 대한 유효성 검사를 PERFORMA하려면

, 당신은 쉽게

if (foobar<=0) throw new BadFoobarException(); 

를 작성하거나 메시지 박스가 팝업 또는 어떤 상황에서 유용 할 수 있습니다.

어설 션의 핵심은 디버깅을 위해 켜져 있고 프로덕션을 위해 꺼져있는 것입니다.

1

어설 션이 실패 할 때마다 최종 사용자에게 1 달러를 지불하고 싶다면 을 사용하십시오.

어설 션 오류는 프로그램의 설계 오류를 나타내는 것이어야합니다.

어설 션은 지정된 술어가 항상 보유한다는 것을 알고 보증 할 수있는 방식으로 프로그램을 조작했다고 주장합니다.

어설 션은 내 코드를 읽는 사용자에게 유용합니다. (1) 그 속성에 돈을 기꺼이 부과합니다. (2) 이전 처형 및 테스트 케이스에서 해당 부동산은 실제로 보유되었다.

내 코드는 클라이언트 코드가 규칙을 고수하고 그와 내가 동의 한 계약을 준수한다고 가정합니다. 이 계약은 용인 될 수 있습니다 (모든 입력 값이 유효하고 유효성이 검사 됨) 또는 요구됩니다 (클라이언트와 나는 특정 입력 값을 절대로 제공하지 않을 것에 동의했으며 [전제 조건으로 설명],이 값을 확인하지 않기를 바랍니다 다시 반복하여). 클라이언트가 규칙을 고수하고 그럼에도 불구하고 내 어설 션이 실패하면 클라이언트에게 보상이 제공됩니다.