• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Q about assertion

 
Ranch Hand
Posts: 443
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This is Q30 from Dan's Mock exam:

One of the answers, "The throw statement could be replaced by an assert statement.", is marked as FALSE and the explanation given is:


A throw statement is used in place of an assert statement because the throw statement can not be disabled and therefore the method is certain to generate an error once control passes beyond all of the return statements.


OK, that's fine. I have no problem with that.
Now if I modify the code to this:

can I then say that the throw statement can now be replaced by an assert statement ?
Thanks.
 
Ranch Hand
Posts: 2120
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
My two cents.
A) If the intention of the programmer was to check for certain contraints of arguments to public methods (b1, b2, b3 and i) , it is not possible to replace throw with an assert. However it is rare to use an error for that purpose.
B) If you just replace the throw statement with an assert the compiler will complain because a return statement is needed to comply with the method signature.
 
Alton Hernandez
Ranch Hand
Posts: 443
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Jose Botella:
My two cents.
A) If the intention of the programmer was to check for certain contraints of arguments to public methods (b1, b2, b3 and i) , it is not possible to replace throw with an assert. However it is rare to use an error for that purpose.


Hi Jose,
If it is based on the programmer's intention, then how one would know when and if an assertion is appropriate. In the 2 sample codes, the programmer might not expect that the throw statement will be reached. It might have been placed there just to be sure, or it could have been taken out because the programmer is so sure.
 
Ranch Hand
Posts: 1392
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

can I then say that the throw statement can now be replaced by an assert statement ?


Yes, providing you add a return of some kind after the assert statement to accommodate the return type of String. Because...
An assumption that a particular variable will have one of a small number of values is an invariant that should be checked with an assertion. An acceptable alternative is to throw an AssertionError.
(I noticed that Dan�s assertion questions are testing specific lessons from the assertion guide. So I went to the assertion guide and found which sentence Dan was testing in this question.)
[ August 09, 2003: Message edited by: Marlene Miller ]
 
Jose Botella
Ranch Hand
Posts: 2120
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I agree. I would not dare to face Dan's exams without a copy of JLS, SDK Docs, etc. ;-)
His exams are wonderful to grab the theory once you have read it.
The problem I have found with this question is that the programmer gives no clue about what the AssertionError is doing. For instance, a string argument for AssertionError constructor like "should never happen", or "wrong argument" would have conveyed the test taker the purpose of the Error.
If the AssertionError is checking arguments to public methods it could not be replaced with a assert. However I prefer an IllegalArgumentException because its purpose is clearer. Also why to use Errors at all? throw an exception. Errors are "serious problems that a reasonable application should not try to catch.".
Though it might seem that the check is about some internal state, these fields are publicly accesible. Thus, the Error is really checking arguments to public methods. The AssertionError cannot be replaced with an assert, because assertions might not be always enabled.
 
Alton Hernandez
Ranch Hand
Posts: 443
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Assuming that the method m1() is coded this way:

I would assume now this has become a control-flow invariant case, which would make the comment replaceable by an assert statement. So what makes this version of the method differs from others? They are all doing the same thing except that there seems to be different assumptions made by the programmer. So if this is how one would determine when an assert statement should used, then it becomes very subjective, isn't it?
[ August 10, 2003: Message edited by: Alton Hernandez ]
 
Jose Botella
Ranch Hand
Posts: 2120
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If the methods in the example were not public I would say yes. Because they are I think they cannot be tested with an assert. Note that even if you are thinking about flow-control assumptions, the checks performed are about arguments to public methods. I think this feature takes precedence because the programmer who wrote F cannot be sure how a client of F will use it.

Anyway, notice that the answer of the question could be that is not possible just to replace throw with an assert because a return is also needed.
The use of assertions cannot be a subjective matter. When in doubt use a string to the assertion in order to remember its purpose.
 
Marlene Miller
Ranch Hand
Posts: 1392
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
In all three of your examples, the assumption being tested is both an internal invariant and a control flow invariant.
The assumption is an internal invariant, because the programmer believes the variables b1, b2, b3 will only have some triplets of values and not others.
The assumption is a control flow invariant, because the programmer believes the place in the code will never be reached.
Even the assertion guide admits their examples of internal invariants are also control flow invariants. They do not say this will always be the case.
[ August 10, 2003: Message edited by: Marlene Miller ]
 
