Patternity is back!

After my initial attempt at doing something useful and automated around design patterns, I started working again on a brand new version of a pattern-aware tool: Patternity.

No more code generation, the focus is now on the generation of documentation artifacts (UML class and sequence diagrams, reports, enhanced Javadoc…) from the source code annotated with explicit pattern occurrences declarations. More like a research project, the goal is to investigate how a tool can be valuable for developers by being aware of the pattern and their occurrences in the source code.



Unlike the initial tool I did in 2002 that was really basic, there are many challenges and concerns to be addressed for a tool to deal with pattern in a clever way:

  1. Patterns variants: a pattern can be realized in the source code in many different ways, while still being the same pattern. For instance many patterns rely on polymorphism,which in practice can be achieved with an interface, an abstract class or just a non-final class. Many patterns also use some form of delegation, typically through an association (member field), but the pattern still holds if the delegation occurs through a lookup mechanism.
  2. Representation of patterns: creating a patterns database of a priori knowledge about patterns, including their static and dynamic aspects in a formal way that a tool can interpret – for instance to generate diagrams. Such representation must also be small enough to be feasible manually (of course only once).
  3. How to declare patterns occurrences within the code without interfering with the developer flow of work: easy and logical annotation syntax, good defaults values, code completion in IDE.
  4. How to generate useful artifacts: documentation class and sequence diagrams, reports…

Pattern metamodel

An analysis of a pattern metamodel (points 1 and 2 above) reveals other concerns that add up to the task:

  • Occurrences: What is a pattern occurrence in the code? How many occurrences of the same pattern can be considered the same occurrence? It sounds obvious that a Strategy class and all its subclasses are indeed one same pattern occurrence, but this is a priori not true for the subclasses of an Immutable class (I take a very wide definition of patterns that includes many idioms and other UML-like stereotypes).
  • Classification: Patterns usually couple a Problem (or Intent) and a Solution for it within a Context; how to create the most useful classification of patterns? (I tend to favour a classification by Problem, but this means a SecurityProxy will probably not be related with a VirtualProxy, which is not very intuitive)
  • Identification: How to identify a pattern occurrence? This is useful so that a declaration of a pattern occurrence can reference another pattern occurrence as a member part of it, just like the Bureaucracy pattern is composed of a Composite, a Mediator, a Chain of Responsibility and an Observer.

Pattern declaration

Declaration of pattern occurrences in the source code (point 3 above) also has its issues:

  • Syntax: Definition of a good syntax, easy to grasp with as little explanation as possible is hard
  • Consistency: many patterns introduce additional elements (we can call them active participants) around existing elements (passive elements) that must not know about the pattern. For instance in the Decorator pattern, the Decorator participant (role) participates actively in the pattern, whereas the decorated element should NOT be touched at all, which means that the source file for the decorated class should not be touched in the version control when adding the pattern.
  • Where to declare: in the source code, using Javadoc tags for classes or methods, or in an external file when this is more convenient (e-g to annotate third-party libraries).
Example of a declaration of a Builder pattern occurrence
Declaration of a Builder pattern occurrence

Generation of documentation artifacts

Generation of artifacts (point 4 above) from both the pattern occurrence declaration and the a priori knowledge about the pattern in the pattern database also yields its own challenges:

  • Reuse, adapt or create a Java API to generate diagrams
  • Find out a logic to interpret pattern data into diagrams or other reports
  • How to deal with huge code bases: use ellipsis, continuation marks and move details to addendum to reduce the size of a diagram


Why use patterns for documentation?

Patterns can store pre-digested documentation as “templates”, either textual or visual (diagrams); then for each actual pattern occurrence these templates can be “evaluated” to generate real and complete documentation artifacts. When we want to create useful documentation, the need for developers to inject design information in addition to the information that is already present in the code base can therefore be reduced, since a significant part of these additional information can be factored out and stored once into the patterns metamodel. I expect that patterns are a convenient concept to encapsulate reusable design information and how it can be used, however this has still to be demonstrated in practical use.

