2011-04-06 25 views
10

Estoy intentando dar el salto desde el diseño y desarrollo centrado en datos a DDD y he leído a Evans y Nillson, pero sigo teniendo problemas para entender cómo debería estructurar mi capa de dominio . ¡Estoy seguro de que la naturaleza de mi proyecto actual no está ayudando!DDD real: estructurar la capa de dominio

Un poco de historia

La aplicación es una solución interna para gestionar las evaluaciones de personal. El personal de recursos humanos creará "plantillas" de evaluación que consisten en un conjunto de preguntas que el equipo lidera y los gerentes deben completar para cada uno de sus informes directos. Las respuestas se mantienen para la auditoría y revisión. Estas evaluaciones pueden ser para una amplia variedad de cosas tales como retroalimentación para las iniciativas de la compañía, evaluaciones de desempeño, etc.

La parte centrada en los datos de mi

no influir en la solución, pero destacando mi centrada en los datos mentalidad, ya tengo una visión para el esquema de base de datos y lo incluyo aquí sólo para referencia (ya que una imagen vale más que mil palabras):

enter image description here

el esquema es, como era de esperar, normalizado y no lo hace emparejar cómo los datos se manejan en mi aplicación. Y, he omitido las tablas de búsqueda y similares para tratar de mantenerlo al mínimo para el problema en cuestión.

Los casos de uso

El primer caso de uso es para recuperar y mostrar una lista de evaluaciones que un usuario necesita para completar. Esto se mostrará cuando el usuario ingrese por primera vez a la aplicación y, al principio, parece que sería relativamente fácil, pero hay dos inconvenientes: 1 - las evaluaciones se basan en el tiempo, por lo que pueden ser requeridas mensualmente, anualmente o cada 'x' número de años basado en la Fecha de Aniversario del empleado; y, 2: los usuarios pueden guardar una evaluación en curso y completarla más tarde. Como resultado, la lista debe contener las evaluaciones pendientes y las que están en progreso.

A continuación, cuando el usuario selecciona una evaluación para realizar, necesito recuperar todas las preguntas para esa evaluación (la versión actual) para que pueda mostrarlas al usuario. En cualquier punto durante la evaluación, el usuario puede guardar los resultados actuales. Solo después de que se haya completado toda la evaluación, en realidad puede ser 'enviada' o confirmada.

En tercer lugar, Recursos Humanos necesita una forma de volver a generar la evaluación con las respuestas proporcionadas por el supervisor.

Finalmente, HR puede crear y modificar evaluaciones, y están versionadas. Por lo tanto, cada vez que alguien modifica una evaluación, se crea una nueva versión y esa se convierte en la plantilla para las NUEVAS evaluaciones que se realizan (las evaluaciones en progreso continúan usando su plantilla original).

Modelo El dominio

Trabajar fuera de orden, tiene sentido para mí que voy a tener una entidad de evaluación que es una raíz agregado para satisfacer el cuarto caso de uso. Tendrá una colección secundaria de entidades de sección que, a su vez, tendrá una colección secundaria de entidades de pregunta. Son todas las entidades porque tienen identidad (¿sí?). La evaluación es el objeto que el código consumidor usa para persistencia, validación, etc. (aunque las entidades de Sección y Pregunta se validan a sí mismas y acumulan el estado a la Evaluación raíz).Mi objetivo es hacer el resumen de versiones del consumidor e implementarlo en la capa de persistencia de datos (¿buena o mala idea?)

Esto significa que también tendré un RecoveryRepository que maneja la persistencia para mí y, posiblemente, una AssessmentFactory eso crea una nueva evaluación cuando sea necesario.

El problema mayor viene con los otros casos de uso. ¿Tengo una raíz agregado de evaluación de empleados también? ¿O es simplemente una entidad?

En cuanto a los casos de uso, necesito utilizar esta información de varias maneras. Primero, cuando estoy generando la lista de evaluaciones para mostrar al usuario, no solo debo evaluar la lista de informes directos en comparación con la frecuencia de evaluación, sino que también necesito saber si ya comencé y/o realicé una evaluación. para ese empleado. Y eso proviene de la tabla EmployeeAssessments. El otro caso es cuando un usuario realmente lleva a cabo la evaluación, en cuyo caso estoy interactuando con las tablas EmployeeAssessments and Responses.

Desde la perspectiva de la interfaz de usuario, cuando un usuario realiza la evaluación, no conocen nada de la estructura de datos interna, etc. Necesito proporcionar a la UI la lista de preguntas para que se muestre y acepte la lista de respuestas persistir. ¿Esto lleva a una segunda raíz con el repositorio que lo acompaña, etc.?

