Showing posts with label contract4j. Show all posts
Showing posts with label contract4j. Show all posts

Monday, December 31, 2007

Today's Java Irritant: Design-by-Contract Disconnects.

Design-by-contract systems enforce API behavior. In Eiffel, contracts specify both internal and external behavior, at the language level.
connect_to_server (server: SOCKET)
require
server /= Void and then server.address /= Void
-- etc.
end

This does what it looks like, at runtime. (/= == != :)

The cost of doing the same in Java is higher; most frameworks use some form of aspect-oriented programming. This isn't a bad thing in itself, but gives some people (managerial types and unimaginative programmers) the heebie-jeebies. Dealing with issues created by lots of aspects can be daunting, but are relatively straight-forward in a well-educated Java house.

Lighter-weight solutions exist, may be preferable in many situations, and are easy to grok. Putting a chunk of precondition tests at the start of a method is trivial:
public String foo(final String bar_) {
Pre.notBlank(bar_);
// etc...
}
Here, the issue is that there's no automagic way to track or document preconditions other than either manually documenting them in Javadocs (preferably through a simple doclet tag, like @pre, or whatever) , or by programmatically scanning the source and pulling out "useful" information and doing something useful with it. Neither are particularly appealing: Javadocs go stale quickly, and writing a robust source parser is non-trivial.

Another answer is to use one of the annotation- and/or aspect-based solutions (or XDoclets, but... ew?) and swallow the bitter pill that is Java, and pay the cost of educating your developers. The packages I'm currently considering are Contract4J, which uses pre-built AspectJ aspects, and SpringContracts (which is nice since most my projects use Spring).