I expect that patterns can help create better diagrams than usual case tools, just because patterns know more about the design: knowing that the Bridge pattern is made of type hierarchies (to render vertically) and a delegation betweem them (to render horizontally) makes it easy to draw its class diagram this way:

Generated class diagram for the Bridge pattern
Generated class diagram for the Bridge pattern

Experimental validation

Possible validation of the utility of the tool can be:

  • Design documentation reconstitution: on a well-known and well-documented Open-Source project in Java, annotate the source code with pattern occurrences declarations, then generate a documentation. By comparing this generated documentation with the official documentation of the project one can manually assert the relevance of our approach
  • Maintenance experiments: similar to this study.
  • From the sole pattern database, generate default documentation for each “default” (generated) pattern occurrence, and compare with the patterns books, the more similar the better.

Future work

We could imagine several other potential benefits from using a pattern-aware tool:

  • The requirement to explicitly declare each pattern occurrence while coding also leads to a more motivated design, where each design decision has to be deliberate rather than more or less random or automatic. For beginners, this also represents an incitive to open the books more often to lookup “what is the pattern I am trying to do right now?” because of the need to document it.
  • Provided that the tool can link a pattern with the Problem it is supposed to address, the pattern occurrences can then trace back to their Problem, and from there, link to other alternative patterns that could have been used as well. This could be valuable to do design-level refactoring.
  • The explicit knowledge of the pattern occurrences in the code base can also give insight to configure other tools: for instance, since the patterns know what participant is supposed to know or not the other participants, this knowledge could be used to configure Jdepend automatically.

Please let me know your ideas, remarks or scepticism on this topic!

The official Patternity website still presents the old version; I expect to update it when there is good progress on the new version, however the new source code will be very soon under the same Sourceforge CVS.

Read More

Documenting the design of software using patterns?

I have experimented an approach that considers every design pattern as the recursive composition of smaller patterns. This led to a prototype tool to illustrate its benefits by generating design-level documentation of annotated source code.

Eat your own dog food

The source code of this tool itself was used as the code base to apply the tool on, in order to generate its own design documentation. The Java Doclet API was used to retrieve the Javadoc tags in the class Javadoc comments, e.g. :

@pattern KnowledgeLevel OperationLevel=MyOtherClass some free text comment…

The pattern catalogue

A subset of design patterns and some other patterns such as the Knowledge Level (Fowler) has been defined in small definitions files then loaded at tool startup. We call this set of patterns definitions the pattern catalogue.

Here is an example of the definition file for the Builder pattern, notice the declaration of the member roles at the bottom, that also declares the expected pattern kind:

Encapsulates the creation of a complex object from a source object.
@extends DesignPattern
@category DesignPattern
@category Creational
@author GoF
@book [GoF 95]  E. Gamma, R. Helm. R. Johnson, and J. Vlissides. Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley 1995.
@style ObjectOrientedProgramming
@reference [ ]
@defaultrole Builder
@role Director=TypeHierarchy
@role Builder=TypeHierarchy
@role Product=TypeSet
@role Factory=AbstractFactory

Parsing the annotations to build the pattern occurrences graph

Every time a Javadoc tag “@pattern Pattern” is met in the Javadoc part of a class, an occurrence of the corresponding pattern is created in memory, linking to the corresponding class in the Java programming language metamodel.

Whenever such pattern uses a Type Hierarchy (this is declared in the definition of the pattern), then the tool will look for every subtype of the declared (super) type in order to complete the pattern occurrence as well as possible.

Even patterns that are usually considered as atomic patterns can be explained as the composition of smaller “elemental” patterns. For instance, A Builder [GoF] usually defines an AbstractBuilder role and a ConcreteBuilder role that implements it. We can express this part of the Builder pattern as a TypeHierarchy elemental pattern in the role Builder; the supertype of the TypeHierarchy therefore represents the AbstractBuilder role, while every other concrete type of this hierarchy represents ConcreteBuilder roles.

