The Registry Pattern

eXtreme Programming Markup Language (XPML) uses several XML documents that are interrelated. For example, releases refer to iterations, which refer to user stories, which might refer to use cases. These objects are referenced by name in the XML documents, and any code that deals with them needs to translate these names into real object references.

This is the situation that the Registry Pattern describes:

Objects need to contact another object, knowing only the object’s name or the name of the service it provides, but not how to contact it. Provide a service that takes the name of an object, service or role and returns a remote proxy that encapsulates the knowledge of how to contact the named object.

It’s the same basic publish/find model that forms the basis of a Service Oriented Architecture (SOA) and for the services layer in OSGi.

In XP Studio, the named objects of interest are the planning objects, e.g. releases, iterations, and such:

public interface PlanningObject {

  /**
   * @return The object's name
   */
  String getName();

  /**
   * Set the object's name.
   * @param name The name to set
   */
  void setName(String name);

  // ...
}

Any code that needs to reference such a planning object, can use the registry:

public class Registry {

  private static Registry instance;

  private final Map registry = new HashMap();

  public static synchronized Registry getInstance() {
    if (instance == null) {
      instance = new Registry();
    }
    return instance;
  }

  public synchronized Reference getReference(
      final String name) {
    final Reference result;
    if (isRegistered(name)) {
      result = registry.get(name);
    } else {
      result = new Reference(name);
      registry.put(name, result);
    }
    return result;
  }

  private boolean isRegistered(final String name) {
    return registry.containsKey(name);
  }

  public synchronized void register(
      final PlanningObject object) {
    final Reference reference = getReference(
        object.getName());
    if (!reference.hasObject() 
        || reference.getObject() != object) {
      reference.setObject(object);
    }
  }

  public synchronized void unregister(
      final PlanningObject object) {
    if (isRegistered(object.getName())) {
      final Reference reference = getReference(
          object.getName());
      if (reference.hasObject()) {
        reference.setObject(null);
      }
    }
  }

}

Note that the actual code uses Java5 generics, but WordPress’ source code formatter can’t handle that.

The planning objects use the registry to register themselves:

public class PlanningObjectImpl 
    implements PlanningObject {

  private String name = "";

  public PlanningObjectImpl(final String name) {
    setName(name);
  }

  public String getName() {
    return name;
  }

  public final void setName(final String name) {
    if (!this.name.equals(name)) {
      Registry.getInstance().unregister(this);
      this.name = name;
      Registry.getInstance().register(this);
    }
  }

  // ...
}

Now any client code can get references to the planning objects:

public class Reference {

  private PlanningObject object;
  private final String name;

  public Reference(final String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }

  public boolean hasObject() {
    return object != null;
  }

  public PlanningObject getObject() {
    return object;
  }

  public void setObject(final PlanningObject object) {
    this.object = object;
  }

}

One example of using references is with user stories, which may depend on other user stories:

public class UserStoryImpl extends PlanningObjectImpl 
    implements UserStory {

  private final Set dependsOn = new HashSet();

  public UserStoryImpl(final String name) {
    super(name);
  }

  public void addDependsOn(final String userStoryName) {
    dependsOn.add(Registry.getInstance().getReference(
        userStoryName));
  }

  public Set getDependsOn() {
    final Set result = new HashSet();
    for (final Reference reference : dependsOn) {
      if (reference.hasObject()) {
        result.add((UserStory) reference.getObject());
      }
    }
    return result;
  }

  // ...

}

That’s the basic registry pattern implementation.

The actual code in XP Studio employs some enhancements. One of them is the use of namespaces so that objects in different projects can use the same name.

Another neat trick is to override the equals() method of both PlanningObjectImpl and Reference to make sure that references and the objects they refer to are regarded as the same, which can greatly simplify some code.

Introducing XP Studio

At my organization, we use a lot of the tricks from the Agile toolbox, like unit tests (although most of us are not doing TDD), refactoring, continuous integration, collective code ownership. We also write black box tests using Selenium and HtmlUnit, but since the developers think them up and implement them, not the customers, we can’t really call them acceptance tests.

If you look at this list, you probably notice that these are all technical practices. What has been lacking so far are the more management oriented ones. But my team has now embarked on a journey to incorporate some of those.

We’re using user stories to define functionality, and deliver them in iterations. Since we’re building a product, not doing a project, our product manager plays the customer role.

The planning game wasn’t easy, since it was all so new for us. But the first iteration delivered all planned stories, the first ever deadline that the team made! Although it is far too early to declare victory, the start is promising indeed.

We do face some challenges, however. Our customer is in Kentucky, USA, while the development team is in The Netherlands. Also, I work from home about half of the time. So we’re definitely not a co-located team. This means we have to invest more in communication. We use e-mail, instant messaging and conference calls to stay in touch.

The distributed nature of our team makes capturing user stories on index cards difficult. Since we’re pretty XML focused (our department is the R&D department for XML in our company), we decided to capture the stories in XML instead and store them in our source source repository.

I know that many in the Agile community don’t like this formalization (Individuals and interactions over processes and tools), but it does have advantages. The biggest one in my book, after making distributed development possible, is that it opens up a whole lot of possibilities for automation. Remember Ubiquitous Automation?

This was the stimulus I needed to breathe some new life in one of those open source projects I participated in, but neglected lately: XP Studio. Check it out and let me know what you think.