El tercer caso de uso es similar en el sentido de que el departamento de recursos humanos desea poder volver a generar la evaluación con las respuestas en una fecha posterior. Sin embargo, estoy pensando que el mismo proceso utilizado al realizar la evaluación se puede usar aquí porque la reanudación de una evaluación existente requeriría la misma información, con la única diferencia de que es la capacidad de lectura/escritura versus la de solo lectura para la HR.

¡Termine ya!

De acuerdo, he hablado lo suficiente y creo que he despejado mi cabeza de las redes de mazorca. Aprecio cualquier dirección, sugerencia, crítica, etc. Como dije, estoy tratando de dar el salto y creo que entiendo los conceptos, ahora es cuestión de aplicarlos. ¡¡¡Gracias!!!

Respuesta

5

Hice el mismo salto que usted hace unos años. Ahora estoy haciendo el salto de simple DDD vanilla a CQRS (ver cqrsinfo.com/).

Me acercaría a esto el modo CQRS, es decir, utilizará el almacenamiento de eventos y las lecturas completamente separadas de las escrituras en un nivel arquitectónico. Sin embargo, creo que la pregunta a la que se refiere está más en línea con la forma simple de DDD de vanilla, así que la responderé en este contexto.

Necesita liberarse completamente de pensar "manejado por datos". Comience con el flujo de trabajo primario. El primer y tercer uso son básicamente solo operaciones de obtención. Primero me concentraría en los casos de uso donde se cambia el estado de raíces agregado. Así que use el caso 2, es decir, "Realizar evaluación" sería un buen lugar para comenzar.

  • Como correctamente señaló, la raíz agregada sería Evaluación. Se podría crear una clase "PerformAssessmentService" (equivalente a un servicio de dominio) y su flujo de trabajo de evaluación de rendimiento existiría aquí. Este flujo de trabajo estaría completamente bajo prueba en el que todas las dependencias, como los repositorios, simplemente se apagaban.

  • Podría terminar escribiendo todo el flujo de trabajo de evaluación de rendimiento sin ninguna base de datos concreta/implementación de UI, etc.Toda la lógica de negocio está orquestada en este servicio de dominio y toda la lógica existe en su entidad de evaluación y otras entidades asociadas.

  • pasar al caso siguiente uso - tal vez utilizar el caso 4 - modificar las evaluaciones (lo mismo que el anterior de nuevo)

  • dejar las cosas periféricos tales como repositorios/base de datos, interfaz de usuario, etc., hasta lo más tarde posible en su implementación. Su importante para encerrar a toda la lógica de negocio en su dominio primero - y luego manejar sus preocupaciones periféricas del dominio - es mucho más barato/más eficiente (en mi experiencia)

Tenga en cuenta que no hay una manera correcta de haz esto, esto es solo una sinopsis de cómo, en general, abordaría el proyecto anterior. La clave aquí es que el dominio es realmente el conductor detrás de todo lo que se implementa ...

+0

Bien, estoy contigo. Centrémonos en el primer caso de uso donde necesito generar la lista de evaluaciones pendientes o en progreso para el usuario actual. Estoy luchando con qué parte de la lógica para resolver si se incluye una evaluación debería estar en la capa de dominio frente a lo que podría hacerse fácilmente en SQL. ¿Realmente quiero que el objeto de dominio Evaluación contenga una lista de objetos AssessmentVersion y que mi clase Specification cree una Expression que use "evaluation.Versions" para que toda la lógica esté en el código? – SonOfPirate

+0

Además, pienso que tendré un AssessmentService que expone un método ListMyDueAssessments() que crea una instancia de la clase MyDueAssessmentSpecification y la pasa al método AssessmentRepository.Find (spec). Find() devuelve una lista de objetos de evaluación que satisfacen la expresión proporcionada por la clase de especificación. ¿Estoy en el camino correcto? ¿Qué pasa con la devolución de una clase AssessmentInfo que es una versión más liviana y aplanada, esto es consistente con DDD? – SonOfPirate

0

Comenzaría con un prototipo rápido y sucio que utiliza repositorios en memoria. Entonces obtendrás una mejor idea si vas por el camino correcto.

+0

Eso es, lamentablemente, exactamente lo que estoy haciendo que ha llevado a estas preguntas. ¿Puedes explicar por qué ingresaste en repositorios? – SonOfPirate

Cuestiones relacionadas