Object Oriented Best Practices - Inheritance v Composition v Interfaces [closed]

Solution 1:

Mark, This is an interesting question. You will find as many opinions on this. I don't believe there is a 'right' answer. This is a great example of where a rigid heirarchial object design can really cause problems after a system is built.

For example, lets say you went with the "Customer" and "Staff" classes. You deploy your system and everything is happy. A few weeks later, someone points out that they are both 'on staff' and a 'customer' and they are not getting customer emails. In this case, you have a lot of code changes to make (re-design, not re-factor).

I believe it would be overly complex and difficult to maintain if you attempt to have a set of derived classes that implement all the permutations and combination of people and their roles. This is especially true given that the above example is very simple - in most real applications, things will be more complex.

For your example here, I would go with "Take another completely different approach". I would implement the Person class and include in it a collection of "roles". Each person could have one or more roles such as "Customer", "Staff", and "Vendor".

This will make it easier to add roles as new requirements are discovered. For example, you may simply have a base "Role" class, and derive new roles from them.

Solution 2:

You may want to consider using the Party and Accountability patterns

This way Person will have a collection of Accountabilities which may be of type Customer or Staff.

The model will also be simpler if you add more relationship types later.

Solution 3:

The pure approach would be: Make everything an interface. As implementation details, you may optionally use any of various forms of composition or implementation-inheritance. Since these are implementation details, they don't matter to your public API, so you are free to choose whichever makes your life simplest.

Solution 4:

A Person is a human being, whereas a Customer is just a Role that a Person may adopt from time to time. Man and Woman would be candidates to inherit Person, but Customer is a different concept.

The Liskov substitution principle says that we must be able to use derived classes where we have references to a base class, without knowing about it. Having Customer inherit Person would violate this. A Customer might perhaps also be a role played by an Organisation.