code

잘 사용되지 않는 자바 어설 션

codestyles 2020. 11. 13. 08:14
반응형

잘 사용되지 않는 자바 어설 션


assertJava에서 키워드가 그렇게 과소 사용 되는지 궁금합니다 . 나는 그것들이 사용되는 것을 거의 본 적이 없지만 좋은 생각이라고 생각합니다. 나는 확실히 다음의 간결함을 선호합니다.

assert param != null : "Param cannot be null";

자세한 정보 :

if (param == null) {
    throw new IllegalArgumentException("Param cannot be null");
}

내 의심은 그들이 과소 사용된다는 것입니다.

  • 그들은 상대적으로 늦게 도착했습니다 (Java 1.4).이 때 많은 사람들이 이미 Java 프로그래밍 스타일 / 습관을 확립했습니다.
  • 기본적으로 런타임에 꺼져 있습니다.

어설 션 은 이론적으로 불변성 을 테스트 하기위한 것으로 코드가 제대로 완료 되려면 참 이어야하는 가정입니다 .

표시된 예는 유효한 입력을 테스트하는 것으로, 일반적으로 사용자가 제공하기 때문에 어설 션의 일반적인 사용이 아닙니다.

어설 션은 오버 헤드가 있기 때문에 일반적으로 프로덕션 코드에서 사용되지 않으며 개발 및 테스트 중에 불변성이 실패하는 상황이 코딩 오류로 포착되었다고 가정합니다.

그들이 자바에 "늦게"온다는 당신의 요점은 그들이 더 널리 보이지 않는 이유이기도합니다.

또한 단위 테스트 프레임 워크를 사용하면 테스트중인 코드의 외부에 프로그래밍 방식 어설 션이 필요합니다.


사용자 입력을 테스트하는 데 사용하는 것은 어설 션의 남용입니다. IllegalArgumentException잘못된 입력을 던지는 것이 더 정확합니다. 호출하는 메서드가 예외를 포착하고 오류를 표시하고 필요한 모든 작업을 수행 할 수 있기 때문입니다 (입력 다시 요청, 종료 등).

해당 메서드가 클래스 중 하나 내부의 개인 메서드 인 경우, 우연히 null 인수를 전달하지 않았는지 확인하려고하기 때문에 어설 션이 괜찮습니다. 어설 션을 켜고 테스트하고 어설 션을 트리거하지 않고 통과하는 모든 경로를 테스트 한 경우 리소스를 낭비하지 않도록 끌 수 있습니다. 댓글처럼 유용합니다. assert방법의 시작은 좋은 그들은 특정 전제 조건을 다음되어야 함을 유지 보수 자에 대한 문서 및 인 assert방법은 일을해야 무엇 사후 문서와 끝. 주석만큼 유용 할 수 있습니다. 더구나, 주장을 사용하면 실제로 문서화 한 내용을 테스트하기 때문입니다.

어설 션은 오류 검사가 아니라 테스트 / 디버깅을위한 것이므로 기본적으로 꺼져 있습니다. 사용자 입력을 확인하기 위해 어설 션을 사용하지 못하도록합니다.


에서 어설와 프로그래밍

기본적으로 어설 션은 런타임에 비활성화됩니다. 두 개의 명령 줄 스위치를 사용하면 어설 션을 선택적으로 활성화 또는 비활성화 할 수 있습니다.

즉, 런타임 환경을 완전히 제어 할 수없는 경우 어설 션 코드가 호출된다는 것을 보장 할 수 없습니다. 어설 션은 프로덕션 코드가 아닌 테스트 환경에서 사용하기위한 것입니다. 사용자가 어설 션을 비활성화 ( 기본값 ) 한 상태에서 애플리케이션을 실행 하면 모든 오류 처리 코드가 사라지기 때문에 예외 처리를 어설 션으로 바꿀 수 없습니다 .


"Effective Java"에서 Joshua Bloch는 ( "유효성 확인 매개 변수"주제에서) 공개 메소드에 대해 인수를 검증하고 유효하지 않은 경우 필요한 예외를 던질 것이라고 제안했습니다 ( "유효성 확인 매개 변수"주제에서). 공개되지 않은 메소드 (노출되지 않고 사용자로서 유효성을 확인해야 함)의 경우 대신 어설 션을 사용할 수 있습니다.

