BTW, one more thought on this topic:
* We're doing field injection in our code and there's a risk when doing this. The
risk is that we don't visually see how many dependencies we add to our class since
it's so easy to use.
* If we were using Constructor injection we would have a list of parameters and above 6-7
we would start to be worried. Actually Checkstyle would catch us since there's a check
on the number of parameters a method accepts.
* Thus Class Fan Out is one way to tell us that we're getting injected too many
components and that we need to introduce an intermediary component level.
* Note that there's another warning: it's the size of the Mock Expectations block
we have in our unit tests (when using AbstractMockingComponentTestCase). When it starts to
be too big it's a code smell and more specifically a design smell that we have too
many injections. The problem is that we don't have any failure on any threshold for
this so it's good that the Class Fan Out has this threshold to warn us.
Thanks
-Vincent
On Sep 10, 2012, at 4:59 PM, Vincent Massol <vincent(a)massol.net> wrote:
Hi devs,
I wanted to understand how Checkstyle computes the Class Fan out so I debugged it.
Here are my findings:
* Some classes are excluded by default:
mIgnoredClassNames.add("boolean");
mIgnoredClassNames.add("byte");
mIgnoredClassNames.add("char");
mIgnoredClassNames.add("double");
mIgnoredClassNames.add("float");
mIgnoredClassNames.add("int");
mIgnoredClassNames.add("long");
mIgnoredClassNames.add("short");
mIgnoredClassNames.add("void");
mIgnoredClassNames.add("Boolean");
mIgnoredClassNames.add("Byte");
mIgnoredClassNames.add("Character");
mIgnoredClassNames.add("Double");
mIgnoredClassNames.add("Float");
mIgnoredClassNames.add("Integer");
mIgnoredClassNames.add("Long");
mIgnoredClassNames.add("Object");
mIgnoredClassNames.add("Short");
mIgnoredClassNames.add("String");
mIgnoredClassNames.add("StringBuffer");
mIgnoredClassNames.add("Void");
mIgnoredClassNames.add("ArrayIndexOutOfBoundsException");
mIgnoredClassNames.add("Exception");
mIgnoredClassNames.add("RuntimeException");
mIgnoredClassNames.add("IllegalArgumentException");
mIgnoredClassNames.add("IllegalStateException");
mIgnoredClassNames.add("IndexOutOfBoundsException");
mIgnoredClassNames.add("NullPointerException");
mIgnoredClassNames.add("Throwable");
mIgnoredClassNames.add("SecurityException");
mIgnoredClassNames.add("UnsupportedOperationException");
* All classes in java.lang.* are excluded too
* Annotation classes are not counted
* Classes in the same package are counted (they won't appear in import since it's
in the same package so don't count imports to get class fan out)
* Static method calls are not counted. So for example StringUtils from Commons Lang never
counts for class Fan out
* Enums are not counted (no new XXX() done. That's why static method calls are not
counted too BTW)
* Classes used in class extend or implement are not counted too.
Hope it helps
-Vincent