Structure101 V3 Released, Adds Architecture Control for Teams

Released today, the new version 3 capabilities make Structure101 a nicely rounded architectural control solution in addition to the previous structural analysis and complexity measurement capabilities.

For example:

  • You can now define layering constraints on your code-base using simple, intuitive architecture block diagrams
  • Communicate these architecture diagrams to the development team through IDE plug-ins
  • Developers get warned immediately if they make code changes that are inconsistent with the architecture
  • RSS activity feeds let you know if new architecture violations make it into a build

Also, there's a new online demo (about 13 minutes, with audio (me!)) and the version 3 Help is available online.

Full press release

Enjoy!

An Overview of Structure101 Architecture Diagrams

Structure101 lets you work with both structure (the whole code-base as it is) and architecture (the subset of the structure that you really care about, and how it should be). It lets you define the architecture in the context of the physical structure and diseminate this to the team. Architecture diagrams are what makes this possible.

Layering and composition

Structure101 architecture diagrams use a concise visual notation for representing architectural layering and composition. Here is an example of one of the architecture diagrams that we use for the structure101 code-base.

Layeringandcomposition_3
The principle is simple; components (“cells”) should only depend on components at lower levels, not in the same or higher levels.

Layering Overrides

Sometimes a top-down dependency structure is too simple to capture the intent of an architecture. "Overrides” allow you to override the default layering of a diagram. For example we may decide to allow a specific dependency from a cell to a higher-level cell. The override is shown as a green (“allowed”) arrow on the architecture diagram. (Note that enabling this “upward” dependencies practically  merges the “hiView”, “xbase” and “graph” components from the perspective of testing, reuse, development, etc.)

Layeringoverrides
A more common example is where we wish to enforce a more strict layering. For example we may want one layer to only use the next layer down, but not layers below that. Such an override is shown as red (“disallowed”) on the architecture diagram.

Combining diagrams

It is not necessary to include all aspects of an architecture on a single structure101 architecture diagram.

A common scenario is where a number of “add-ins” are distributed across several packages. For example, this diagram shows part of the structure101 architecture.

Combiningdiagrams1
It is correct, but incomplete. Classes in assemblies.X should never depend on classes in lang.Y.  We could express this by adding several overrides, but it is much cleaner to use a separate diagram for this aspect of the architecture.

The next diagram defines a number of “language packs” that do not have a direct equivalent in the physical structure (they are “pure” architecture components), but express the architectural constraint that was missing above.

Combiningdiagrams2
The combination of the 2 diagrams defines the intended architecture.

Mapping the architecture to physical code

In order to understand how a physical code-base conforms to an intended architecture, we need to map the architectural components (cells) to physical code. 

Simple patterns are used to establish this mapping. This has a number of benefits:

  • If a diagram contains a component mapped to com.headway.lang.* and the team creates a new package com.headway.lang.cobol, then the diagram is not rendered obsolete – all the classes in the new package map to the intended component.
  • I can create components with more complex mappings with expressions such as com.headway.*.test.?
  • I can create and show a component for which no code has yet been created, either by specifying no pattern or specifying the paths where I expect the new code to be implemented.
  • I can effectively “hide” physical entities from a diagram. For example any code in com.headway.lang.cobol will simply map to a component with the expression com.headway.lang.* - I do  not need to show package cobol on the diagram if I don’t want to.

Another flexibility is that a physical entity maps to the component with the most specific pattern.  For example if I include 2 components, one with com.headway.lang.* and the other with the expression com.headway.lang.java.*, then the class com.headway.lang.java.myClass will map to the latter. The effects of this can be at the same time subtle and powerful. For example I could move the component that maps to com.headway.lang.java.* into another “parent” altogether. 

Finally, each diagram has a (possibly empty) expression that maps to  “excluded” items. This is useful if some physical entities would otherwise undesirably map to a component in the diagram.

