Por ejemplo, tengo una clase llamada entidad que se parece a

public class Entity {
   private User userCreated;
   private Date dateCreated;
   private User userModified;
   private Date dateModified;
}

Luego tengo mi clase de usuario que en realidad es hija de Entity

public class User extends Entity {
    private String username;
}

Tengo la sensación de que hay un bucle en la relación, pero el objeto está relacionado de esta manera en mi sistema, ya que en todos mis datos es una Entidad, y todas mis entidades son creadas por el Usuario, incluido mi Usuario, por lo que mi Usuario es un Entidad.

He probado los códigos y funciona, y mi pregunta es, ¿es malo este diseño? Si es malo, ¿hay alguna forma mejor de implementarlo?

2
Lance 26 oct. 2018 a las 11:17

4 respuestas

La mejor respuesta

No hay nada malo en esto en general. Solo es una mala práctica si una clase base contiene lógica que requiere el conocimiento de todas sus subclases (por ejemplo, para decidir qué instancia devolver en alguna llamada al método), ya que eso puede romper la clase base (o forzarla para actualizarse) cada vez que se introduce una nueva subclase.

Por otro lado, el JDK en sí contiene ejemplos de clases que se refieren a sus subclases.

Por ejemplo (quizás eso sea un poco de trampa), la clase Object contiene referencias a String y Class, que son sus subclases.

Si su relación de clase lo requiere, no tiene nada de malo.

3
Eran 26 oct. 2018 a las 08:24

Necesita agregar abstracción solo si existe en su dominio comercial. Haga las siguientes preguntas: ¿es una entidad de usuario o solo un nombre de usuario (que es solo una cadena)? No se olvide del YAGNI principio.

0
Alex T 26 oct. 2018 a las 08:33

En general, no desea dependencias bidireccionales y tampoco desea que la clase base conozca sus subclases, sino solo lo contrario, porque todas ellas pueden crear un fuerte acoplamiento entre clases, es decir, los cambios en cualquier lado pueden tener consecuencias en ambos lados.
Pero eso no significa que nunca quieras usar este acoplamiento.
A veces este acoplamiento no es deseable, pero a veces es deseable y aquí parece ser un acoplamiento deseable: el padre y el hijo están semánticamente muy acoplados y, por lo tanto, es muy poco probable que luego desee aislar al usuario o la entidad más independiente entre ellos.
Por lo tanto, acepta e incluso desea que este acoplamiento evite la duplicación / complejidad sin valor.

Tenga en cuenta que puede desacoplar las cosas introduciendo una interfaz para definir una Entidad, pero es mucho código para no obtener una gran cosa:

public interface EntityAble {
   User getUserCreated();
   Date getDateCreated();
   User getUuserModified();
   Date getDateModified();
  // setters
}

Para definir una entidad como:

public class Entity implements EntityAble {
   private User userCreated;
   private Date dateCreated;
   private User userModified;
   private Date dateModified;
   // override getters/setters
}

Y Usuario como:

public class User implements EntityAble {
   private String username;      
   private User userCreated;
   private Date dateCreated;
   private User userModified;
   private Date dateModified;
   // override getters/setters  
}

Ahora la Entidad está compuesta de campos de Usuario que no son una Entidad, sino mucha duplicación / LOC para no necesariamente obtener algo.
En algunos casos de uso, este diseño podría tener sentido, pero con su requerimiento real es una sobrecarga.

1
davidxxx 26 oct. 2018 a las 08:49

No hay nada inherentemente malo al respecto, en mi opinión.

Esta es realmente una versión ligeramente modificada de la pregunta "¿está bien que un objeto se contenga a sí mismo?". La respuesta es la misma en ambos casos: sí, está bien.

Por ejemplo, un nodo en una lista vinculada contendrá una referencia al nodo siguiente y anterior, por ejemplo:

class Node
{
    private Node next;
    private Node previous;
}

Y no hay nada malo en este diseño.

En su caso, User es un Entity, simplemente más especializado. Una analogía para el ejemplo anterior podría ser Node y BranchedNode.


Sin embargo, una cosa en la que puede pensar es que si un usuario requiere que un usuario los haya creado, ¿qué usuario creará el primer usuario? Una especie de situación de pollo y huevo. ¿Quizás el primer usuario tendrá userCreated y userModified igual a nulo? ¿O tal vez se señalarán a sí mismos?

1
Michael 26 oct. 2018 a las 08:38