yc


@Don, 당신은 어설 션이 기본적으로 꺼져 있다는 것에 실망합니다. 나는 또한 인라인하는이 작은 javac 플러그인을 작성했습니다 (즉, if (!expr) throw Ex이 바보 같은 주장 바이트 코드 대신에 바이트 코드를 내 보냅니다.

Java 코드를 컴파일하는 동안 클래스 경로에 fa.jar 을 포함하면 마법을 수행 한 다음

Note: %n assertions inlined.

@ http://smallwiki.unibe.ch/adriankuhn/javacompiler/forceassertions 및 github https://github.com/akuhn/javac 참조


어설 션을 작성하고 표준 if then 조건문으로 대체해야하는 이유를 모르겠습니다. 조건을 처음부터 ifs처럼 작성하지 않는 이유는 무엇입니까?

어설 션은 테스트 전용이며 두 가지 부작용이 있습니다. 활성화되면 더 큰 바이너리와 성능 저하 (이것이이를 끌 수있는 이유입니다!)

어설 션이 활성화 / 비활성화 될 때 런타임에 앱의 동작이 다르기 때문에 조건을 검증하는 데 어설 션을 사용해서는 안됩니다. 이는 악몽입니다!


어설 션은 다음과 같은 이유로 유용합니다.

  • 프로그래밍 오류 조기 발견
  • 코드를 사용하여 코드 문서화

코드 자체 검증이라고 생각하십시오. 실패하면 프로그램이 손상되어 중지해야 함을 의미합니다. 단위 테스트 중에 항상 켜십시오!

에서 실용주의 프로그래머 그들은 심지어 그들이 생산에 실행할 수 있도록하는 것이 좋습니다.

어설 션을 켜진 상태로 둡니다.

불가능을 방지하기 위해 어설 션을 사용하십시오.

어설 션이 실패하면 AssertionError가 발생하므로 catch Exception에 의해 포착되지 않습니다.


어설 션은 매우 제한적입니다. 부울 조건 만 테스트 할 수 있으며 매번 유용한 오류 메시지에 대한 코드를 작성해야합니다. 이를 입력에서 유용한 오류 메시지를 생성하고 JUnit 실행기의 IDE에서 두 입력을 나란히 표시 할 수있는 JUnit의 assertEquals ()와 비교하십시오.

또한 지금까지 본 IDE에서는 어설 션을 검색 할 수 없지만 모든 IDE는 메서드 호출을 검색 할 수 있습니다.


tl; dr

  • 예, 프로덕션 에서 타당한 곳 에서 어설 션 테스트를 사용하십시오 .
  • 원하는 경우 내장 기능이 아닌 다른 라이브러리 ( JUnit , AssertJ , Hamcrest 등)를 사용하십시오 assert.

이 페이지에있는 대부분의 다른 답변은 "어설 션은 일반적으로 프로덕션 코드에서 사용되지 않습니다."라는 격언을 강요합니다. 워드 프로세서 또는 스프레드 시트와 같은 생산성 앱에서는 사실이지만 Java가 널리 사용되는 사용자 지정 비즈니스 앱에서는 어설 션- 프로덕션 테스트는 매우 유용하고 일반적입니다.

프로그래밍 세계의 많은 격언과 마찬가지로, 한 맥락에서 진실로 시작하는 것은 잘못 해석 된 다음 다른 맥락에서 잘못 적용됩니다.

생산성 앱

"어설 션은 일반적으로 프로덕션 코드에서 사용되지 않습니다."라는이 격언은 일반적이지만 올바르지 않습니다.

공식화 된 어설 션 테스트는 Microsoft Word 와 같은 워드 프로세서 또는 Microsoft Excel 과 같은 스프레드 시트와 같은 앱에서 시작되었습니다 . 이러한 앱은 사용자가 입력 한 모든 키 입력에서 어설 션 테스트 어설 션 배열을 호출 할 수 있습니다 . 이러한 극단적 인 반복은 성능에 심각한 영향을 미쳤습니다. 따라서 제한된 배포판에있는 그러한 제품의 베타 버전에서만 어설 션이 활성화되었습니다. 따라서 격언.

비즈니스 앱

반대로 데이터 입력, 데이터베이스 또는 기타 데이터 처리를위한 비즈니스 지향 앱에서는 프로덕션에서 어설 션 테스트를 사용하는 것이 매우 유용합니다. 성능에 대한 사소한 타격은 매우 실용적이고 일반적입니다.

비즈니스 규칙 테스트

Verifying your business rules at runtime in production is entirely reasonable, and should be encouraged. For example:

  • If an invoice must have one or more line items at all times, then write an assertion testing than the count of invoice line items is greater than zero.
  • If a product name must be at least 3 characters or more, write an assertion testing the length of the string.
  • When calculating the balance for a cash ledger, you know the result can never be negative, so run a check for a negative number signaling a flaw in the data or code.

Such tests have no significant impact on performance in production.

Runtime conditions

If your app expects certain conditions to always be true when your app runs in production, write those expectations into your code as assertion tests.

If you expect those conditions may reasonably on occasion fail, then do not write assertion tests. Perhaps throw certain exceptions. Then try to recover where possible.

Sanity-checks

Sanity checks at runtime in production is also entirely reasonable, and should be encouraged. Testing a few arbitrary conditions that one could not imagine being untrue has saved my bacon in countless situations when some bizarre happening occurred.

For example, testing that rounding a nickel (0.05) to the penny resulted in a nickel (0.05) in a certain library helped me in being one of the first people to discover a floating-point technology flaw that Apple shipped in their Rosetta library during the PowerPC-to-Intel transition. Such a flaw reaching the public would have seemed impossible. But amazingly, the flaw had escaped the notice of the originating vendor, Transitive, and Apple, and the early-access developers testing on Apple’s betas.

(By the way, I should mention… never use floating-point for money, use BigDecimal.)

Choice of frameworks

Rather than use the built-in assert facility, you may want to consider using another assertion framework. You have multiple options, including:

Or roll-your-own. Make a little class to use in your project. Something like this.

package work.basil.example;

public class Assertions {
    static public void assertTrue ( Boolean booleanExpression , CharSequence message ) throws java.lang.AssertionError {
        if ( booleanExpression ) {
            // No code needed here.
        } else { // If booleanExpression is false rather than expected true, throw assertion error.
            // FIXME: Add logging.
            throw new java.lang.AssertionError( message.toString() );
        }
    }

}

Example usage:

Assertions.assertTrue( 
    localTime.isBefore( LocalTime.NOON ) , 
    "The time-of-day is too late, after noon: " + localTime + ". Message # 816a2a26-2b95-45fa-9b0a-5d10884d819d." 
) ;

Your questions

They arrived relatively late (Java 1.4), by which time many people had already established their Java programming style/habit

Yes, this is quite true. Many people were disappointed by the API that Sun/JCP developed for assertion-testing. Its design was lackluster in comparison to existing libraries. So many ignored the new API, and stuck with known tools (3rd-party tools, or roll-your-own mini-library).

They are turned off at runtime by default, WHY OH WHY??

In the earliest years, Java got a bad rap for poor performance speed. Ironically, Java quickly evolved to become one of the best platforms for performance. But the bad rap hung around like a stinky odor. So Sun was extremely wary of anything that might in any measurable way impact performance. So in this perspective, it made sense to make disabling assertion-testing the default.

Another reason to disable by default might have been related to the fact that, in adding the new assertion facility, Sun had hijacked the word assert. This was not a previously reserved keyword, and required one of the few changes ever made to the Java language. The method name assert had been used by many libraries and by many developers in their own code. For some discussion of this historical transition, read this old documentation, Programming With Assertions.


In fact they arrived in Java 1.4

I think the main problem is that when you code in an environment where you do not manage directly jvm options by yourself like in eclipse or J2EE servers (in both cases it is possible to change jvm options but you need to deeply search to find where it can be done), it is easier (I mean it requires less effort) to use if and exceptions (or worse not to use anything).


As others have stated: assertions are not appropriate for validating user input.

If you are concerned with verbosity, I recommend you check out a library I wrote: https://bitbucket.org/cowwoc/requirements/. It'll allow you to express these checks using very little code, and it'll even generate the error message on your behalf:

requireThat("name", value).isNotNull();

and if you insist on using assertions, you can do this too:

assertThat("name", value).isNotNull();

The output will look like this:

java.lang.NullPointerException: name may not be null

참고URL : https://stackoverflow.com/questions/298909/java-assertions-underused

반응형