Pregunta

Soy bastante nuevo en el proceso de diseño de OO, así que tengan paciencia conmigo ...

Tengo dos entidades que necesito modelar como clases, llámelas Parent e Child (está lo suficientemente cerca del dominio del problema real). Un padre tendrá uno o más hijos: no tengo interés, en esta solicitud, en padres sin hijos.

Donde mi cerebro va a almorzar es el hecho de que necesito poder encontrar uno del otro. En mi base de datos puedo implementar esto con una relación de clave externa normal, y la naturaleza de SQL basada en conjuntos facilita la búsqueda de todos los elementos secundarios para un elemento primario determinado o el elemento primario para un elemento secundario determinado. Pero como objetos ...?

Creo creo que el padre debe llevar una colección (lista, lo que sea) de niños. También creo que cada niño debe llevar una referencia a su padre. Sin embargo, la naturaleza circular de las referencias está haciendo que me duela la cabeza.

Soy yo:

  • ¿En el camino correcto?
  • Completamente fuera de la base? Si es así, ¿qué debo hacer de manera diferente?

Es casi seguro que se implementará en VB.NET, pero todavía estoy lejos de cortar código.

Editar después de 8 respuestas:

Gracias a todos. Fue difícil elegir una sola respuesta para aceptar.

Para aclarar un par de cosas que fueron cuestionadas en las respuestas:

  • Padre e hijo son muy diferentes entidades - no hay herencia relación en absoluto. Elegí el nombres que hice porque son realmente muy cerca del mundo real dominio del problema, y ??ahora veo que es una fuente de confusión de un OO perspectiva.
  • La jerarquía tiene solo un nivel de profundidad: los niños nunca tendrán niños dentro de la aplicación.

Gracias de nuevo.

¿Fue útil?

Solución

Las referencias circulares son finas y absolutamente estándar al crear una estructura de árbol. El Modelo de objeto de documento (DOM) de HTML, por ejemplo, tiene las propiedades principales y secundarias en cada nodo en un árbol DOM:

interface Node {
    // ...
    readonly attribute Node     parentNode;
    readonly attribute NodeList childNodes;
    // ...
}

Otros consejos

Parece que estás en el camino correcto para mí. Según su modelo de dominio, los padres tienen hijos y los niños tienen padres. Es posible que deba hacer referencia entre sí.

No hay nada malo con las referencias circulares, solo debes tener cuidado con lo que haces con ellas. Donde tendrá problemas es administrar sus entidades en el lado del servidor de manera automatizada cuando las carga desde la base de datos. Por ejemplo, obtiene un objeto secundario de la base de datos con una consulta. ¿Incluye la información de los padres? ¿Incluye a los hijos de los padres?

Las herramientas ORM como Lightspeed o Entity Framework de Microsoft generalmente se ocupan de esto usando " carga diferida " directivas Al principio buscarán lo que necesita (por lo tanto, cuando obtiene un Niño, solo obtiene las propiedades del Niño y la ID del padre). Si más tarde, desreferencia al elemento primario, va y recupera las propiedades principales e instancia el objeto principal. Si más tarde aún, accede a su colección Children, luego va y recupera la información secundaria relevante y crea objetos Child para esa colección. Sin embargo, hasta que los necesite, no lo rellena.

Creo que es razonable querer poder atravesar el gráfico de objetos de esta manera. Es difícil saber si tiene una razón justificable de su publicación, pero no creo que las referencias en sí mismas demuestren un mal diseño.

Creo que estás en el camino correcto. ¿Por qué la naturaleza circular de las referencias hace que te duela la cabeza? ¿Cuál es el problema fundamental que tiene con un Parent que tiene referencias a sus hijos y un Child que tiene una referencia a su padre?

¿Estás hablando de una jerarquía de clases, donde la clase principal sabe acerca de sus clases secundarias?

Debe evitar esto a toda costa.

Por defecto, una clase secundaria sabe todo acerca de una clase primaria, porque es una instancia de la clase primaria . Pero para que una clase primaria sepa sobre sus clases secundarias, es necesario que la clase secundaria también sepa todo sobre todas las demás clases secundarias. Esto crea una dependencia entre un hijo y cada otro hijo de esa clase. Este es un escenario inmanejable que causará problemas en el futuro, incluso si puede compilarlo o ejecutarlo, lo que en muchos idiomas no será el caso.

Dicho esto, me parece que no estás tratando de hacer una jerarquía de clases, sino una jerarquía de colección, es decir, un árbol. En ese caso, sí, estás en el camino correcto; Es un paradigma común. El nodo primario tiene una colección de nodos secundarios, y el nodo secundario tiene una referencia al nodo primario.

La cosa es? ¡Son todos de la misma clase ! Aquí hay un ejemplo muy simple en C #:

public class Node
{
  public readonly Node Parent; // null Parent indicates root node
  public readonly List<Node> Children = new List<Node>();
  public Node(Node parent)
  {
     Parent = parent;
  }
  public Node()
  {
     parent = null;
  }
  public void AddChild(Node node)
  {
     Children.Add(node);
  }
}

Tengo la sensación de que esto es lo que realmente buscas. Usando este paradigma, subclasificarías el Nodo para cualquier nefasto propósito que tengas.

Si entiendo que los objetos de P contienen una matriz de objetos P- > c [] que representan niños. Y cualquier nodo P sin hijos es una hoja ... con cada P que contiene P- > P '(el padre).

La solución que especifique, con Padres que contienen referencias a los niños y viceversa, elimina la necesidad de atravesar el árbol para obtener la ascendencia de un niño y niños de un nodo. Esto es realmente un árbol en el que puede realizar todo tipo de enlaces y algoritmos para recorrerlo y enumerarlo. ¡Lo cual está bien!

Sugiero leer el capítulo de árboles en El arte de la programación de computadoras para obtener una visión excelente y profunda de las estructuras de los árboles y formas eficientes de enumerar padres e hijos.

Si los hijos deben tener un padre, generalmente solo necesito una instancia de tipo padre en el constructor hijo.

Me parece que estás en el camino hacia un mal diseño. Su arquitectura nunca debe tener referencias circulares.

Probablemente debería volver a examinar por qué sus hijos necesitan una referencia a los padres y viceversa. Me inclinaría hacia el padre que tiene una colección de hijos. Luego puede agregar funcionalidad al padre para verificar si un objeto hijo es hijo de la instancia.

Una mejor explicación del objetivo también podría ser un poco más útil ...

EDIT

Leí un poco más (y escuché comentarios) ... y resulta que estoy bastante equivocado. De hecho, las referencias circulares tienen su lugar siempre que tenga cuidado con ellas y no las deje salir de las manos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top