Whether under the name of annotations (in Java) or pragmas (in Smalltalk), developers use them increasingly as a means to encode extra information in the source code.
This information is typically orthogonal to the intention of the annotated code. For example, annotations can be used to identify the attributes that need to be persisted (like we do in Moose, or like Hibernate does to express mappings on tables), or they can be used to denote the methods that should be displayed in the user interface (like we do in Moose).
At first sight, this powerful mechanism comes at zero cost: you get to have more behavior without inferring with the base code. It’s not so, or like the saying goes: “any promise that is too good to be true, it probably is".
Every annotations adds a logical dependency between the places that define it or those that use it. Furthermore, annotations do not come alone. Typically, we get groups of annotations that work together or that offer similar behavior. It is true that the base code does not have anything directly to do with annotations, but the overall
To get an idea of what happens when we introduce annotations, I created a visualization called Annotation Constellation (available in Moose). The labels show annotations, the small squares represent classes, and the lines connect annotations with the classes defining the respective annotations. The spring layout reveals islands of annotations and related classes.
The picture below shows the shape of the default Pharo annotations (version 1.1). We can see that there are a handful of annotations, only few of them being connected.
The most used pragmas are #primitive: and #primitive:module:. Both of these annotate methods. The interesting thing is that in some classes, you get only usages of only one of these two, but there are also classes that use both.
A slightly different situation, can be seen with #version: and #version:imports:. These annotations are consistently used together.
If the base Pharo looks pretty clean, after we load Moose in it the landscape changes dramatically, as can be seen in the picture below (the image is available in larger resolution if you copy it locally). First, there are more annotations. Second, these annotations are grouped in complex clusters showing that they work closely together.
You might think that this situation is specific to Smalltalk. Please take a look at what happens in a JEE system.
The goal of the visualization is to reveal part of the extra complexity introduced by annotations in the system. I say part because there are several things that are not taken into account, like which classes depend on the defined annotations. But even this visualization shows that we cannot afford to ignore annotations if we want to understand a system as a whole.
Comments
It would be interesting to normalize the annotations (those that can be placed on different elements, e.g. on class declaration or on method), then to try to display them with a venn diagram. I say try, because it’s not always feasible, but an algo could try to infer one best venn diagram, the one that manages to visualize the maximun of annotations.
EJB should be partitionned in stateful and stateless. Beans using a persitence context should be a subset of all EJB. Data objects might be split into persistent data, or XML serializable, some of them might be in both categories. NamedQueries might be used to identify complex DAO that would be a subset of all DAOs, etc.
Looks familiar :) http://www.moosetechnology.org/?_s=rUz6pKLev4zmBXv8
Nice idea. I would have been expected to see the different types of classes separated in persistence, business and presentation layer, as they usually use different annotations. But the jee graph is far to complicated to be useful in my opinion. With some tweaking it might get better.
Thanks for the comments. The goal of this visualization is not to make sense of what is in a system, although it can be used for that if more filtering is applied. Rather, the goal was to show that there is a need to look into annotations in more details, exactly because they are complex :).
But, thanks for the suggestions.