A lot of my functions have a whole load of validation code just below the declarations:
if ( ! (start < end) ) {
throw new IllegalStateException( "Start must be before end." );
}
I'd like to precisly specify the valid ranges of certain inputs - for example a A > B, C => 1 or str_d.length() > 0.
Given that some of my functions have quite a lot of arguments which must be validated I can end up writing a lot of boiler-plate just to validate the pre-conditions. I'm writing a library which is mainly going to be used by non-technical developers, we've found that validating function inputs is the best way to help our users operate our API correctly. The sooner we raise an error the less work our customers will have to do.
Is there a more elegant method to specify the pre-conditions, post-condtions (and possibly the invariant conditions) in my methods.
A colleague told me about a feature of the Eiffel programming language which allows pre/post/invariant conditions to be described in very natural ways without repeating a lot of boilerplate code. Is there an add-on to the Java language which will allow me to use some of this magic?
Sometimes, your methods may not have preconditions. It may be that a client does not need to do or know anything at all to successfully call your method. In those cases, it's ok to not mention preconditions at all. However, every method should have a postcondition.
A postcondition is a condition that must always be true after the execution of a section of program code. Postconditions describe the outcome of the execution in terms of what is being returned or the state of an object.
Design by Contract™ is an approach to designing robust yet simple software. It provides methodological guidelines to achieve these goals without resorting to defensive programming. Instead, Design by Contract builds class invariants and pre/post validation of methods arguments and return values into the code itself.
Guava's Preconditions class is just for this. You typically use it with static imports, so your example would look like:
checkArgument(start < end, "Start must be before end");
It makes it easy to add more information to the message as well, without paying the cost of String
concatenation if the check passes.
checkArgument(start < end, "Start (%s) must be before end (%s)", start, end);
Unlike assert
statements, these can't be disabled.
Check out the Cofoja project which provides contracts for Java through annotations. It provides Pre-/Postconditions and Invariants. Also in contrast to other Java implementations it correctly handles contracts defined in parent classes/interfaces. Contract evaluation can be enabled/disabled at runtime.
Here is a code snippet from their tutorial:
import com.google.java.contract.Invariant;
import com.google.java.contract.Requires;
@Invariant("size() >= 0")
interface Stack<T> {
public int size();
@Requires("size() >= 1")
public T pop();
public void push(T obj);
}
How about assert start < end
. Have a look at the documentation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With