5 Stimmen

Wie modellieren Sie Rollen/Beziehungen im Hinblick auf Domain Driven Design?

Wenn ich drei Entitäten habe, Projekt, Projektrolle und Person, wobei eine Person Mitglied verschiedener Projekte sein kann und verschiedene Projektrollen innehaben kann (z. B. "Projektleiter" oder "Projektmitglied") - wie würden Sie eine solche Beziehung modellieren?

In der Datenbank habe ich derzeit die folgenden Tabler: Project, Person, ProjectRole Project_Person mit PersonId & ProjectId als PK und eine ProjectRoleId als FK-Beziehung.

Ich bin hier wirklich ratlos, da alle Domänenmodelle, die mir einfallen, gegen irgendeine "DDD"-Regel zu verstoßen scheinen. Gibt es irgendwelche "Standards" für dieses Problem?

Ich habe einen Blick auf Streamlined Object Modeling geworfen und es gibt ein Beispiel, wie ein Project und ProjectMember aussehen würden, aber AddProjectMember() in Project würde ProjectMember.AddProject() aufrufen. Project hat also eine Liste von ProjectMembers, und jedes ProjectMember hat im Gegenzug einen Verweis auf das Project. Sieht für mich ein wenig verworren aus.

Update

Nachdem ich mehr über dieses Thema gelesen habe, werde ich Folgendes versuchen: Es gibt verschiedene Rollen, oder besser gesagt, Modellbeziehungen, die von einer bestimmten Rollentyp innerhalb meiner Domäne. Zum Beispiel ist ProjectMember eine eindeutige Rolle, die uns etwas über die Beziehung sagt, die eine Person innerhalb eines Projekts spielt. Sie enthält einen ProjectMembershipType, der uns mehr über die Rolle verrät, die sie spielen wird. Ich weiß mit Sicherheit, dass Personen innerhalb eines Projekts Rollen spielen müssen, also werde ich diese Beziehung modellieren.

ProjectMembershipTypes können erstellt und geändert werden. Diese können "Projektleiter", "Entwickler", "Externer Berater" oder etwas anderes sein.

Eine Person kann mehrere Rollen innerhalb eines Projekts haben, und diese Rollen können zu einem bestimmten Zeitpunkt beginnen und enden. Solche Beziehungen werden durch die Klasse ProjectMember modelliert.

public class ProjectMember : IRole
{
    public virtual int ProjectMemberId { get; set; }
    public virtual ProjectMembershipType ProjectMembershipType { get; set; }

    public virtual Person Person { get; set; }
    public virtual Project Project { get; set; }
    public virtual DateTime From { get; set; }
    public virtual DateTime Thru { get; set; }
    // etc...
}

ProjectMembershipType: z. B. "Projektleiter", "Entwickler", "Berater"

public class ProjectMembershipType : IRoleType
{
    public virtual int ProjectMembershipTypeId { get; set; }
    public virtual string Name { get; set; }
    public virtual string Description { get; set; }

    // etc...
}

3voto

Vijay Patel Punkte 16000

Ich würde folgendermaßen vorgehen:

class Person
{
  string Name { get; set; }
  IList<Role> Roles { get; private set; }
}

class Role
{
  string Name { get; set; }
  string Description { get; set; }
  IList<Person> Members { get; private set; }
}

class Project
{
  string Name { get; set; }
  string Description { get; set; }
  IList<ProjectMember> Members { get; private set; }
}

class ProjectMember
{
  Project Project { get; private set; }
  Person Person { get; set; }
  Role Role { get; set; }
}

El ProjektMitglied Klasse bringt sie alle zusammen. Dieses Modell gibt Ihnen die Flexibilität, ein und dieselbe Person verschiedenen Projekten mit unterschiedlichen Rollen zuzuordnen (z.B. könnte sie ein Entwickler in Projekt A und ein Tester in Projekt B sein).

Bitte erstellen Sie keine rollenspezifischen Klassen - diese Lektion haben wir bereits gelernt.

Ich habe eine Beispiel-Applikation um dies zu demonstrieren (auch Beziehungen gehören dazu):

  1. Laufen " bin \debug\RolesRelationshipsSample.exe "
  2. Doppelklicken Sie auf die Bibliothekssymbole, um Entitäten zu erstellen
  3. Ziehen Sie sie per Drag & Drop, um die entsprechenden Beziehungen zuzuweisen.

Sie können gerne mit dem Code spielen. Ich hoffe, Sie finden ihn nützlich.

1voto

tpdi Punkte 33618

Sie modellieren eine Many-to-many-Beziehung: An einem Projekt können viele Personen arbeiten, und eine Person kann an mehreren Projekten arbeiten.

Sie modellieren die Beziehung als Projektrolle, die nicht nur als bidirektionaler Link von Person <-> Projekt dient, sondern auch einen Rollentyp und Beginn/Ende der Besetzung dieses Rollentyps durch diese Person in diesem Projekt aufzeichnet. (Beachten Sie, dass das englische Wort "that" für die Datenbank FK oder im Code für einen Zeiger/Verweis steht).

Aufgrund dieser FKs können wir in der Datenbank den Graphen von der Person über die Projektrolle bis zum Projekt verfolgen:

select a.person_id, b.project_role_id, c.project_id
from person a join project_role b on (a.id = b.person_id)
join project c on (b.project_id = c.id)
where a.person_id = ?

Oder wir können es in die andere Richtung verfolgen, vom Projekt aus:

select a.person_id, b.project_role_id, c.project_id
from person a join project_role b on (a.id = b.person_id)
join project c on (b.project_id = c.id)
where c.project_id = ?

