Aquí hay un requisito simplificado:
El usuario crea un
Question
con múltiplesAnswer
s.Question
debe tener al menos unoAnswer
.Aclaración: piense
Question
yAnswer
como en una prueba : hay una pregunta, pero varias respuestas, donde pocas pueden ser correctas. El usuario es el actor que está preparando esta prueba, por lo tanto, crea preguntas y respuestas.
Estoy tratando de modelar este ejemplo simple para que 1) coincida con el modelo de la vida real 2) para ser expresivo con el código, para minimizar el posible mal uso y errores, y para dar pistas a los desarrolladores sobre cómo usar el modelo.
La pregunta es una entidad , mientras que la respuesta es un objeto de valor . La pregunta tiene respuestas. Hasta ahora, tengo estas posibles soluciones.
[A] Fábrica adentroQuestion
En lugar de crear Answer
manualmente, podemos llamar a:
Answer answer = question.createAnswer()
answer.setText("");
...
Eso creará una respuesta y la agregará a la pregunta. Entonces podemos manipular la respuesta configurando sus propiedades. De esta manera, solo las preguntas pueden crear una respuesta. Además, evitamos tener una respuesta sin una pregunta. Sin embargo, no tenemos control sobre la creación de respuestas, ya que eso está codificado en el Question
.
También hay un problema con el 'idioma' del código anterior. El usuario es quien crea las respuestas, no la pregunta. Personalmente, no me gusta que creamos un objeto de valor y, dependiendo del desarrollador para llenarlo con valores, ¿cómo puede estar seguro de lo que se requiere agregar?
[B] Fábrica dentro de la pregunta, tome el # 2
Algunos dicen que deberíamos tener este tipo de método en Question
:
question.addAnswer(String answer, boolean correct, int level....);
Similar a la solución anterior, este método toma datos obligatorios para la respuesta y crea uno que también se agregará a la pregunta.
El problema aquí es que duplicamos el constructor de la Answer
sin razón alguna. Además, ¿la pregunta realmente crea una respuesta?
[C] Dependencias del constructor
Seamos libres de crear ambos objetos por nosotros mismos. Expresemos también el derecho de dependencia en el constructor:
Question q = new Question(...);
Answer a = new Answer(q, ...); // answer can't exist without a question
Esto le da pistas al desarrollador, ya que la respuesta no se puede crear sin una pregunta. Sin embargo, no vemos el 'lenguaje' que dice que la respuesta se 'agrega' a la pregunta. Por otro lado, ¿realmente necesitamos verlo?
[D] Dependencia del constructor, toma # 2
Podemos hacer lo contrario:
Answer a1 = new Answer("",...);
Answer a2 = new Answer("",...);
Question q = new Question("", a1, a2);
Esta es la situación opuesta de arriba. Aquí las respuestas pueden existir sin una pregunta (que no tiene sentido), pero la pregunta no puede existir sin una respuesta (que tiene sentido). Además, el 'lenguaje' aquí es más claro en esa pregunta que tendrá las respuestas.
[E] Manera común
Esto es lo que llamo la forma común, lo primero que suelen hacer las personas:
Question q = new Question("",...);
Answer a = new Answer("",...);
q.addAnswer(a);
que es la versión 'suelta' de las dos respuestas anteriores, ya que tanto la respuesta como la pregunta pueden existir sin la otra. No hay ninguna pista especial de que tengas que unirlos.
[F] Combinado
¿O debería combinar C, D, E? Para cubrir todas las formas en que se puede establecer una relación, para ayudar a los desarrolladores a usar lo que sea mejor para ellos.
Pregunta
Sé que las personas pueden elegir una de las respuestas anteriores en función de la 'corazonada'. Pero me pregunto si alguna de las variantes anteriores es mejor que la otra con una buena razón para eso. Además, no piense dentro de la pregunta anterior, me gustaría exponer aquí algunas de las mejores prácticas que podrían aplicarse en la mayoría de los casos, y si está de acuerdo, la mayoría de los casos de creación son algunas entidades similares. Además, seamos independientes de la tecnología aquí, por ejemplo. No quiero pensar si ORM se va a usar o no. Solo quiero un buen modo expresivo.
¿Alguna sabiduría sobre esto?
EDITAR
Ignore otras propiedades de Question
y Answer
, no son relevantes para la pregunta. Edité el texto anterior y cambié la mayoría de los constructores (donde fue necesario): ahora aceptan cualquiera de los valores de propiedad necesarios. Eso puede ser solo una cadena de preguntas o un mapa de cadenas en diferentes idiomas, estados, etc., independientemente de las propiedades que se pasen, no son un foco para esto;) Así que supongamos que estamos por encima de pasar los parámetros necesarios, a menos que se diga diferente. Gracias!
fuente
addAnswer
oassignAnswer
sería un lenguaje mejor que soloanswer
, espero que esté de acuerdo con esto. De todos modos, mi pregunta es: ¿seguiría con la B y, por ejemplo, tendría la copia de la mayoría de los argumentos en el método de respuesta? ¿No sería eso una duplicación?Answer
es un objeto de valor, se almacenará con una raíz agregada de su agregado. No almacena objetos de valor directamente, ni guarda entidades si no son raíces de sus agregados.En caso de que los requisitos sean tan simples que existan múltiples soluciones posibles, entonces se debe seguir el principio KISS. En su caso, esa sería la opción E.
También existe el caso de crear código que exprese algo, que no debería. Por ejemplo, vincular la creación de respuestas a la pregunta (A y B) o dar una referencia de respuesta a la pregunta (C y D) agrega un comportamiento que no es necesario para el dominio y puede ser confuso. Además, en su caso, la pregunta probablemente se agregaría con la respuesta y la respuesta sería un tipo de valor.
fuente
Yo iría ya sea [C] o [E].
Primero, ¿por qué no A y B? No quiero que mi pregunta sea responsable de crear ningún valor relacionado. Imagínese si la Pregunta tiene muchos otros objetos de valor: ¿pondría el
create
método para cada uno? O si hay algunos agregados complejos, el mismo caso.¿Por qué no [D]? Porque es lo opuesto a lo que tenemos en la naturaleza. Primero creamos una pregunta. Puede imaginar una página web donde cree todo esto: el usuario primero crearía una pregunta, ¿verdad? Por lo tanto, no D.
[E] es KISS, como dijo @Euphoric. Pero también me empieza a gustar [C] recientemente. Esto no es tan confuso como parece. Además, imagine que si la Pregunta depende de más cosas, entonces el desarrollador debe saber lo que necesita poner dentro de la Pregunta para que se inicialice correctamente. Aunque tiene razón, no existe un lenguaje 'visual' que explique que la respuesta se agrega a la pregunta.
Lectura adicional
Preguntas como esta me hacen preguntarme si nuestros lenguajes de computadora son demasiado genéricos para modelar. (Entiendo que tienen que ser genéricos para responder a todos los requisitos de programación). Recientemente estoy tratando de encontrar una mejor manera de expresar el lenguaje de negocios utilizando interfaces fluidas. Algo como esto (en idioma sudo):
es decir, tratar de alejarse de las grandes clases de * Servicios y * Repositorios a fragmentos más pequeños de lógica empresarial. Solo una idea.
fuente
Creo que te perdiste un punto aquí, tu raíz agregada debería ser tu entidad de prueba.
Y si realmente es así, creo que un TestFactory sería el más adecuado para responder a su problema.
Delegaría el edificio de Preguntas y Respuestas a la Fábrica y, por lo tanto, básicamente podría usar cualquier solución que pensara sin corromper su modelo porque se está ocultando al cliente la forma en que instancia sus entidades secundarias.
Esto es, siempre que TestFactory sea la única interfaz que use para crear una instancia de su Prueba.
fuente