I want to ask a question about how you would approach a simple object-oriented design problem. I have a few ideas of my own about what the best way of tackling this scenario, but I would be interested in hearing some opinions from the Stack Overflow community. Links to relevant online articles are also appreciated. I'm using C#, but the question is not language specific.
Suppose I am writing a video store application whose database has a Person
table, with PersonId
, Name
, DateOfBirth
and Address
fields. It also has a Staff
table, which has a link to a PersonId
, and a Customer
table which also links to PersonId
.
A simple object oriented approach would be to say that a Customer
"is a" Person
and therefore create classes a bit like this:
class Person {
public int PersonId { get; set; }
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
public string Address { get; set; }
}
class Customer : Person {
public int CustomerId { get; set; }
public DateTime JoinedDate { get; set; }
}
class Staff : Person {
public int StaffId { get; set; }
public string JobTitle { get; set; }
}
Now we can write a function say to send emails to all customers:
static void SendEmailToCustomers(IEnumerable<Person> everyone) {
foreach(Person p in everyone)
if(p is Customer)
SendEmail(p);
}
This system works fine until we have someone who is both a customer and a member of staff. Assuming that we don't really want our everyone
list to have the same person in twice, once as a Customer
and once as a Staff
, do we make an arbitrary choice between:
class StaffCustomer : Customer { ...
and
class StaffCustomer : Staff { ...
Obviously only the first of these two would not break the SendEmailToCustomers
function.
So what would you do?
- Make the
Person
class have optional references to aStaffDetails
andCustomerDetails
class? - Create a new class that contained a
Person
, plus optionalStaffDetails
andCustomerDetails
? - Make everything an interface (e.g.
IPerson
,IStaff
,ICustomer
) and create three classes that implemented the appropriate interfaces? - Take another completely different approach?