Herencia en entidades comerciales: acceso y visualización de atributos de subclase al solicitar el tipo de clase base desde la capa de acceso a datos

(Tenga en cuenta que soy un programador relativamente inexperto. Soy consciente de que esta pregunta puede verse como demasiado abierta porque hay muchas filosofías sobre la herencia en OOP. Esta pregunta está más dirigida a mi proceso de pensamiento, es decir, ¿Me estoy acercando a este escenario de una manera que parecería correcta para un programador experimentado? ¿Qué tienen mis ideas que son obviamente precisas o inexactas?)

Estoy diseñando un sistema de inventario que realiza un seguimiento de la información sobre el hardware de TI, incluidos ordenadores, impresoras, conmutadores, enrutadores, teléfonos móviles, discos duros y otros dispositivos. Tengo una base de datos diseñada y ahora estoy en el proceso de planificar una aplicación de front-end. Tengo la intención de que la aplicación use la capa de acceso a datos, la capa de lógica comercial y las entidades comerciales. Todavía estoy en las etapas de planificación conceptual y me doy cuenta de que no debería considerar los detalles de implementación en este momento, pero mi mente tiende a avanzar rápidamente. La forma en que se supone que funciona la función de búsqueda es: el usuario ingresa los criterios de búsqueda y ejecuta la búsqueda. Se devuelve una lista de dispositivos coincidentes (o el único dispositivo coincidente). La lista de dispositivos se muestra en algún tipo de vista de lista y se muestra una vista de detalles para el dispositivo cuando se selecciona.

Me he estado preguntando si el uso de la herencia en mis eventuales entidades comerciales beneficiaría mi aplicación, o si agregaría una complejidad innecesaria... o si simplemente está mal. Mi pensamiento inicial es la configuración como se ilustra:

(Este no es el diseño real, solo un concepto simplificado para esta publicación) Además de que cada dispositivo tiene atributos específicos de tipo, cualquier dispositivo en un momento dado puede estar en uno de dos estados, activo o archivado. No sé cómo modelar esto en absoluto.

Diagrama de clases conceptual

Empecé a pensar en cómo podrían funcionar las consultas al usar esta configuración. Parece bastante simple consultar cualquier subclase específica de un dispositivo desde una capa de acceso a datos, como

Pseudocódigo:

Computer comp = getComputerBySerialNumber(sn);
List<Router> routers = getRouters();

// I can then write code to display a list of basic device information and
// additionally display all details of a computer or router when requested.
// Obviously display would be handled in a different layer.

El problema que me llevó a escribir esta pregunta es cómo manejar consultas como "obtener todos los dispositivos desde una ubicación específica".

// Returns a list of devices regardless of device type
// as long as they have the same location
List<Device> devsFromLocation = getDevicesByLocation(loc);

// List contains computers, routers, printers, etc.

¿Cómo mostraría los detalles básicos del dispositivo y luego los detalles específicos del dispositivo si tengo una referencia de objeto de clase base? (Tratando de evitar el casting loco o el uso de la reflexión). A cada uno de los dispositivos de esa ubicación le faltarían los atributos específicos de sus subtipos. Si quisiera mostrar todos los datos sobre un dispositivo en particular, tendría que volver a consultar la base de datos para obtener los campos restantes. ¿Tener que ejecutar otra consulta es una señal de diseño deficiente? Además, ¿cómo determinaría el tipo correcto de dispositivo? Posiblemente una declaración de cambio/caso grande que prueba cada Device.Type atributo, ejecutar la consulta correcta, devolver el subtipo completo y mostrar los detalles al usuario? O... ¿Es mejor devolver listas separadas que contengan objetos de subtipos completos y luego recorrer todas las listas para mostrar atributos comunes en la vista de lista y luego mostrar fácilmente los detalles del subtipo en la vista de detalles?

