Reputation: 23
Why
1) you can test postconditions with assertions in both public and non public methods
but, you are advised to
2) not use assertions to check the parameters of a public method(preconditions)?
I understand that 2) is caused by : - convention: the method guarantees that it will always enforce the argument checks(e.g. with checked exceptions) so it must check its arguments whether or not the assertions are enabled. - the assert construct does not throw an exception of the specified type. It can throw only an AssertionError, which is not quite user friendly
But I don't understand why 1) is available for public methods as well ?
Thanks.
The above questioned rephrased :) A contract is made of two parts :
- requirements upon the caller made by the class
- promises made by the class to the caller
Why Sun advises you to not use assertions as preconditions for public methods because the assertions could be disabled and then you are not checking the requirements imposed on the caller, but allows you to use assertions to test postconditions for public methods(test the return value to see you are returning a correct result) is still an enigma for me.
Put in other words, you must be very careful when enforcing requirements, but you can close an eye when verifying the promises.
Is there a technical reason for this metaphorically called "lack of ethics" that you demostrate when you enforce your client to respect the requirements, but you are not so harsh with yourself in respecting the promises ? :)
Upvotes: 1
Views: 750
Reputation: 1793
Java assertions are worthless, in my opinion.
If you read Meyer's "Object-Oriented Software Construction", he makes the case about how assertions should always be enabled - especially for production code. So, if they were always enabled by default, no matter what, it would be much better. Maybe I'm niggling with that fact a bit too much, but it's definitely a detriment - a static method is "safer" since you know it will always execute... and you can still control that with a system property. thus the default is always 'safe mode'.
DbC - It seems kind of like it would be hard to fit into the Java language - we can't put preconditions/postconditions on an interface and have them automatically work on any implementation. There are some frameworks that attempt to provide this behavior, but I haven't managed to use them in any of my projects.
I instead write my own "Contract" class full of static methods, and use a lot of assertions throughout the production code. It has methods called 'precondition' and 'postcondition', but really all you care about is assert(). there is no mechanism in Java's design whereby you can implement 'pre' and 'post' hooks on an inheritor's code. that's why some of the frameworks out there use a precompiler or AOP...
Upvotes: 0
Reputation: 2259
It's not a technical reason but a reflection of the fact that asserts aren't a design by contract implementation, which is something they say in the guide.
On balance, we came to the conclusion that a simple boolean assertion facility was a fairly straight-forward solution and far less risky.
Not everyone sees things the way that Meyers does, and Java has language goals which conflict with Eiffel's in some places. In Program Development in Java, Liskov stresses defensive programming, that is, if something can go wrong, contract-related or not, you check for it as you go. Contracts are "asserted" in comments that go at the top of the method body. Now, that book predates the addition of boolean asserts to Java, and who knows what they would have said if it had been written a couple of years later. My point is that
As you noted, the designers suggest that you could do some DbC with postconditions, nonpublic preconditions, occasional invariant checks, but they don't sound all that serious about it. Is it unethical? I understand the objection, but it's not a given that everyone will want to program with contracts in the first place.
Upvotes: 0
Reputation: 80186
You are using "assert" keyword to assert your assumptions and in case of public methods the pre-conditions should be always true (so that the method has correct data to perform its task) whether running in production or not.
Since assert will be disabled in production you can't use the assert keyword to enforce the pre-conditions of a public method so you should be throwing a unchecked exception. Now, coming to the post-conditions there is no such contract for the method (say f1) performing the task. The output of this f1() method might be a input to another method (say f2), in which case the pre-conditions in f2() might enforce the assumptions.
On a side note, I suggest looking at the google-guava library's Preconditions class for checking pre-conditions and throwing unchecked exceptions, both using a simple and intuitive API.
Upvotes: 2
Reputation: 533560
Point 2) states you shouldn't use assertions because they might not be turned on. Instead, it appears to recommend using checks which are performed every time and throw a checked exception.
If you want to throw different exceptions when assertions are enabled you can do
boolean assertions = false;
assert assertions = true;
if (assertions && myCheckHere) throw new MyExceptionOrError();
Technically, a method has parameters e.g. String name, a method is invoked passing arguments e.g. "Hello", So its the argument you want to check, the compiler will check the parameters.
Upvotes: 2
Reputation: 19717
Not sure where you got this information, but assertions are excellent for checking the parameters of public methods. They enforce the very contract that the method claims to live up to.
Upvotes: 1