Patrón de repositorio: cómo lazy Lazy Load? o, ¿debería dividir este Agregado?

votos
66

Tengo un modelo de dominio que tiene el concepto de Editor y Proyecto.

Un Editor posee varios Proyectos, y un Proyecto no solo tiene un propietario del Editor, sino también un número de miembros del Editor. Por lo tanto, un Editor también tiene una serie de Proyectos unidos.

Estoy tomando un enfoque DDD para modelar esto y usar el patrón Repositorio para la persistencia. Sin embargo, todavía no logro entender el patrón lo suficiente como para determinar cómo debo hacer esto.

Estoy trabajando en la suposición de que el Editor y el Proyecto están potencialmente en el mismo agregado, con la raíz como Editor. Por lo tanto, puedo obtener un Editor y luego enumerar sus Proyectos, y desde allí enumerar a los Editores miembros de los Proyectos.

Sin embargo, si solo puedo recuperar Editores de mi repositorio, ¿no significa que tengo que cargar todos los Proyectos del repositorio cuando obtengo el Editor que los posee? Y si quiero cargar perezosamente los Editores miembros, ¿el Proyecto también necesita una referencia al repositorio?

Alternativamente, si divido el agregado y tengo un repositorio de Editor y un repositorio de proyecto, ¿cómo debo manejar una transacción entre los dos, como cuando un nuevo proyecto se agrega a un editor? Por ejemplo:

Editor e = new Editor(Editor Name);
editorRepository.Add(e);

Project p = e.CreateProject(Project Name);
projectRepository.Add(p);    // These two lines
editorRepository.Save(e);    // should be atomic

¿Estoy malinterpretando la intención del patrón Repositorio?

Publicado el 19/01/2009 a las 15:10
por usuario
En otros idiomas...                            


4 respuestas

votos
3

Depende de las necesidades de su aplicación. Si es un gran problema cargar todos los Proyectos para un Editor dado, entonces pruebe un patrón de carga diferido como un Proxy Virtual .

En cuanto a la carga lenta de los editores miembros de un proyecto, si usa el Proxy virtual, no veo ningún problema para inyectar el proxy con el EditorRepositorio ya que no considero que el proxy sea parte del dominio.

Si divide el Agregado, puede investigar el patrón Unidad de trabajo como una solución a la atomicidad. Sin embargo, este problema no es exclusivo de DDD y estoy seguro de que existen otras soluciones para el comportamiento transaccional.

Respondida el 23/01/2009 a las 01:45
fuente por usuario

votos
4

¿Qué tal dividir las responsabilidades en un editor propietario y un editor miembro?

Sin conocer su dominio, me imagino que tendrían diferentes responsabilidades; por ejemplo, EditorOwner podría ser bastante rico (y podría ser la raíz agregada), pero es posible que el Proyecto solo necesite conocer una cantidad limitada de sus miembros, por lo que el objeto EditorMiembro puede ser bastante liviano.

Estos objetos de dominio también pueden relacionarse con los usuarios, pero eso estaría en otro contexto.

¿Eso ayuda a las cosas, o simplemente lo hace más complicado?

Respondida el 23/01/2009 a las 03:55
fuente por usuario

votos
0

Aquí tienes 2 relaciones diferentes, una para la propiedad y otra para la membresía.

La relación de propiedad es simple de uno a muchos (un propietario para cada proyecto). La relación de membresía es de muchos a muchos (muchos Editores por proyecto, muchos proyectos por editor).

Puede proporcionar una propiedad Owner en la clase Project y proporcionar un método en ProjectRepository para que todos los proyectos sean propiedad de un Editor específico.

Para las muchas relaciones, proporcione una propiedad Members en la clase Project y un método en ProjectRepository para obtener todos los proyectos que contengan el Editor especificado como miembro.

También parece que los editores y los proyectos son entidades, probablemente dividiría el agregado, pero tal vez esos términos tengan un significado específico en su contexto que los haga subentidades de un agregado.

Respondida el 11/02/2009 a las 12:01
fuente por usuario

votos
30

¿Estoy malinterpretando la intención del patrón Repositorio?

Voy a decir "sí", pero debes saber que tanto yo como todas las personas con las que he trabajado hemos pedido lo mismo por la misma razón ... "No estás pensando en la cuarta dimensión, Marty".

Simplifiquemos un poco y nos apeguemos primero a los constructores en lugar de a los métodos Crear:

Editor e = new Editor("Editor Name");
e = editorRepository.Add(e);

Project p = new Project("Project Name", e);
p = projectRepository.Add(p);

Debajo, el repositorio de su proyecto siempre está almacenando un propietario válido ( p.EditorId) en los datos del proyecto a medida que se crea, y como sea que vuelva a poblar los proyectos de un editor, estará allí. Es por eso que es una buena práctica poner todas las propiedades requeridas en los constructores. Si no quiere pasar todo el objeto, solo e.Idlo hará.

Y si quiero cargar perezosamente los Editores miembros, ¿el Proyecto también necesita una referencia al repositorio?

Ahora, en cuanto a cómo volver a llenar los proyectos de un editor bajo demanda, tiene un par de opciones según lo que está buscando. Straight Repository dice que quieres:

IEnumerable<Project> list = projectRepository.GetAllProjects()
                                .Where(x => x.editorId == e.Id);

¿Pero dónde ponerlo? No dentro de Project, o Editor, tienes razón, o tendrán que acceder a repositorios y eso no es bueno. El fragmento anterior está ligeramente acoplado, pero no es reutilizable por sí mismo. Acaba de llegar a los límites del Patrón de repositorio.

El siguiente paso es una Capa de Adaptador para su aplicación, con una fuente de repositorios compartida ( StaticServiceWrapper) y algún tipo de objeto EditorAdapter (o Agregado o como quiera que los llame) o ahora puede mezclar en métodos de extensión que pueden hablar con cualquiera y todos los repositorios necesarios con fluidez. No lo hice exactamente de esta manera en un sistema de producción, sino para mostrarle un ejemplo conciso:

public static class Aggregators
{
    // one to one, easy
    public static Editor GetOwner(this Project p)
    {
        return StaticServiceWrapper.editorRep.GetEditorById(p.editorId);
    }

    // one to many, medium
    public static IEnumerable<Project> GetProjects(this Editor e) 
    { 
        return StaticServiceWrapper.projectRep.GetAllProjects()
                .Where(x => x.editorId == e.Id);
    }

    // many to many, harder
    public static IEnumerable<Editor> GetMembers(this Project p)
    {
        var list = StaticServiceWrapper.projectMemberMap.GetAllMemberMaps()
                        .Where(x => x.projectId == p.projectId);

        foreach ( var item in list )
            yield return StaticServiceWrapper.editorRep.GetEditorById(item.editorId);
    }
}

Básicamente, una vez que termine GetAll, GetById, Add, Update, Remove Object Repository, debe dejar las asociaciones por sí solas y avanzar en la jerarquía de objetos / capas a las partes divertidas como Adapters and Caches and Business Logic ( "Oh , mi! " ).

Respondida el 14/05/2009 a las 03:40
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more