Spring Framework 2.1 M3 Architecture

Here are some architecture diagrams for Spring Framework 2.1 M3 (released yesterday). You can point the (free) structure101 plug-in at these and get IDE warnings if your customizations break Jeurgen's architecture.

Here is the top level breakout of org.springframwork:

Springarchitecture

Structure101 created this from the physical code-base. All the cells in the diagram use only lower-level cells. With such a clean structure, I did no further editing of the diagram, other than to adjust the level of nesting.

Below is a further breakout of some of the larger modules.

org.springframework.aop:

Springaop

org.springframework.beans:

Springbeans

org.springframework.jdbc:

Springjdbc

org.springframework.jms:

Springjms

org.springframework.orm:

Springorm

org.springframework.web

Springweb

You can view these online here (I'll update later today), and if you have a Spring-based project, you could install the structure101 Eclipse or IntelliJ plug-in (free from here) and point it to the Spring project in the online repository (use this url: http://www.structure101.com/java/data in the plug-in properties) and the diagrams will be visible inside your IDE, any existing violations flagged (i.e. if you have created any upward dependencies), and you will be warned if and when you make code-changes that are inconsistent with the layering.

This is a new-ish feature - please email me directly and let me know how you got on or if you have questions.

Structure101 IntelliJ Plug-in

This has just been made available for download. It displays architecture diagrams within the IDE, and warns if any code changes are inconsistent with the target architecture.

Intellijsmall

It works more or less like the structure101 Eclipse plug-in except that for now it checks for architecture violations on demand rather than automatically when you do a build.

Complexity Debt - don't "fix it", "keep a lid on it"

So you just discovered that your code-base has racked up a whole load of complexity debt. This  maybe explains why progress seems so painfully slow lately. You briefly think of suggesting a major complexity-reducing refactoring effort. This will delay the next release significantly, but foreshorten the time to the following releases. Plus a cleaner, simpler code-base will make the world a nicer happier place, right?

But you don't suggest this. You're human and self-preservation is an instict. Precisely because of the recent slow progress, there is a lot of disapointment on the whole product delivery front at the minute. Suggesting another big delay doesn't feel like the best career move just now.

Luckily there is another, more subtle way to get to that happier place without climbing out on long limbs over thin ice.

Don't repay the debt in one big painful bang - just keep a lid on it. And watch it begin to disipate as though by magic.

You use personality, charisma, leadership and/or donuts to convince your team that henceforth, they will not add any more complexity debt to the code base. Now watch what happens...

If I need to add to a method with a CC of 20 (where the threshold is say 15) and I add a couple of new paths, then I temporarily increase the complexity from 20 to 22. Uh oh, I said I wouldn't do that. No problem - I'm working on the method already, so I have a good handle on what it does. I just extract a suitable lump into a new method with a nice helpful name and bingo, I have 2 methods each within tolerance instead of 1 over. The 2 methods are simpler and easier to understand and maintain than the 1 before, and the overall code-base debt just went down a bit. Well, I feel good about this.

But wait. That one new method pushes the containing class over the class-level complexity threshold. Again, I refactor the class while its workings are in my head already (perhaps I use move field or extract class). Again, if the class was previously over-threshold, then I probably just reduced the overall debt a bit more.

The same will happen when anyone trys to add to any overly-complex package. And as the xs framework sets thresholds at every level of design breakout, the developers are relieved of the temptation to "hide" complexity by pushing it up or down the hierarchy. The code-base becomes truly less complex, without anyone really trying.

This is cool enough to be named - how about "KALOI" for "keep a lid on it".

KALOI is supported by Structure101 and there is more explicit support in the pipeline. More on this later.

Structure101 v2 beta 2 released

Structure101 is for contolling architecture and structural complexity. Version 2 introduced slicing and tagging. Beta 2 adds dependency hiding and cross-perspective navigation.

New in v2 beta 2:

  • Context menus (right mouse click) have been added. This introduces the new capability to navigate easily between views (perspectives).
  • It is now possible to tag dependencies as well as items.
  • It is also possible to hide tagged dependencies – I.e. remove them from the model. This is useful for simulating structural changes.
  • Performance problems on Linux and Mac have been fixed.
  • Look and feel on Linux and Mac have been improved

Spring 2's architecture - A single dependency cycle slipped in

The Spring guys have let a single dependency cycle into their architecture. A very small flaw, but it's a perfect example of why you need to check your code-base at different levels to keep it truly tangle-free.

I did a quick analysis of the Spring Framework some time back and sure enough found their claims of a cycle-free architecture to be correct - a pleasure to behold!

The recent announcement of Spring 2.0 rc4 prompted me to point Structure101 version 2 at same and check they were keeping up the high standard they had set themselves. The Structure101 "notables" quickly took me to the org.springframework.aop package which contains the following tangle:

Springtangle_1

Ok, this is not exactly a fatal flaw, far from it, but it surprised me because I know that Juergen keeps an eye on this stuff. Then I took a look at the leaf package slice (leaf packages being packages that contain classes), and guess what? Not a single tangle.  It is only when you look at the slice one level up that the tangle is apparent:

Springtangle2

Taking a look at the leaf packages contained by these 2 packages:

Springtangle3

(The package names are relative to org.springframework.aop). The dependency between the tagged packages (blue dots) is the one causing the problem. Overlaying the parent package boundaries on this graph, you can see why it is that, although the package diagram is acyclic, dependencies between the parent packages go in both directions, making them cyclically dependent.

Springtangle4

I presume they check only at the flat-package level, which is why this one slipped through the net.

Tracking complexity debt

Un-monitored, the complexity of a code-base increases with its size. Jboss and Struts are perfect examples. However monitoring complexity helps you keep complexity debt under control, or even down to zero.

If you publish the last couple of years worth of releases of your project to a Structure101 repository, you'll probably see something like this in the Structure101 Tracker web application:

Jbossxschart

jboss over time

Structure101 matches the amount of XS to the lines of code that cause it. Unless someone pays attention to it, the same team will tend to code-in a consistent degree of complexity debt as they go - in this case they're running at a not-unusual but alarming 80%.

Struts shows a similar chart running at about 57% XS:

Strutsxschart

struts over time

I was in with the Prime Carrier guys yesterday. They've been tracking their excess complexity for several months now and it really shows.  Here's the chart for one of their projects:

Pc1

Prime Carrier project 1 over time

As you can see, XS is hugging the zero line even as the size of the code-base grows. This is why we call it "excess" (XS) - it really is excessive and totally avoidable. Occasionally a cyclic dependency (tangle) or fat class may get into the build, but it's flagged and usually fixed during the next iteration.

They recently released a new version of another product under severe deadline pressure and consciously decided to pick up a bit of short-term debt. As you can see, they're already paying it back before it incurs too much "interest":

Pc2

Prime Carrier project 2 over time

These are a great bunch of hard-nosed developers who are keeping the code-base clear of debt so they can focus on the principal - customer requirements.