Marlene Miller
Ranch Hand
Posts: 1392
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well, how do I know the programmer believes this? It depends on what the contract of the method is? It depends on what the specification of the return values of this method is?
But no documentation came with this method. So, as programmers do, we look at the code and say, obviously the programmer does not expect two of the variables to be true at the same time.
[ August 10, 2003: Message edited by: Marlene Miller ]
 
Jose Botella
Ranch Hand
Posts: 2120
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have found applicable this example in The Tutorial JDK 1.4 by Gregory Travis.


Rule: do not use assertions to enforce public usage patterns or protocols
The following public class can be in one of two states: open or closed. It is an error
to open a Connection that is already open, or to close one that is already closed.
However, we would not use an assertion to ensure that these mistakes are not made:
public class Connection
{
private boolean isOpen = false;
public void open() {
// ...
isOpen = true;
}
public void close() {
// BAD!!
assert isOpen : "Cannot close a connection that is not open!";
// ...
}
}
The programmer has attempted to enforce the requirement that a Connection can
only be closed if it is already open.
This usage is valid if and only if the Connection class were a private class, or
were otherwise guaranteed to be invisible to the outside, and if we were willing to
ensure and assume that any code that uses this class is written correctly. In this case,
it would be legitimate to enforce this assumption with an assertion.
However, if the Connection class is used publicly, it would not be surprising to
find a bug in which someone tried to close a Connection that wasn�t open in the
first place. In this case, a regular exception would be better:
public class Connection
{
private boolean isOpen = false;
public void open() {
// ...
isOpen = true;
}
public void close() throws ConnectionException {
if (!isOpen) {
throw new ConnectionException(
"Cannot close a connection that is not open!" );
}
// ...
}
}
If you go the other route, and attempt to ensure that this code is only called from
call sites you control, think twice. Any code you write now may be used or reused
later in a different configuration. Anything can happen after the initial revision, so
it�s best to be on the safe side. Using an explicit exception provides the most information
to a frustrated programmer down the line.

 
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think that the original code is note a good use of assert, or AssertionError. The "unreachable" code is reachable if more than one setB[n]() method has been set to true. As such, we're really relying on other coders not to call those methods if they're considered inappropriate. And so it would be better to throw something like IllegalStateException instead. Preferably at the time the second set() method is called; don't wait until later. Or each set() method could set the other two variables to false, if they're supposed to be mututally exclusive. E.g.
or
These should of course be well-documented, as this sort of behavior is not what you normally expect of a set() method. Perhaps something like this is more appropriate:

Without something like these alternatives, I'm not sure it's productive to worry much about preserving the original programmer's intent here; it was misguided anyway.
However, going back to the original question: if we accept the original logic that assert can be disabled, but AssertionError cannot - then Alton's proposed replacement code is exactly equivalent in functionality to the original code, and as such, it's no more eligible to be replaced by assert than the original was. There is absolutely no difference in functionality between

and
 
Alton Hernandez
Ranch Hand
Posts: 443
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi all,
Thank you for all your replies.


Originally posted by Jose Botella:

Note that even if you are thinking about flow-control assumptions, the checks performed are about arguments to public methods. I think this feature takes precedence because the programmer who wrote F cannot be sure how a client of F will use it.

Originally posted by Marlene Miller:

Well, how do I know the programmer believes this? It depends on what the contract of the method is? It depends on what the specification of the return values of this method is?

Originally posted by Jim Yingst:

Without something like these alternatives, I'm not sure it's productive to worry much about preserving the original programmer's intent here; it was misguided anyway.



So what then determines if a statement or comment is replaceable by an assert statement? Is it based on the programmer's assumptions or in the correctness of his/her assumptions?
In the original method, the programmer assumes that there is a strong possibility that more than one of the variables, b1,b2,& b3, would be true, so that is why he/she is prepared to throw an exception. In the 3rd version of the method, the programmer believes that this will not happen so the programmer is putting a comment there instead. But of course, if you would look at the entire code, and considering that the method is public, then this assumption is incorrect. But even private methods are not immune to wrong assumptions.

Every time I see an assert statement, I can't help but think that the programmer is not so sure with his/her assumptions - sure enough not to check the assumption all the time, and yet not so sure enough not to check it at all.
[ August 12, 2003: Message edited by: Alton Hernandez ]
 
Jose Botella
Ranch Hand
Posts: 2120
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


So what then determines if a statement or comment is replaceable by an assert statement?


