6

I am working on a project (which includes JavaEE web apps and JavaSE apps) that has grown from a single developer to a team of three, and issues of readability and robustness are starting to emerge.

One glaring omission from the Java language has been fine tuned contracts, and how easily these are exposed to other developers. (By contracts I mean mostly validating method parameters and object pre/post conditions).

There are a few solutions that I am looking at, and I would like to get some feedback from others who have some practical experience.

It would seem that Java currently has two supported ways to define a contracts:

  1. The assert statement
  2. Throwing exceptions (such as IllegalArgumentException)

Asserts seem to only have value as a debugging tool. Since asserts are not enabled by default, the expectation is that developers will only rely on them during some formalized testing period, after which they are ignored.

Throwing exceptions seems like a robust option in that they allow almost any kind of checks to be made. However, the range of exceptions defined by the Java library seem to be poorly suited to defining contracts (for examply subclasses of IllegalArgumentException don't specifically with range issues, null checks etc, and subclasses of IllegalStateException appear to be concerned with network connection and file states), which forces each group to define their own range of exception classes.

But the biggest problem is that neither asserts nor exceptions explicitly map contract requirements to parameters or concepts like pre and post conditions. It is expected that the developer will manually maintain the JavaDoc comments with the code to make it clear under what conditions an assert will fail or an exception will be thrown.

It is clear to me that the standard Java libraries don't adequately support design by contract, which brings me to my questions:

Are my assumptions above correct, or have I missed some property of asserts and exceptions that actually makes them quite useful for this kind of problem?

5
  • Hi Phyxx, please see the FAQ. We generally try to avoid discussion questions or those that ask for recommendations. The questions become too broad, not constructive, and simply generate a lot of "me too" type answers. Consider editing this to narrow the scope of your question to something more specific and less about product recommendations.
    – jmort253
    Commented May 7, 2012 at 2:37
  • is this question better suited for stackoverflow.com?
    – k3b
    Commented May 7, 2012 at 7:48
  • 2
    @jmort253 My interpretation is actually that "Which technology should I learn next?" are explicitly offtopic. I edited it however and feel that it should be answerable now.
    – maple_shaft
    Commented May 7, 2012 at 13:19
  • This doesn't answer your question, but a Java developer can extend Exception and throw any kind of Exception she or he wants. Commented May 7, 2012 at 14:35
  • @maple_shaft - I think that did the trick.
    – jmort253
    Commented May 7, 2012 at 17:17

2 Answers 2

3

Your assumptions are correct. Java requires a third-party library to implement design by contract.

Here are some third-party libraries listed in the Wikipedia article on design by contract.

Contract4J, jContractor, Jcontract, C4J, Google CodePro Analytix, STclass, Jass preprocessor, OVal with AspectJ, Java Modeling Language (JML), SpringContracts for the Spring framework, Modern Jass, Custos using AspectJ,JavaDbC using AspectJ, JavaTESK using extension of Java, chex4j using javassist, or Contracts for Java, and the highly customizable java-on-contracts.

3

Usually I find that good tests plus a sensible level of runtime validation deliver most of the benefits of design-by-contract. I'm not sure it is necessarily worth bring in a whole new toolset for design-by-contract in normal Java programs.

Techniques you can use without leaving standard Java:

  • Use JUnit tests to explicitly post conditions on a wide variety of inputs
  • For any public API (i.e. one that is intended to be consumed by external users / other groups in your organisation) do runtime validation of parameters explicitly. Throw exceptions with a meaningful error message in the event of any invalid input (an IllegalArgumentException is fine, but do make sure the message makes sense!)
  • For any functions that validate their arguments, you should write JUnit tests with invalid input and verify that an exception is thrown (this is effectively a pre-condition test)
  • Write a validate() method for all complex custom objects that tests the internal state / consistency of the object and any composed sub-objects. You can call this method either during testing or at runtime to ensure that the whole structure is valid. Effectively this is an invariant check on a data structure.
  • Use asserts within functions to test for invariants during execution. These can be expensive, so it make sense to use asserts so that the checks will not be applied in production code, but these checks are very valuable during testing and debugging. Remember that your assets should also get used during your JUnit automated test suite runs, so you should pick up most logic errors during development.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.