Im Idealfall würden wir gerne dasselbe im C#-Code tun können. Also ja, wir wollen, dass eine Person eine Liste hat, und ein Projekt eine Liste hat, und eine ProjectRole auf eine Person und ein Projekt verweist.

Ja, Project::addPerson( Person& ) sollte wirklich sein Project::addProjectRole( ProjectRole& ) es sei denn, wir beschließen, dass Project::addPerson( Person& ) ist eine Komfortmethode der Form:

void Project::addPerson( Person& p ) {
  this.addProjectRole( new ProjectRole( p, &this, RoleType::UNASSIGNED ) ;
}

Eine ProjectRole verfügt nicht über eine Liste, sondern über einen Verweis auf eine Person und einen Verweis auf ein Projekt. Außerdem hat sie als Werte ein Startdatum, ein Enddatum und einen RoleType (der entweder eine Aufzählung oder eine Klasseninstanz ist, die einen Aufzählungswert nachahmt - das heißt, es gibt nur ein Objekt pro Aufzählungstyp, und es ist zustandslos, unveränderlich und idempotent und kann daher von vielen ProjectRoles gemeinsam genutzt werden).

Das soll aber nicht heißen, dass beim Abrufen einer Person aus der Datenbank die gesamte Datenbank im Objektgraphen des Codes verifiziert werden muss; träge Proxies, die nur bei Verwendung abrufen, können uns das ersparen. Wenn wir uns nur mit der Person und nicht mit ihren Rollen (und Projekten) beschäftigen, können wir einfach die Person abrufen. (NHibernate, zum Beispiel, macht das mehr oder weniger nahtlos).

Grundsätzlich denke ich das:

1) Dies ist eine Standardmethode zur Darstellung von Many-to-Many-Beziehungen; 2) Es ist Standard, dass eine Beziehung zusätzliche Daten enthält (wann, welche Art von) und 3) Sie haben so ziemlich die richtige Idee und sind nur zu Recht gewissenhaft, wenn es darum geht, Feedback zu bekommen.

0voto

xtofl Punkte 39285

Verwechseln Sie nicht die "Beschreibung" einer Rolle mit der Rolle, die eine Person in einem Projekt hat? Das Hinzufügen des Konzepts "RoleDescription" (sozusagen eine "Rollenklasse") und von "RoleInstance"-Objekten, die sich auf tatsächliche Personen in Projekten beziehen, könnte helfen.

0voto

Jamie Ide Punkte 46985

Es handelt sich um eine Many-to-many-Beziehung mit zusätzlichen Daten, der Rolle. Wir haben eine ähnliche Struktur, nur dass in unserem Fall eine Person mehrere Rollen in einem Projekt haben kann, so dass ich mich mit denselben Fragen herumgeschlagen habe. Eine Lösung besteht darin, eine ProjectPerson-Klasse zu erstellen, die Person erweitert und die Eigenschaft role hinzufügt:

public class ProjectPerson : Person
{
    public string Role { get; set; }
}

Ihre Project-Klasse hat jetzt eine Auflistung von ProjectPerson, aber die Person-Klasse hat eine Auflistung von Project, weil es keinen Sinn macht, die Project-Klasse zu erweitern, um Rollen hinzuzufügen. Sie müssen zusätzliche Arbeit leisten (die Person in der ProjectPerson-Auflistung nachschlagen), um die Rolle für ein Project aus der Sicht der Person zu finden.

Eine zweite Lösung ist die Standardmethode zur Handhabung von Many-to-Many-Beziehungen mit zusätzlichen Daten. Erstellen Sie eine ProjectRole-Klasse und modellieren Sie sie als die Viele-Seite von zwei Eins-zu-Viele-Beziehungen von Project und Person. Das heißt, sowohl Project als auch Person haben jeweils eine Sammlung von ProjectRole.

Bei der Auswahl einer Lösung ist es wichtig zu berücksichtigen, wie gut Ihre Datenzugriffsstrategie das Modell unterstützen wird. Sie möchten Szenarien vermeiden, in denen das Laden der Sammlung für jedes Objekt in der Sammlung einen oder mehrere Abrufe in der Datenbank erfordert.

0voto

Clive Fletcher Punkte 1

Es scheint, dass es zwei Haupteinheiten gibt - Projekt und Projektmitglied. Das Projektmitglied hat die Attribute "Mitgliederrolle" und "Mitgliedsname". Jedes dieser Attribute kann zu einer Domäne gehören, d.h. zu einer Reihe von Werten, die in Nachschlagetabellen sowohl aus Bequemlichkeitsgründen als auch für die Suche gepflegt werden können. Es wird davon ausgegangen, dass jemand Informationen über alle Projektmitglieder benötigt, die eine bestimmte Rolle/Aufgabe wahrnehmen.

Anmerkung. Zu Nachschlagetabellen können Einträge hinzugefügt werden, aber normalerweise wird der Wert eines Eintrags nicht geändert. Sobald ein Wert aus der Nachschlagetabelle ausgewählt wurde, gilt er als fester Bestandteil der zugehörigen Tabelle - in diesem Fall der Tabelle Projektmitglied.

Ich würde nicht erwarten, eine "Person"-Entität oder -Tabelle in einem Unternehmen zu sehen, abgesehen von der Bequemlichkeit einer Nachschlagetabelle wie im obigen Fall. Personalabteilungen führen eine Liste von Mitarbeitern mit spezifischen Informationen, die für die Gehaltsabrechnung usw. erforderlich sind, aber es gibt nichts Grundlegendes über Personen, das das Unternehmen wissen muss. NB: Suchen Sie den Geschäftsprozess, um eine Entität zu identifizieren - erfinden Sie ihn nicht.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X