Quiero hacer una pregunta acerca de cómo abordaría un problema de diseño orientado a objetos simple. Tengo algunas ideas propias sobre cuál es la mejor manera de abordar este escenario, pero me gustaría escuchar algunas opiniones de la comunidad Stack Overflow. También se agradecen los enlaces a artículos relevantes en línea. Estoy usando C#, pero la pregunta no es específica del idioma.Mejores prácticas orientadas a objetos - Herencia v Composición v Interfaces
Supongamos que estoy escribiendo una aplicación de tienda de videos cuya base de datos tiene una mesa Person
, con PersonId
, Name
, DateOfBirth
y Address
campos. También tiene una tabla Staff
, que tiene un enlace a un PersonId
, y una tabla Customer
que también vincula a PersonId
.
Un enfoque orientado a objetos simple sería decir que un Customer
"es un" Person
y por lo tanto crear clases un poco como esto:
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; }
}
Ahora podemos escribir una función dicen para enviar mensajes de correo electrónico a todos los clientes :
static void SendEmailToCustomers(IEnumerable<Person> everyone) {
foreach(Person p in everyone)
if(p is Customer)
SendEmail(p);
}
Este sistema funciona bien hasta que tengamos a alguien que sea tanto un cliente como un miembro del personal. Suponiendo que en realidad no quieren nuestra lista everyone
tener la misma persona en dos veces, una vez como un Customer
y otra como Staff
, hacemos una elección arbitraria entre:
class StaffCustomer : Customer { ...
y
class StaffCustomer : Staff { ...
Obviamente, solo el primero de estos dos no rompería la función SendEmailToCustomers
.
¿Qué harías?
- hacer que la clase
Person
tienen referencias opcionales a una claseStaffDetails
yCustomerDetails
? - Crear una nueva clase que contenga un
Person
, másStaffDetails
opcional yCustomerDetails
? - Haga que todo sea una interfaz (por ejemplo,
IPerson
,IStaff
,ICustomer
) y cree tres clases que implementen las interfaces adecuadas. - ¿Adoptar otro enfoque completamente diferente?
Sí, y puede elegir una implementación ahora y cambiar de opinión más adelante sin romper otro código. –