Frage

Ich habe versucht, ein klares und einfaches Beispiel dafür zu finden, was eine anämische Domäne wirklich bedeutet.Es gibt viel Theorie und auch viele gut beantwortete Fragen.Dennoch konnte ich mir kein klares Bild davon machen, inwieweit die Bedeutung „anämischer Bereich“ wirklich reicht.Daher glaube ich, dass es einfacher wäre, sich ein praktisches Dummy-Beispiel für ein anämisches Domänendesign anzusehen und Sie zu fragen, wie dieses zu einem domänengesteuerten Design weiterentwickelt werden könnte ...

Nehmen wir also an, wir haben eine Datenentität vom Typ TaskData:

public class TaskData
{
    public Guid InternalId { get; set; }

    public string Title { get; set; }

    public string Details { get; set; }

    public TaskState ExplicitState { get; set; }

    public IEnumerable<TaskData> InnerTasks { get; set; }

}

Und es besteht Bedarf an einer zusätzlichen Eigenschaft namens „Tatsächlicher Zustand", was ein berechneter Zustand ist:Wenn die Aufgabe innere Unteraufgaben hat, hängt der Wert streng von den untergeordneten Aufgaben ab, andernfalls ist die „Tatsächlicher Zustand" ist gleich "ExplicitState"

Wenn ich diese Logik separat schreibe Service Klasse (ich nenne sie „Motoren") wir haben:

internal class TaskStateCalculator
{
    public TaskState GetState(TaskData taskData)
    {
        if (taskData.InnerTasks.Any())
        {
            if (taskData.InnerTasks.All(x => this.GetState(x) == TaskState.Done))
            {
                return TaskState.Done;
            }
            if (taskData.InnerTasks.Any(x => this.GetState(x) == TaskState.InProgress))
            {
                return TaskState.InProgress;
            }

            return TaskState.Default;
        }

        return taskData.ExplicitState;
    }       
}

Der erste Frage Ist:

Spiegelt der obige Code ein anämisches Domänendesign wider, auch wenn das TaskStateCalculator Service/Engine ist Teil meiner Domain-Schicht?Wenn ja, müssen wir die Logik in das Innere verschieben, um dies zu vermeiden TaskData Klasse (und umbenennen). TaskData Zu Aufgabe).Habe ich recht?

Der zweite Frage ist (eigentlich eine Kette davon):

Was ist, wenn wir eine schwierigere Situation haben?Nehmen wir an, es besteht Bedarf an einer Immobilie namens ComputeSomething innen Aufgabe Entität, und die Logik dieser Eigenschaft muss auf die gesamten Aufgaben zugreifen Repository.In diesem Fall ist die Aufgabe Klasse hätte eine Abhängigkeit von TaskRepository.Wäre das in Ordnung?Wie würde EF eine Instanz einer solchen Klasse erstellen?Was ist die Alternative?

War es hilfreich?

Lösung

Ich habe versucht, ein klares und einfaches Beispiel dafür zu finden, was eine anämische Domäne wirklich bedeutet

Tatsächlich ist es wirklich einfach, von einem kraftlosen Domänenmodell zu einem reichhaltigen zu wechseln.

  1. Setzen Sie alle Eigenschaftssetzer auf private und fügen Sie dann Methoden hinzu, wenn Sie den Status eines Modells ändern möchten.
  2. Bewerten Sie alle Gesetz von Demeter Verstöße erkennen und ggf. Methoden hinzufügen.

Irgendwann haben Sie ein richtiges Modell.

In Ihrem Fall würde ich diese Logik darin verkapseln TaskData da Ihr TaskStateCalculator gegen das Gesetz von Demeter verstößt

public class TaskData
{
    public Guid InternalId { get; private set; }

    public string Title { get; private set; }

    public string Details { get; private set; }

    public TaskState ExplicitState { get; private set; }

    public IEnumerable<TaskData> InnerTasks { get; private set; }

    public TaskState GetState()
    {
        if (!InnerTasks.Any())
            return ExplicitState;

        if (InnerTasks.All(x => this.GetState(x) == TaskState.Done))
        {
            return TaskState.Done;
        }

        if (InnerTasks.Any(x => this.GetState(x) == TaskState.InProgress))
        {
            return TaskState.InProgress;
        }

        return TaskState.Default;
    }       
}

Eine andere Sache ist, dass ich die InnerTasks-Sammlung wahrscheinlich überhaupt nicht der Außenwelt zugänglich machen würde (sie einfach als Mitgliedsfeld verwenden würde).Aber das ist schwer zu sagen, da ich nicht weiß, wie die Klasse in anderen Szenarien verwendet wird.

Warum private Setter

Jedes Mal, wenn Sie mehr als eine Eigenschaft ändern müssen, ist es oft besser, das Verhalten mit einer Methode zu beschreiben, da Sie dann nicht vergessen können, alle erforderlichen Eigenschaften zu ändern.Eine Methode beschreibt auch besser, was Sie tun möchten, als eine Reihe von Eigenschaften zu ändern.

Selbst wenn Sie nur eine einzelne Eigenschaft ändern, kann diese Eigenschaft die Klasse in einen ungültigen Zustand versetzen, da die Änderung möglicherweise nicht mit den übrigen Informationen in der Klasse kompatibel ist.Vergessen Sie nicht, dass die Kapselung eines der Grundprinzipien von OOP ist

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top