Model your attributed sets as maps!

Maarten Winkels

At my current project we have a very detailed analysis model. Actually, detailed doesn't begin to describe it. the model describes over 200 classes. One of the many problems with such an extended analysis model is that there is no room for the developers to interpret the business model and figure out the technical design that fits it best. Implementing the classes that the analysis model describes with their properties and associations is complicated enough, and then the operations and services that are based on these classes will still need to be designed and implemented. This leads to developers simply typing out the classes as the Analysis model describes them.

One striking example is where a many to many association acquires attributes. Let's look at an example.

At some point during development, the Analysis model describes the classes Game and GameSet:

gameSetGame

These analysis classes are exactly what you think they are. A Game is a game, with name, description and any other properties the business needs. A GameSet is a collection of games, but with extra properties and associations, so it has every right to be a 'real' Analysis class. Now how do we implement this? Probably like this:

public class Game {}
public class GameSet {
   public Collection games;
   ... 
} 

This seems to work fine. A Game is probably not that interested to know in which GameSets it participates, so we'll leave the association mapped on one side (although we could add a collection of GameSets to the Game class as well). We can now easily determine which GameSet contains which games and, for example, how alike two game sets are by comparing their games:

public int overlap (GameSet other) {
   Collection overlap = this.games;
   overlap.retainAll(other.games);
   return overlap.size();
}

Then one sunny day, somebody of the analysis team decides that they need to add extra attributes to this association. Not all games in a GameSet are equal and in every GameSet a Game can behave differently. So they decide to break open this simple association and replace it with a new class GameEnjoyment (I asked them, nobody knows where THAT name came from...)

gameSetGameEnjoymentGame

And this extra class has some properties that describe some attributes of the Game in this particular GameSet. How do we implement this? A developer cluelessly following the analysis model might come up with this:

public class Game {}

public class GameEnjoyment {
   public Game game;
}

public class GameSet {
   public Collection gameEnjoyments;
   ...
}

This looks really awkward. A GameSet (a collection of Games) no longer has a relation to the Game class. Finding out which Games are in the GameSet means iterating over the GameEnjoyments and collecting the Games that these are associated with. Furthermore, from the definition of a GameSet, a GameSet can only hold one GameEnjoyment for a certain Game. A far superior implementation would look like this:

public class Game {}

public class GameEnjoyment {}

public class GameSet {
   private Map gameToGameEnjoyment;

   public Collection getGames () {
      return gameToGameEnjoyment.keySet();
   }

   public Collection getGameEnjoyments () {
      return gameToGameEnjoyment.values();
   }

   public int overlap (GameSet other) {
      Collection overlap = this.getGames();
      overlap.retainAll(other.getGames());
      return overlap.size();
   }
}

This implementation covers the meaning of the analysis classes much better, although it doesn't follow it to the letter. Furthermore it removes the need to iterate again and again through the collection of GameEnjoyments to find the associated Games of a GameSet.

I think it's very important to review an Analysis model thoroughly before deciding on the best technical design that will implement it. Mainly because they have separate goals: An Analysis model is a tool to communicate with the business. A technical design describes an API for the developers to work with. This still leaves me at my current project with an enormous Analysis model, with every small change in the business requirements cascading through dozens of classes and their related services. I think the main problem here is that the Analysis model is neither a tool for communication (nobody really understands what all those classes and properties are for, except possibly the senior architect, who is by the way retiring next year) nor does it describe a usable API for the programmers, because they have to sift through diagram after diagram to find out how the GameSet with the Games (don't forget the GameEnjoyments) finally result in GameParticipations that are related to PaymentObligations that make up a Subscription that a Relation has. I think that an Analysis model that can cover all the walls in the room when printed in Times New Roman,8pt has far passed its goal to communicate some dire business needs.

Comments (1)

  1. Viktor Grgic - Reply

    July 15, 2006 at 9:36 pm

    The problems you describe here are also described in a book called "Domain-driven design" (http://domaindrivendesign.org/book/). The solution is to have one model for everyone; instead of analysis model and technical design.
    The book also describes many patterns for dealing with complex domains and changing requirements.

Add a Comment