Simply if the assert statement is a correct use of the assertion facility.
You can read about the matter in The Tutorial JDK 1.4 donwloadable from javalobby.org
 
Jim Yingst
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So what then determines if a statement or comment is replaceable by an assert statement? Is it based on the programmer's assumptions or in the correctness of his/her assumptions?
The original question came from Dan's exam, and his answer had nothing to do with the programmer's intent or assumptions. When he says A is replaceable with B, he means that if you replace A with B then the code will behave exactly the same way, under all circumstances. Dan's answer to the original question was that "The throw statement could be replaced by an assert statement" is FALSE, because even though the assert would be nearly[ identical in functionality to the throw, the assert could be disabled by the user, and the throw cannot. That's the only difference. We don't need to know the programmer's intent to answer this question - we just need to know how the program would behave. That's all that "replaceable" means as far as Dan's exam is concerned.
Now Alton, your first post asked what if you moved the throw statement outside the else clause. It's important to realize that this change has no effect at all on the behavior of the code. None. Nada. It's exactly the same, in terms of functionality (in all circumstances) as Dan's original code. So, when you then ask "can I then say that the throw statement can now be replaced by an assert statement?" the answer is NO. For exactly the same reason as was given originally - the throw cannot be disabled by the user; the assert can.
[B][Alton]: Assuming that the method m1() is coded this way:

I would assume now this has become a control-flow invariant case, which would make the comment replaceable by an assert statement.[/B]
Using Dan's original logic, this is even less replaceable than the original version of the problem was. In Dan's original the only difference was that the throw could not be disabled, while the assert could. Both would end up generating an AssertionError though, provided the assert was not disabled. Now however, you've got more differences. The code here does not throw an AssertionError at all, ever, so replacing it with an assert would certainly change the behavior. So I'd say no, this code is not replaceable by an assertion. Not as Dan has used "replaceable".
Realize that this is just what Dan means when he says replaceable - he's looking for exaxt functional equivalence. Other people may mean other things, which may be more subjective. To my knowledge, this phrasing isn't used in the exam anyway, which is good because if the questioner were anyone other than Dan, I wouldn't really be sure what was meant.
Now, if the question had been "is this an appropriate use of assertions (or AssertionError)?" then the other comments in this discussion would be more relevant. I believe that assert is not appropriate here, because this is a public method and assertion (or AssertError) is being used to check preconditions. If some other code sets b1 and b2 true prior to execution of m1(), or any combo of two or more b's, the assert will be triggered. So the assertion is checking the state of the F instance before m1() exectutes. That's precondition checking. From the 1.4 release notes: "The assert statement is appropriate for nonpublic precondition, postcondition and class invariant checking. Public precondition checking should still be performed by checks inside methods that result in particular, documented exceptions, such as IllegalArgumentException and IllegalStateException." Assert is simply not appropriate for this situation.
[ August 12, 2003: Message edited by: Jim Yingst ]
 
Jose Botella
Ranch Hand
Posts: 2120
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I can see now that my comment caused some confusion:


If the intention of the programmer was to check for...


The programmer here means Dan. I did not want to be so direct to mention him.
The intention of the programmer means the assumption Dan wanted to check.
Sorry to insist Jim, but don't you think that if Dan's intent would have been to test an assumption of a proper use for the assertion facility, such statement would be replaceble by an assert?
Notice I do not mean the assumption tested in this example is appropiate for an assert statement. But just to respond to this general question:


So what then determines if a statement or comment is replaceable by an assert statement?


______________________________________________________________
AssertionError is also testing the argument to a public method (i)
 
Jim Yingst
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sorry to insist Jim, but don't you think that if Dan's intent would have been to test an assumption of a proper use for the assertion facility, such statement would be replaceble by an assert?
I'm not sure what you mean. Personally I don't think Dan's intent was to test about proper use of assertions.; rather I think he was testing knowledge of the mechanical details of how they work. I.e., does the examinee understand that assertions may be disabled, but a throw can't? That's the bit of knowledge that his initial answer relies on, and it's sufficient to answer Alton's initial question as well. Beyond that, I don't really know what Dan's intent was. But since the discussion has turned to the question of proper use of exceptions, I felt it important to comment that the original problem did not demonstrate proper use of assertions, in my opinion.
 
Jose Botella
Ranch Hand
Posts: 2120
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for your contributions. Jim
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic