Permítanme comenzar primero disculpándome por la duración de la publicación, pero realmente quería transmitir tantos detalles por adelantado para que no me tome su tiempo yendo y viniendo en los comentarios.
Estoy diseñando una aplicación siguiendo un enfoque DDD y me pregunto qué orientación puedo seguir para determinar si una Raíz Agregada debería contener otro AR o si deberían dejarse como AR independientes, "independientes".
Tomemos el caso de una aplicación simple de reloj de tiempo que permite a los empleados entrar o salir del día. La interfaz de usuario les permite ingresar su ID de empleado y PIN, que luego se valida y se recupera el estado actual del empleado. Si el empleado está actualmente registrado, la interfaz de usuario muestra un botón de "Salida de reloj"; y, por el contrario, si no están sincronizados, el botón dice "Clock In". La acción realizada por el botón corresponde también al estado del empleado.
La aplicación es un cliente web que llama a un servidor de fondo expuesto a través de una interfaz de servicio RESTful. Mi primer paso para crear URL intuitivas y legibles resultó en los siguientes dos puntos finales:
http://myhost/employees/{id}/clockin
http://myhost/employees/{id}/clockout
NOTA: Estos se utilizan después de que la ID y PIN del empleado se hayan validado y se haya pasado un "token" que representa al "usuario" en un encabezado. Esto se debe a que existe un "modo gerente" que permite que un gerente o supervisor registre o desconecte a otro empleado. Pero, por el bien de esta discusión, estoy tratando de mantenerlo simple.
En el servidor, tengo un ApplicationService que proporciona la API. Mi idea inicial para el método ClockIn es algo como:
public void ClockIn(String id)
{
var employee = EmployeeRepository.FindById(id);
if (employee == null) throw SomeException();
employee.ClockIn();
EmployeeRepository.Save();
}
Esto parece bastante sencillo hasta que nos damos cuenta de que la información de la tarjeta de tiempo del Empleado en realidad se mantiene como una lista de transacciones. Eso significa que cada vez que llamo a ClockIn o ClockOut, no estoy cambiando directamente el estado del Empleado, sino que agrego una nueva entrada en la Hoja de horas del empleado. El estado actual del Empleado (registrado o no) se deriva de la entrada más reciente en el TimeSheet.
Entonces, si voy con el código que se muestra arriba, mi repositorio debe reconocer que las propiedades persistentes del Empleado no han cambiado, pero que se agregó una nueva entrada en la Hoja de tiempo del Empleado y se inserta en el almacén de datos.
Por otro lado (y aquí está la última pregunta de la publicación), TimeSheet parece que es una Raíz Agregada, así como también tiene identidad (el ID del empleado y el período) y podría implementar fácilmente la misma lógica que TimeSheet. (ID de empleado).
Me encuentro debatiendo los méritos de los dos enfoques y, como se indicó en el párrafo inicial, me pregunto qué criterios debería evaluar para determinar qué enfoque es más adecuado para el problema.