By analogy with the members of a class, we call members patterns and member occurrences the patterns and occurrences (respectively) a pattern or occurrence is composed of. The tool totally ignore fields and methods, it only considers types (interfaces and classes).

The benefits of this approach are to reuse a bigger part of the pattern definitions through composition and to help address the variant problem.

Once the pattern occurrences graph is completely built, it is rendered into an UML class diagram using Graphviz dot. Here is an example of overview for the full project:

Example of overview diagram for the Core module of the prototype source code

In the above diagram we can see how the patterns naturally sit on top of the several type hierarchies while connecting them together. Also the relationships between patterns become very obvious, such as the Interpreter that references the Builder and the Composite sub-patterns. This suggests that such diagrams are very valuable to document the design of a code base.

Topological sort

The approach of representing every pattern as the composition of other patterns yields to directed graphes, at the pattern level (the “meta” level) and at the pattern occurrences level. One consequence is that we can apply a topological ordering on such graphs. In the current prototype we need to do a topological sort on the patterns definitions so that we can know in advance in what order to process pattern occurrences declarations: the patterns used must be built before the patterns using them.

The pattern occurrences graph can also be navigated using the usual Depth-First search or Breadth-First search. DFS is convenient to generate the Overview diagrams such as the diagram shown above, whereas BFS is convenient to drill down the design from the top to the bottom, one level at a time. This can therefore generate the following table of contents:

Patterns graph navigation index
Patterns graph navigation index

Natural language generation alternative

As an alternative to visual diagrams, a tool can also generate natural language text to communicate the exact same information. I have tried this approach using simple text templates in each pattern definitions. Each pattern therefore defines its own design description, but using variable names to be filled later with the data from the pattern occurrences graph.

The biggest work in this approach is to deal with the plural, the enumeration of collections (comma between each item but the last etc.), truncating collections that are too long, and the complete omission of a section if a pattern member is totally missing.

Here is a sample of text generation for the prototype tool itself. Notice how the structure is rigid for each pattern occurrence: Pattern name, short description, then template text evaluated with the actual types names, followed by the comment that was put after the @pattern declaration:

Design of the module Core
This module is essentially made of 9 pattern occurences: Strategy, Visitor, KnowledgeLevel, Interpreter, Builder and AbstractFactory.

The visitor design pattern is a way of separating an algorithm from an object structure. A practical result of this separation is the ability to add new operations to existing object structures without modifying those structures
This module defines a Visitor OccurrenceVisitor. comment

A Strategy object encapsulates an algorithms that can be selected on-the-fly at runtime.
This module defines the interface of a Strategy: Plugin. It enables plugins to manipulate the Patternity metamodel.

Provides one or more method(s) that encapsulate(s) the creation of object.
The type OccurrenceFactory defines the interface of an AbstractFactory that creates instances of Occurrence and TypeOccurrence.

Define a representation for a language along with an interpreter that uses the representation to interpret sentences in the language.
The type(s) Occurrence and TypeOccurrence define(s) an object representation of the considered language. The considered language describes a graph of patterns occurrences. It uses the Visitor Visitor to add new operations to the object representation without modifying this structure.

A Strategy object encapsulates an algorithms that can be selected on-the-fly at runtime.
This module defines the interface of a Strategy: Loader. Encapsulates how to load every pattern definition into the pattern.repository.


A Knowledge Level is a group of objects that describes how another group of objects should behave.
This module defines a KnowledgeLevel (also known as metamodel). It is made of two levels of objects: objects in the knowledge level, i.e. the instances of Pattern define how objects in the operational level can behave, i.e. instances of Occurrence. Typically each type in the operation level maintains a reference to its corresponding type in the knowledge level in order to know how to behave.


Later, at work, when asked to produce a design documentation targeted at other developers, I have experimented doing a similar effort manually, using nothing but patterns. I am still impatient to receive some feedback from the people that will read the resulting documentation in order to validate or infirm this approach.

Read More