Why static analysis?
Because compilers are not enough. – Many times we want to test contracts and conventions in the code which compilers cannot test and on a large scale project – manual review is impossible (and like javadoc does not stand the test of time and maintenance).
What do we mean by contracts and conventions?
Well – Really we’re talking about anything we want to enforce in the code and is not enforced by the compiler. From simple style rules to complex contracts between types of classes in are system.
Lets focus on Java in this post:
A very general contract that is actually embedded in the java platform is:
“Always override hashcode
when you override equals
“.
This is so fundamental and still – not in the language – in the sense that because we override Object
, the compiler will not warn us about it.
In Freud we test all our classes by running this analysis test:
public static FreudAnalyser equalsAlwaysGoesTogetherWithHashCode(final AnalysedObjectIterator iterator)
{
return Freud.iterateOver(Class.class).in(iterator).
assertThat(hasDeclaredMethod("equals", Object.class).and(hasDeclaredMethod("hashCode")).
or(no(hasDeclaredMethod("equals", Object.class)).and(no(hasDeclaredMethod("hashCode")))));
}
AnalysedObjectIterator
is the iterator of all the “things” we want to test – In this case, all classes.FreudAnalyser
is the engine that runs Freud test on Class objects.- The assertion methods – are coming from Freud’s Class DSL. Those are static methods that return hamcrest Matchers.
So, what is Freud?