40 votes

Modèle de référentiel: comment charger paresseux? ou dois-je diviser cet agrégat?

J'ai un modèle de domaine qu'est le concept d'un Éditeur et d'un Projet.

Un Éditeur est propriétaire d'un certain nombre de Projets, et un Projet n'a pas seulement un Éditeur propriétaire, mais aussi un certain nombre de membres de l'Éditeur. Par conséquent, un Éditeur a également un certain nombre de "rejoint" les Projets.

Je prends un DDD approche pour la modélisation de cette et en utilisant le modèle de Référentiel pour la persistance. Cependant, je ne connaît pas le motif assez bien encore à déterminer comment je dois faire.

Je suis en train de travailler sur l'hypothèse que l'Éditeur et le Projet sont potentiellement dans le même ensemble, avec la racine en cours de l'Éditeur. Je peux donc obtenir un Éditeur et puis énumérer ses Projets, et pourrait à partir de là énumérer les Projets de " membre des Éditeurs.

Cependant, si je suis seulement permis de récupérer des Éditeurs de mon référentiel, n'est-ce pas ce que j'ai à charge de tous les Projets à partir du référentiel quand je reçois l'Éditeur qui détient les droits? Et si je veux un chargement différé des membres des Éditeurs, le Projet a besoin d'une référence au référentiel?

Sinon, si je divise la somme et avoir un Éditeur de référentiel et d'un dépôt de Projet, comment dois-je gérer une transaction entre les deux, comme quand un nouveau Projet est ajouté à un Éditeur? Par exemple:

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

Suis-je une mauvaise interprétation de l'intention du modèle de Référentiel?

30voto

ifatree Points 773

Suis-je une mauvaise interprétation de l'intention du modèle de Référentiel?

Je vais dire "oui", mais je sais que moi et chaque personne avec qui j'ai travaillé a demandé la même chose pour la même raison... "Vous n'êtes pas en pensant 4ème dimensions, Marty".

Simplifions un peu et le bâton avec les constructeurs au lieu de Créer tout d'abord des méthodes:

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

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

En dessous, votre projet de référentiel est toujours stocker un propriétaire valides (p.EditorId) dans les données du projet comme il a été créé, et cependant vous le re-remplir un éditeur projets, il sera là. C'est pourquoi il est une bonne pratique pour mettre toutes les propriétés requises dans les constructeurs. Si vous ne voulez pas passer l'ensemble de l'objet, l' e.Id le fera.

Et si je veux un chargement différé des membres des Éditeurs, le Projet a besoin d'une référence au référentiel?

Maintenant, quant à savoir comment re-remplir un éditeur projets sur demande, vous avez un couple de choix en fonction de ce que vous allez pour. Droite Référentiel dit que vous voulez:

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

Mais où le mettre? Pas à l'intérieur du Projet, ou de l'Éditeur, vous avez raison, ou ils devront obtenir l'accès aux dépôts et ce n'est pas bon. L'extrait ci-dessus est faiblement couplé, mais n'est pas réutilisable sur son propre. Vous avez juste atteint les limites du Modèle de Référentiel.

Next up est une Couche Adaptateur pour votre application, avec une source partagée de dépôts (StaticServiceWrapper) et une sorte de EditorAdapter objet (ou d'une Agrégation ou ce que vous feriez appel) ou vous pouvez maintenant mélanger dans les méthodes d'extension qui peut parler de tout et de tout le nécessaire dépôts couramment. Je ne l'ai pas fait exactement de cette manière dans un système de production, mais pour vous montrer un concis exemple:

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);
    }
}

Fondamentalement, une fois votre GetAll,GetById,Ajouter,mettre à Jour,Supprimer l'Objet Référentiel est fait, vous avez à quitter les associations seul et passer sur l'objet ou de la couche de la hiérarchie des pièces amusantes comme des Adaptateurs et des Caches et de la Logique Métier ("Oh, oui!").

5voto

Michael Hart Points 2338

Comment sur le fractionnement des responsabilités dans un EditorOwner et un EditorMember?

Sans connaître votre domaine, j'imagine qu'ils auraient des responsabilités différentes (par exemple, la EditorOwner peut être très riche (et peut être la somme de la racine), mais le Projet peut-être seulement besoin de savoir qu'une quantité limitée sur ses membres, de sorte que le EditorMember objet peut être assez léger.

Ces objets de domaine peut également se rapporter à des Utilisateurs, mais ce serait dans un autre contexte.

Est-ce que c'choses, ou tout simplement le rendre plus compliqué?

3voto

moffdub Points 3757

Il dépend des besoins de votre application. Si c'est un gros problème pour charger tous les Projets, pour un Éditeur, puis essayer un modèle de chargement différée comme un Proxy Virtuel.

Concernant paresseusement le chargement du membre de la rédaction d'un Projet, si vous utilisez un Proxy Virtuel, je ne vois pas le problème de l'injection de la procuration à la EditorRepository depuis je ne considère pas le proxy pour faire partie du domaine.

Si vous fractionnez la somme, vous pouvez enquêter sur l' Unité de Travail modèle comme une solution à l'atomicité. Ce problème, cependant, n'est pas unique à DDD et je suis sûr qu'il y a d'autres solutions pour les transactions comportement.

0voto

Ici, vous avez 2 des relations différentes, l'une pour la propriété et l'un pour l'adhésion.

La propriété, la relation est simple à de nombreux (un seul propriétaire pour chaque projet). L'adhésion relation plusieurs à plusieurs (beaucoup d'Éditeurs de projet en projet, de nombreux projets par l'éditeur).

Vous pouvez fournir un Propriétaire de la propriété sur le Projet de la classe, et de fournir une méthode sur la ProjectRepository pour obtenir tous les projets détenus par un Éditeur spécifique.

Pour les nombreuses relations, fournir un des Membres de propriété sur le Projet de la classe, et une méthode sur la ProjectRepository pour obtenir tous les projets contenant de l'Éditeur spécifié en tant que membre.

Il semble également que les Éditeurs et les Projets sont des entités, je serais probablement diviser le total, mais peut-être que ces termes ont une signification spécifique dans votre contexte, que faire d'un sous-total.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X