How can I set constraint checks on the input parameters of my method?

Here is a typical way to achieve this:

public void myContractualMethod(final String x, final Set<String> y) { if ((x == null) || (x.isEmpty())) { throw new IllegalArgumentException("x cannot be null or empty"); } if (y == null) { throw new IllegalArgumentException("y cannot be null"); } // Now I can actually start writing purposeful // code to accomplish the goal of this method 

I think this solution is ugly. Your methods are quickly populated with template code that checks the valid contract of input parameters, obscuring the heart of the method.

Here is what I would like to have:

 public void myContractualMethod(@NotNull @NotEmpty final String x, @NotNull final Set<String> y) { // Now I have a clean method body that isn't obscured by // contract checking 

If these annotations look like the JSR 303 / Bean Validation Spec, it's because I borrowed them. No wonder they don't seem to work that way; they are intended to annotate instance variables, and then run the object through a validator.

Which of the many default Java development schemes provides the closest functionality to my How-To example? Excluded exceptions must be runtime exceptions (e.g. IllegalArgumentExceptions), so encapsulation is not interrupted.

+5
java validation annotations design-by-contract
source share
7 answers

If you are looking for a complete phased contract mechanism, I would consider some of the projects listed on the Wikipedia page for DBC .

If you are looking for something simpler, you can look at the Preconditions class from the google collections, which provides the checkNotNull () method. This way you can rewrite the code you sent:

 public void myContractualMethod(final String x, final Set<String> y) { checkNotNull(x); checkArgument(!x.isEmpty()); checkNotNull(y); } 
+5
source share

I saw Eric Burke's technique, which roughly resembles the following. This is an elegant use of static imports. The code reads very nicely.

To understand, here is the class Contract . It is minimal here, but can be easily filled as needed.

 package net.codetojoy; public class Contract { public static void isNotNull(Object obj) { if (obj == null) throw new IllegalArgumentException("illegal null"); } public static void isNotEmpty(String s) { if (s.isEmpty()) throw new IllegalArgumentException("illegal empty string"); } } 

And here is an example of use. The foo() method illustrates static imports:

 package net.codetojoy; import static net.codetojoy.Contract.*; public class Example { public void foo(String str) { isNotNull(str); isNotEmpty(str); System.out.println("this is the string: " + str); } public static void main(String[] args) { Example ex = new Example(); ex.foo(""); } } 

Note: when experimenting, note that there may be an error in this case in the default package. Of course, I lost the brain cells trying to do this.

+2
source share

There is a small Java Argument Validation package implemented as Plain Java. It comes with several standard checks / checks. And for those cases when someone needs their own more specific checks, he comes with some helper methods. For validations that happen several times, simply extend the ArgumentValidation interface with your own and create an implementation class that leaves the ArgumentValidationImpl class.

+1
source share

This does not directly answer your question, but I think part of your problem is that you overdid it with the check. For example, you can replace the first test:

 if (x.isEmpty()) { throw new IllegalArgumentException("x cannot be empty"); } 

and rely on Java to throw a NullPointerException if x is null . You just need to change your โ€œcontractโ€ to say that NPE is thrown for certain types of situations โ€œyou called me with illegal parametersโ€.

0
source share

Jared has pointed you to various frameworks that support DBC support for Java.
I find it best to work: just document your contract in JavaDoc (or whatever Documentationframework you use, Doxygen supports DBC tags.)
Having your code confused by so many throws and checks of your arguments is not very useful for your reader. Documentation is.

0
source share

I would use Parameter Annotations, Reflection, and a common validation class to create an application for the entire application. for example, you can encode a class method, for example:

.. myMethod (@notNull String x, @notNullorZero String y) {

 if (Validator.ifNotContractual(getParamDetails()) { raiseException.. or return .. } 

}

Class methods are "tagged" to annotate their contract requirements. Use reflection to automatically detect parameters, their values, and annotations. Send all this to the static class for verification and report it.

0
source share

Not a fully working solution, but JSR-303 has a suggestion for extending method level checking . Since this is just an extension proposal just now, JSR-303 implementations may ignore it. Finding an implementation is a little more difficult. I do not think that Hibernate Validator supports it yet, but I believe that agimatec-validation has experimental support. I have not used for this purpose, so I do not know how well they work. I would be interested to know about this if someone leaves.

0
source share

All Articles