Frage

Ich suche nach Empfehlungen, wie das folgende Design-Problem zu nähern (ein fiktives Beispiel basierend auf Stackoverflow verwendet wird). Ich habe versucht, ein anämisches Domänenmodell zu vermeiden und allgemein „best-practice“ Beratung für diese Art von Fall zu suchen.

Szenario:

Angenommen, ein neues Feature für Stackoverflow entwickelt wird, die eine E-Mail-Benachrichtigung auf die Frage des Eigentümers sendet, wenn seine / ihre Frage 10 upvotes erhält.

Die Domain-Objektmodell ist so etwas wie folgt aus:

public class Question
{
    string Question { get; set; }
    IList<Votes> Upvotes { get; set; }
    User Owner { get; set; }

    public void AddUpvote(Vote upvote)
    {
        Upvotes.Add(upvote);
    }
}

Mögliche Implementationen:

  1. Ändern AddUpvote() einen IEmailerService Parameter zu nehmen und die Logik innerhalb des AddUpvote() Verfahren durchzuführen.

    public void AddUpvote(Vote upvote, IEmailerService emailer)
    {
        Upvotes.Add(upvote);
        if ( Upvotes.Count == 10 )
        {
            emailer.Send(Owner.EmailAddr);
        }
    }
    
  2. erkennen diesen Zustand innerhalb AddUpvote() und haben AddUpvote() eine IEmailService von einem IoC-Container zu lösen (anstelle der IEmailerService als Parameter vorbei).

  3. Detect diesen Zustand im externen Service-Objekt, das question.AddUpvote() aufruft.

    public void UpvoteClickHandler(Question question)
    {
        question.AddUpvote(new Upvote());
        if ( question.Upvotes.Count == 10 )
        {
            _emailer.Send(question.Owner.EmailAddr);
        }
    }
    
  4. Ihre bessere Lösung hier!

War es hilfreich?

Lösung

Sie wirklich nicht wollen, diese beiden zusammen zu mischen, da sie getrennte Bedenken haben. Lassen Sie die Frage Klasse kümmern sich um Fragen und die Nachrichtendienst-Betreuung über das, was zu tun ist, wenn die Abstimmung 10 trifft, oder 20 oder 100 oder ...

Das folgende Beispiel ist nur zu Demonstrationszwecken gedacht, aber Sie werden den Punkt. Es gibt eine klare Trennung von Bedenken, so dass die Frage Klasse muss nicht für das Senden von Nachrichten ändert sich, wenn sich die Anforderungen ändern. Denken Sie daran, nach den SOLID Grundsätze sollte eine Klasse nur einen Grund haben zu ändern.

public class Question
{
    public string Description { get; set; }
    public Int32 Votes { get; set; }
    public User Owner { get; set; }

    public event EventHandler<QuestionEventArgs> OnUpvote;

    private void RaiseUpvoteEvent(QuestionEventArgs e)
    {
        var handler = OnUpvote;
        if (handler != null) handler(this, e);
    }

    public void Upvote()
    {
        Votes += 1;

        RaiseUpvoteEvent(new QuestionEventArgs(this));
    }
}

public class MessageService
{
    private Question _question;

    public MessageService(Question q)
    {
        _question = q;

        q.OnUpvote += (OnUpvote);
    }

    private void OnUpvote(object sender, QuestionEventArgs e)
    {
        if(e.Question.Votes > 10)
            SendMessage(e.Question.Owner);
    }
}

public class QuestionEventArgs: EventArgs
{
    public Question Question { get; set; }

    public QuestionEventArgs(Question q)
    {
        Question = q;
    }
}

So haben Sie es. Es gibt viele andere Möglichkeiten, um dies zu erreichen, aber das Ereignismodell ist ein guter Weg zu gehen, und es führt die Trennung von Bedenken Sie, um in Ihrer Implementierung mögen Wartung machen früher.

Andere Tipps

Beide Optionen 1) und 2) herausspringen als der falsche Ort ist, um eine E-Mail zu versenden. Eine Frage Instanz sollte nicht wissen, diese beiden Dinge:

  1. Es soll nicht über die Politik wissen, das heißt, wenn eine E-Mail senden.
  2. Es sollte nicht über die Mechanik der Benachrichtigung für eine Politik, dh die E-Mail-Dienst kennen.

Ich weiß, dass dies eine Frage des Geschmacks ist, aber Sie sind in der Frage zu binden eng mit einer Politik als auch den Mechanismus eine E-Mail zu versenden. Es wäre wirklich schwer, diese Frage Klasse in ein anderes Projekt zu bewegen (wie ServerFault, die Stackoverflow Schwesterstandort zum Beispiel ist)

Ich interessiere mich für diese Frage, weil ich ein Benachrichtigungssystem für einen Help Desk bin zu schaffen, die ich baue. Dies ist, was ich in meinem System habe:

Erstellen Sie eine NotificationManager (Im Grunde genommen völlig die Sorge der Benachrichtigungen an eine separate Klasse bewegen).

public Class NotificationManager
{
    public void NotificationManager(NotificationPolicy policy, IEmailService emailer)
    {
    }
}

Ich habe etwas entlang der Linien von diesen dann (Die UpvoteClickHandler hat eine Abhängigkeit zu einer NotificationManager Instanz):

public void UpvoteClickHandler(Question question)
{
    question.AddUpvote(new Upvote());
    _notificationManager.Notify(Trigger.UpvoteAdded, question);
}

Die ganze UpvoteClickHandler tut, ist NotificationManager sagen, dass ein upvote in Frage wurde hinzugefügt und lassen NotificationManager bestimmen, ob und wie sie eine E-Mail senden soll.

Die Antwort hängt von Ihrem grundlegenden Ansatz zur Anwendung und Objektdesign. Und (Hier ändern), was Sie als Ihre wichtigste Eigenschaft des Systems anzuzeigen. Sieht aus wie Sie Daten, Fragen haben, und Geschäftsregeln, bis Stimmen. Nicht Objekte Frage überhaupt. So sollten Sie Ihre Daten als Daten behandeln und erlauben Datentools an ihnen zu arbeiten, indem sie nicht das Verhalten in ihnen vermischen. Traditionelles Objektdesign würde alle Verhaltensweisen und Daten im Objekt, so eMail zu senden würde in dem Objekt gehört. (Option 1 und 2) Ich denke, dies ist die Black Box ist, oder in sich geschlossene Objekt Ansatz. Moderne Verfahren, wie ich zu erfahren habe kommen, hat Objekte als einfacher Dateninhaber. Welche sollen bewegt werden um, beharrte, transformiert und Sachen mit ihnen gemacht haben. Vielleicht als wenig mehr als structs in C. lebt Das Verhalten von den Leistungen und Transformationen kommt, die auf die einfachen Objekte angewandt werden.

HALLO alle,

Meiner Meinung nach „sendet eine E-Mail-Benachrichtigung an einen Eigentümer Frage, wenn seine / ihre Frage 10 upvotes empfängt“ ist Domänenlogik und therfore sollte es in Domain-Objekt sein, um eine anämische Domäne zu vermeiden.

Es ist die Handlung des Sendens der E-Mail (das heißt Kommunikation mit SMTP-Server), die in die Infrastrukturschicht gehen.

So denke ich, dass die Option 1 nicht völlig falsch ist. Beachten Sie, dass Sie immer Ihr Objekt testen, indem Sie eine Mock Umsetzung des IEmailerService vorbei.

Mit freundlichen Grüßen

Stefano

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