Showing posts with label domain. Show all posts
Showing posts with label domain. Show all posts

Tuesday, July 17, 2007

Domain Modeling Users in Java - Part 2

In my previous post, I analyzed a common mistake made by developers in designing flexible domain models for users: using hierarchical (is-a) relationships to model what are actually aggregate (has-a) relationships.

In this post, I stop analyzing what went wrong and try to put forth one design that helps eliminate all of the observed problems, giving you a user domain model flexible enough to handle the changing nature of whatever business you're in.

Users Are Not Roles. Users Have Roles.

Instead of trying to model a type hierarchy for your users, consider instead that a user is simply someone who uses your system, plain and simple. Typically, users have things like usernames, passwords, email addresses, and the like. Frequently, users are tied to permissions via roles (e.g., "an administrator can do function X"). It is this role-based solution which provides the flexibility -- whether you use it for security and permissions or not is irrelevant. Let's examine.

A role is a set of motivations for a given user. And, as with any good actor, users can play many different roles -- frequently at the same time. This important distinction leads us to aggregate roles into a user rather than attempt to model by hierarchy.

Once you aggregate the roles, you begin to see the power of the solution. Now you can create hierarchical models of roles to support your business needs, and you can have a user play as many (or few) roles as necessary.

Figure 2

In Figure 2 above, we've refactored the inflexible design from the previous post. A user can now have several different Roles and a hierarchy of Role provides us with ample flexibility to use inheritance the way it was meant to be used -- to pass common attributes and methods along to children. Each Role implementor provides domain-specific information making it easy to use and clear to read.

What's even more fantastic about this methodology is something I didn't even bother to touch on in the previous post. Previously, you would have broken into tears trying to come up with a flexible database schema to go with your domain model. But with this model, you can easily map a role to a table and use an intermediate mapping to go from users to their roles. Presto, a flexible domain model and persistence strategy to boot.

On a final note, this model also meshes very well with security frameworks, where the Role implementations are likely to map to permissions -- another side benefit with no additional work.

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.