Monday, July 16, 2007

Domain Modeling Users in Java - Part 1

Developing a domain model to ensure future flexibility is not a trivial task. One of the most common domain problems clients run into is the changing nature of what defines a "user".

In the first part of this series, I'll try to illustrate a common design mistake people make and explain how and why it causes trouble later on down the line. In the second part of this series, I'll cover a more flexible solution that overcomes the observed limitations.

As always, while this blog tends towards Java for its examples, problems covered here occur in many languages.

The Common Design Mistake

Let's examine what is typically the first and only design for a user model in an example domain (which is a simplified form of the design I've seen in the last two clients I worked with)

Figure 1
Figure 1 shows a typical user model implementation. As you can see, there is a base class User implementation and additional attributes (and methods, one would assume) are modeled as extension classes from this base. In this simple model, there are advertisers, affiliates, and partners, each with some varying attributes.

There are a couple of interesting questions already, both of which strike at the very heart of why this is a design mistake.

  1. What happens when a Partner is also an Advertiser?
  2. Are Advertiser, Affiliate, and Partner "types of user" or are they "roles played by a user"
  3. All three user "types" appear to have phoneNumber as an attribute. Assuming not all future users will have this as an attribute, how can the developer simplify this design so as not to repeat commonly used attributes all over the place?
While you may already see there is a problem with the design, anyone in doubt need only examine what comes next. With the above design, the following code will very likely be found somewhere in the business logic or UI logic:
if ( user instanceof Advertiser )
  doSomething();
else if ( user instanceof Affiliate )
  doSomethingElse();
else if ( user instanceof Partner)
  doYetAnotherThing();

So much for object-oriented design...

In part 2 of the series, I'll cover a simple object-oriented design solution that allows for future flexibility and gives solid answers to the three questions asked.

No comments: