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")))));
}
A few concepts to guide you through your (possibly) first Freud example:
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?
Freud is a static analysis tool that allows its user to easily define static analysis tests.At LMAX, we currently use Freud to test our java classes and source code, properties files, css and spring configuration (written in XML).
Why Freud?
Freud has two main advantages over other famous static analysis tools.1. It is designed as an engine where the user defines the tests. Not an application with a set of tests that you might be able to configure to your needs and possibly (if you’re really masochistic) extend. This means that unlike checkstyle it is not focused on style rules and unlike findbugs you can define your own test without wasting hours trying to figure out its internals.2. Freud code should be readable. You define a statement using the DSL, provide an iterator (what to test) and the rest is done by the analysis engine.Again, unlike other frameworks, you can read Freud’s code and actually understand what is it about.
So, how come no one else heard of it then?
Ah yes…. if only there were more hours in a day…. Freud is in its early stages.We open sourced it and are trying to add to it - The engine is complete - but the DSLs are not.Everytime we encounter a case in LMAX where static analysis can help - We add to Freud by writing the test we need and enriching the DSL.In the next posts I’ll go over more examples of what Freud can already do.But it is constantly growing and should get very soon to a state where it will live to the promises above.