Subtle design: inheritance vs roles

February 10, 2009 at 11:04 AMAndre Loker

Let’s say you’re supposed to design a staff administration. Part of the domain model are managers and employees. Whenever you talk to your client you hear sentences such as “some of our employees are managers of a given department” or similar. Therefore, you might be tempted to model employees and managers as an “is-a” relationship, that is, you use inheritance.

isa

Let us evaluate this (really simple!) model critically. What implications does a design like this have, assuming that we are going to implement this model in a OO language like C#?

1. First of all, it implies that everyone is either an employee or a manager throughout his or her life. Although we can principally model “dynamic inheritance” in e.g. ERDs, in a language such as C# we can’t change the type of an instance all of a sudden. So, if you create a new employee, you’d have to decide whether it is in fact an employee or a manager and create an instance of the according type. As a consequence, an employee can’t be promoted to a manager and a manager can’t be degraded to a simple employee.

2. An employee can’t manage more than one department. Because one employee can’t be “multiple managers at once” (although some might which to when looking at their schedule *g*), there’s no way to let some employee manager multiple departments. Of course, in this simple model you could change the cardinality of the Manager <-> Departmennt relationship. But as soon as you for example want to assign a bonus payment to managers dependent on the manager itself and the department, simply associating multiple departments to a single manager won’t do the trick anymore.

By now you should have realized that modelling the employee-manager relationship as an “is-a” is rather inflexible. We can improve the design if we reconsider the meaning “some of our employees are managers of a given department”. What this actually means is: “some of our employees are in the role of being a manager of a given department”. Thus, being a manager is a role played by a player, ie. the employee. In general this can be modelled like:

role1As you see the player can play multiple roles, each role is played by only one player. We can easily attach or detach roles as needed without changing the type of the player. Putting the role-player relationship into our case leads to:

emproleThis design is much more flexible: employees can start as “normal” employees, can be promoted or degraded and can manage as many departments at once as required.

Identification and countability

When do you model a relationship as inheritance and when as a role-player relationship? To help you make this decision R. J. Wieringa (see references below) suggests to determine how the different entities are counted and how they are identified. If we count managers, do we count in fact employees? If so, each manager should be identified the same way as employees, e.g. by an employee number. In that case managers and employees can be modelled using inheritance. On the other hand, if managers are counted and identified differently from employees (e.g. using a management contract number) we should apply the role-player relationship.

Another example given by Mr Wieringa is the relationship between persons and passengers on a flight. Modelling passengers as a subtype of persons is probably not optimal because it would imply that a person can only be a passenger once. Passengers are most likely not counted as persons. They are probably identified by a ticket number not by e.g. a social security number.

Conclusion

Be critical if you model “obvious” is-a relationships. Do you really have a case of specialization or is the “subtype” only a role that is played by the general type?

References

Once again the concepts presented in this article are based on Design Methods for Reactive Systems by R.J. Wieringa (Amazon) (And no, I don’t get any commission for recommending this book).

Posted in: Design | Patterns

Tags: ,

Subtle design: snapshot cardinalities

February 9, 2009 at 3:02 PMAndre Loker

So your designing some application, let’s say for a library. Being the DDD guy that you are, you talk to a clerk at the library and she tells you that the system under development should save the fact that a book is lent out by a specific reader. So you choose to model that fact like this:

book You present this diagram to the library manager and he’s slightly confused: “What’s that? Our books are lent out by hundreds or thousands of people. Your design supports only one reader!”

You answer: “No, no. This model only says that a book is lent out by a single reader at a given time.

What happened here is that the library manager and you had a different idea of what portion of time the UML model represented. For you, the cardinalities shown in the diagram represented so called Snapshot Cardinalities, ie. cardinalities that occur at a single point in time. E.g. at any given moment, a book is lent by not more than one reader. The manager looked from a different perspective and interpreted the cardinalities as being historic. Throughout the lifetime of a book it is lent out by many readers, therefore his confusion.

The moral of the story

  • don’t assume that everyone looking at an UML diagram has the same idea of the semantics of numbers (or arrows for that matter).
  • be aware that we can have snapshot cardinalities as well as historic cardinalities. Most of the time you’ll use snapshot cardinalities because that’s what you’ll probably use in your code later on. Nevertheless, make that clear to the people with which you’re talking about the diagram
  • don’t mix different types of cardinalities, or be very explicit if you do so

For the interested reader I recommend R.J. Wieringa, Design Methods for Reactive Systems (Amazon)

Posted in: Patterns | Design

Tags: ,