Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an beautiful way to assert pre-conditions in Java methods?

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?

like image 308
Salim Fadhley Avatar asked Jul 25 '11 12:07

Salim Fadhley


People also ask

Do All methods have preconditions?

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.

What is a postcondition Java?

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.

What is design by contract in Java?

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.


3 Answers

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.

like image 99
ColinD Avatar answered Nov 05 '22 02:11

ColinD


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);
}
like image 21
Arno Fiva Avatar answered Nov 05 '22 02:11

Arno Fiva


How about assert start < end. Have a look at the documentation.

like image 5
nfechner Avatar answered Nov 05 '22 02:11

nfechner