this post was submitted on 13 Jun 2023
6 points (100.0% liked)

Java

1367 readers
1 users here now

For discussing Java, the JVM, languages that run on the JVM, and other related technologies.

founded 1 year ago
MODERATORS
 

Assertions being built into Java is nice and they've been around since version 1.4. They predate type parameters! I have never seen them being used and the reason always seems to be that because you can't count on them being turned on because they're off by default.

The only theoretical use I can think of it for "executable comments", as in something like the example below, but they're annoying as the IDE will usually complain that it is always true (with no way to specifically disable warning for always true assertions, only always true conditions in general).

if (condition) {
  // Very long block of code
} else {
  assert !condition; // Primarily a reminder for when the if condition is not easily seen
}

Here it doesn't matter if the assertion is executed or not because it is just a reminder. The idea being that code sticks out more than a comment.

top 16 comments
sorted by: hot top controversial new old
[–] captcrax 5 points 1 year ago (1 children)

I think the idea was that you could run extra checks by in a QA environment without bearing the runtime cost of all the if (QA) tests in your production code.

No, I've never used it. Our company style guide discourages it because even in QA it would be too easy for some config to get lost/forgotten and give unexpected behavior. What if you're silently skipping asserts during your CI smoke tests because the jvm flag was missed, but now you think you've got the extra protection of those asserts?

[–] terebat 1 points 1 year ago (1 children)

That latter part is the same reason we mainly just use it in unit tests, and not much else. It's such a baffling situation when there's an assert, but the code still executes despite the assert. Debugging an incident or issue just becomes super annoying when that can be the case.

[–] JackbyDev 2 points 1 year ago

What's interesting is that the document seems to be aware of this and suggests not using it for full desogn-by-contract style pre/post conditions but does say it is fine for that on private methods.

But I've found myself so many times seeing things in production that I can't replicate locally (at least not easily) that I can't really say I'd want code like this (even if it was disabled in all environments except for unit testing). I just feel like it would throw people off. "Well it can't be that this private method is getting a negative number because there is an assertion. Sure, they're disabled, but a test would've ran into it. I can even easily see where this private method is called from." Then the problem ends up being that a negative number somehow got there lol. If that assertion had not been there then maybe people would've tried to see if that was the case first. Better yet, have a trace level log message for parameters then enable it for that one class.

[–] [email protected] 3 points 1 year ago (1 children)

You are not wrong that they are in a way "executable comments". Just like comments they are intended only for development/debugging and can't (shouldn't) have any influence on production code.

For example, in your sample code the if is unnecessary, because condition can't be (should not be) true. If it were, it would be a bug. Instead it should be written as:

assert !condition;
// Very long block of code

If the condition can ever be true then you shouldn't be using assert.

See also https://stackoverflow.com/a/2758645/318493

[–] JackbyDev 2 points 1 year ago (1 children)

Sorry, the example wasn't clear, I meant to have a normal if statement for normal things and then assert that the condition that you just checked in the if is false in the else before doing what you'd normally do in the else block. Something like this.

if (isEven) {
  log.info("it's even");
} else {
  assert !isEven;
  log.info("it's odd");
}

Again, not a great example because the code is short enough to clearly see the entire thing, but it better illustrates what I meant.

[–] [email protected] 1 points 1 year ago (1 children)

To be honest that doesn't change anything about what I said. The assertion condition must never be true at runtime. If it ever can be, then it's a wrong use of assert.

[–] JackbyDev 1 points 1 year ago

In that example it can't be true in the else block (assuming it is a local variable).

[–] [email protected] 3 points 1 year ago (1 children)

It always felt like they were a relic from an older version of Java. I have used it once during a university lecture and that was it. I think they are also not so useful if you have good unit tests and have well-structured code. In most cases where they would be useful, it is probably still safer to use actual if statements, even if that adds more boilerplate to the code.

[–] JackbyDev 2 points 1 year ago (1 children)

used it once in university

In university they always seem so intent to teach you everything. I remember seeing someone ask about some question that involved the return value of the assignment operator. I was like "look whatever you do please don't use this in the real world" lol. It may not have been Java.

[–] Clifspeare 1 points 1 year ago (1 children)

I mean, it's still a fairly common pattern to use the l-value yielded by the assignment operator in for-loops in C.

[–] JackbyDev 1 points 1 year ago

Can you give an example? I'm not sure I follow.

[–] thtroyer 2 points 1 year ago (1 children)

I was excited to use assert when I learned about it. I thought it would be ideal for short, clean guard clauses at the top of methods, to fail early on invalid data.

Once I realized that they're configurable and generally seemed to be off by default, they seem completely useless for that scenario. Doubly so when you're working in an environment where you don't control the server environment.

[–] JackbyDev 1 points 1 year ago (1 children)

I still think it can be useful but it really needs to be for things that can't be true as opposed to things that shouldn't be true. Like imagine this pseudocode (I have no idea off the top of my head if there is some extreme edge case where this does not hold true lol)

int i = someInt();
i = i % 3;
assert 0 <= Math.abs(i) && Math.abs(i) < 3 ;
[–] thtroyer 1 points 1 year ago

I would avoid using it that way too. Seems like it could be a source of confusion in the future (another dev may assume it offers protection it doesn't), and I would guess most IDEs would flag it as unnecessary.

I do my best to avoid huge if blocks, but when they do happen, I prefer a small, simple comment noting the purpose.

[–] Deely 1 points 1 year ago (1 children)

I could be wrong but assert used practically everytime while writing unit / integration tests. Practically every test contains form of asset, could be standard Java assert keyword, or, more often JUnit Assert class.

[–] JackbyDev 2 points 1 year ago

I've never seen a unit test using the assert keyword, only the JUnit Assert class methods. It throws AssertionError so it is like the assert keyword but can't be disabled like the assert keyword.