Once the mapping is established, any dependencies that violate the architecture is shown on the diagram as a curved dotted line as shown here between component “graph” and the higher-level package “hiView”.

Maptophysical
It is easy to discover the code-level cause of a violation by selecting it on the diagram within a structure101 client or IDE plug-in.

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.

Structure101 Supports Java 1.5

We have overhauled the byte-code parser to now pick up Java 1.5 constructs (e.g. generics and annotations), plus it is much faster.

You can download the first build that includes the new parser here.

If you currently use the structure101 IDE plug-in you may find that you get bogus warnings on "new" architectural violation when you start using the new parser. This is  because the parser is now finding a few more dependencies related to the Java 1.5 language updates, and thinks they are new compared to your reference snapshot. If it's giving you a headache, you should just republish your reference snapshot to the structure101 repository with the new parser.

Structure101 v2 goes GA today

Additions let you see complete slices of a code-base at any level, home in on structural complexity, view dependency graphs in matrix form, and map code items and groups (like tangles) through different hierarchies, slices and perspectives (more download).

Manage complexity like debt

Ben Hosking writes in Managing Complexity - The aim of Designing Code that:

"The most important part of design is managing complexity"

I like the simplicity of that. What happens if you don't manage complexity. Well, it starts to cost. Talking at OOPSLA 2004, Ward Cunningham (Mr. Wiki) compared complexity with debt:

"Manage complexity like debt," Cunningham told attendees. Using this analogy, he likened skipping designs to borrowing money; dealing with maintenance headaches like incurring interest payments; refactoring, which is improving the design of existing code, like repaying debt; and creating engineering policies like devising financial policies.

In an interview with Bill Venners (Artima), Andy Hunt (Pragmatic Programmer) extends the analogy concisely:

"But just like real debt, it doesn't take much to get to the point where you can never pay it back, where you have so many problems you can never go back and address them."

It's a lovely metaphor. But it does breaks down in one place. Project managers don't get a pile of bills through the door every month. Even if they wanted to, they can't rip them open, sum them up, compare them against income and outgoings and discover just how fragged they are, or even hell, that they can afford loads more debt!

Well it's not quite that bad. We can at least measure and sum up the complexity of items at different levels of design breakout (methods, classes, packages, subsystems and projects).  We may not be able to put a hard complexity number on the tipping point (insolvency), but we can give you a number. With this you can compare projects, monitor trends that show where it's getting more or less complex, and discover which items at what level are causing the trend.

For example here is the home page for the Structure101 Tracker web application showing the sizes and over-complexity of several projects:

Tracker

Now, correlate XS with the depth of furrow on team leaders' foreheads, and you've really got something to go on...

CAT-scan a code-base

Structure101 v2 goes beta today. With it you can walk through the code-base in slices from the class-level, to the package-level and up through the design levels, spotting tangles and seeing how far they have spread.

This is a snag of the Slice perspective with the slice selector highlighted:

Sliceselector

You can now see dependency graphs as matrices, which tend to be better for very large graphs (like slices). A value in a cell indicates a dependency from the column item to the row item. Here's the equivallent of the tangle shown as a diagram above - as a matrix (highlighted) it now fits in on the screen:

Smallmatrix

And here is a much bigger slice of all the classes in the code-base grouped by parent package (the orange areas).

Bigmatrix

Even zoomed way out, it is possible to pick out some patterns on the matrix. The rows and columns are ordered so that as far as possible items only use items below or to the right, so any dots (dependencies) above the diagonal indicate cyclic dependencies. Horizontal lines indicate heavily used items, vertical lines indicate items that use a lot of other items.

Version 2 lets you "tag" (mark) code-level items (like methods and classes), and any higher-level item (like a package) that contains tagged items is shown as tagged. This lets you tag items in one slice and then see how it maps to other slices and hierarchies. For example, you could tag a big class-level tangle in the Slice perspective and then go to the Composition perspective to see how the tangle is distributed across the package design - it would look like this:

Taggedhierarchy