¿Es este un caso útil de herencia o estoy haciendo un mal uso de ella? Actualmente estoy sufriendo el problema de demasiada información. Leo todo lo posible sobre OOD, y tengo tantas reglas y pautas en mi cabeza que nunca sé si estoy haciendo algo bien. Siento que mi cerebro está buscando aplicar la información que he estado absorbiendo, así que estoy imaginando una implementación que es incorrecta. Sigo pensando en todo este asunto de programar en abstracciones para mantener el código flexible, pero en algún momento necesitas lidiar con clases concretas, ¿no? Desde mi perspectiva, la herencia tiene que ver con el comportamiento y no con los atributos. Dado que en realidad no estoy modelando ningún comportamiento (¿o sí lo estoy y simplemente no puedo verlo?) y solo estoy recopilando datos sobre los dispositivos, me resulta difícil interpretar sus relaciones. Dado que estas clases son esencialmente colecciones tontas de atributos, siento que todas deberían ser clases separadas. Por otra parte, tendré campos duplicados en todas las clases, pero ¿realmente importa en este caso?

Sé que hay toneladas de libros sobre OOD, herencia, composición, etc. He leído algunos de esos libros; Actualmente estoy leyendo un poco más y he pasado días investigando en línea. Todos usan convenientemente ejemplos obvios de herencia. Tengo pesadillas con ejemplos de frutas, animales y formas.

Gracias por tomarse el tiempo para leer mi pregunta, y gracias por cualquier información o perspectiva que pueda proporcionar. No dude en ofrecer cualquier otro consejo, información, secretos comerciales, mapas de tesoros enterrados, un barco apto para navegar y un sextante, o cualquier otra cosa que crea que podría ayudar.

preguntado el 04 de julio de 12 a las 07:07

1 Respuestas

La forma más directa es agregar un método de información a su clase base que devuelva la información y hacer que cada tipo derivado anule ese método con la información correcta.

Esto le permitiría hacer:

foreach (Base b in list)
  Write(b.Information());

Si su salida necesita ser más dinámica, considere un objeto de información de dispositivo.

Después de haber leído solo su publicación (por lo que podría haberme perdido algún detalle que hace que esta sea una mala idea), también le sugiero que haga Active State un miembro de la Device clase base, ya que Device 'tiene-un (n)' Active State (y Archive State si es lo mismo).

Aparte de eso, su diseño es agradable y simple y tiene sentido.

EDIT:

Entonces podrías tener un Report objeto en el que desea que se escriba la información, por lo que tendría:

class Device{
  write_information_to_report(Report report);
}

Esto puede ser anulado por las clases derivadas para agregar la información específica derivada.

Podrías abstraer la Report fuera también para ser algo así como InformationOutputter si realmente quisieras.

Un buen ejemplo de este tipo de cosas mirando formas de dibujo:

class Graphics{
  line(int, int, int, int) = 0;
  curve(float, float, float, float) = 0;

class OpenGLDrawer : Graphics {
  line(int, int, int, int) { // Use open gl to draw a line };
  curve(int, int, int, int) { // Use open gl to draw a line };
}

class DirextXDrawer : Graphics {
  line(int, int, int, int) { // Use directX to draw a line };
  curve(int, int, int, int) { // Use directX to draw a line };
}

class Shape{
  draw(Graphics g) = 0;
}

class Triangle : Shape{
  draw(Graphics g) { g.line(... /* draw a triangle using line */ };
}

class Circle : Shape{
  draw(Graphics g) { g.arc(... /* draw a circle using arc */};
}

Aquí puede ver que puede hacer que cada objeto sea responsable de su propia función, la funcionalidad común se puede compartir en el nivel de clase base y cualquier objeto gráfico puede dibujar cualquier forma.

Respondido 06 Jul 12, 14:07

Gracias por su respuesta. ¿Qué haría este método de información? ¿Simplemente devolver una cadena de toda la información? ¿Qué sucede si quiero vincular atributos específicos a los campos de la interfaz de usuario? - ElEscuadrónSecreto

@reallythecrash Bueno, podría hacer lo que sintiera que tenía que hacer. Idealmente, pasaría algún objeto al método de información y podría 'escribir' la información en sí mismo en ese objeto. Ampliaré esto en mi respuesta en una edición ... - sji

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.