2014-11-21 13 views
7

Hier eine kurze Erklärung meiner Domain:Wie würde ein Voting/Like-System in einem DDD/CQRS/EventSourced-Projekt modelliert?

Ich habe Artikel, die im Grunde wie jeder Artikel (Titel, Zusammenfassung und ein Körper) sind.

Ich muss Stimmen zu meinen Artikeln erlauben, Stimmen werden von anonymen Benutzern abgegeben (keine Registrierung erforderlich, aber eine Sitzung wird Stimmen speichern, bitte nicht darauf konzentrieren).

In dieser Domäne ist Artikel meine Gesamtwurzel.

ich nicht einen Weg finden kann meine Stimmen mit folgenden Anforderungen zu modellieren:

kann

eine Abstimmung entweder Ich mag oder Ich mag es nicht sein, sollte es wandelbar sein (es im Laufe der Zeit geändert werden kann, oder sogar storniert)

Ein Gastbenutzer mit zugehöriger Sitzung kann nur eine Stimme pro Artikel abgeben.

Soll also Vote alleine aggregiert sein?

so etwas wie

Class Vote { public function cast(ArticleId id, GuestSessionToken token, VoteValue value); }

Aber in diesem Fall, wie soll ich für unicity überprüfen? Eventuelle Konsistenz verwenden (es scheint in Ordnung zu sein, da ich einige Duplikate nicht habe, soweit sie selten sind).

Denn wenn ich meinem Artikel-Aggregat die Vote-Methode hinzufüge, muss ich den Verlauf für jede abgegebene Stimme wiederholen, was ziemlich langsam klingt (angesichts der Tatsache, dass ich 100.000 Stimmen pro Artikel haben kann).

Ich weiß, dass Leistung und Optimierung beim Entwurf der DDD-Methode nicht berücksichtigt werden sollten, aber hier ist es ein spezifisches Problem, das ich vorher lösen muss, um irgendetwas zu implementieren.

Jeder von euch hat schon einmal etwas Ähnliches gemacht?

+0

Ich beantwortete eine ähnliche Frage hier: http://stackoverflow.com/a/38259448/225022 – Bishoy

Antwort

-1

Ich würde das Vote-Objekt von einem VoteCast-Objekt trennen.

VoteCast ist das Ereignis, es könnte einen Wert von Oben, Unten oder Abbrechen haben. Es gibt auch ein Abstimmungsobjekt, das von VoteCasts aktualisiert wird.

Bei der Berechnung von Stimmen müssen Sie die Abgüsse nicht wiedergeben, sondern nur die Stimmen zählen. Sie können die Abstimmungen in Sammlungen auf dem Artikel (Up, Down) setzen und einfach die Anzahl der Sammlungen zurückgeben. Ein VoteCast würde ändern, zu welcher Sammlung die Stimmen gehören.

+0

Sie könnten sogar eine "Nachzählung" haben, um die VoteCasts erneut auf die Stimmen anzuwenden :-) –

7

Vote ist eine aggregierte Wurzel für sich. Wenn wir über Assoziationen nachdenken, "ein Artikel hat viele Stimmen", dann wenden wir einen relationalen Ansatz an, was uns zu dem so kritisierten Big Aggregate-Ansatz neigt, der von der DDD-Gemeinschaft konsensfähig ist. Stattdessen wollen wir uns auf das Verhalten konzentrieren. Wir wissen bereits, dass ein Artikel keine Sammlung von Stimmen enthalten wird. Da eine Abstimmung ihren eigenen Lebenszyklus benötigt, wird sie ihre eigene globale Identität und somit ihr eigenes Repository haben. Ein Gegenstand wird von den Nutzern gewählt, ist es ein schöner Ansatz Semantik zu unserem Domain-Modell mit Domänenexperten Semantik so spielen zu geben, könnten wir sagen

„ein Artikel von dem Benutzer gewählt wird“
anArticle.votedBy(aReader); 

Denken Sie daran, dass der Benutzer spielt die Rolle eines Lesers in diesem begrenzten Kontext. Die victedBy-Methode ist eine Factory-Methode, die in der Lage ist, eine Abstimmung zu erstellen.Seine Umsetzung wäre:

Article.votedBy(aReader) { 
    return new Vote(this, aReader); 
} 

stets, dass die Erinnerung am Ende eine Abstimmung die konzeptionellen Kennungen eines Artikels und einem Lesegerät haben, das getrennte Modell Förderung anstelle der tatsächlichen Bezüge zu anderen Aggregat Wurzeln halten. Der Domain-Service wäre also der Leser selbst. Nehmen wir an, dass Sie eine Rest-Schnittstelle

RestInterface.voteArticle(articleId) { 
    reader = new Reader(articleRepository); 
    reader.vote(articleId); 
} 

Reader.vote(anArticleId) { 
    article = articleRepository.get(anArticleId); 
    vote = article.votedBy(this); 
    voteRepository.add(vote); 
} 

modellieren sollten Sie eine bestimmte überprüfen (sicherstellen, dass ein Benutzer einen Artikel stimmt nur einmal) durch eine erstellte eindeutige Einschränkung auf Datenbankebene platzieren. Dies ist die am wenigsten aufdringliche Methode, dies zu überprüfen. Andernfalls sollten Sie ein weiteres Domänenmodell hinzufügen, das die Voten moderiert. Vielleicht macht dieses neue Objekt mehr Sinn, wenn verschiedene Voting-Geschäftsregeln erstellt werden, aber um sicherzustellen, dass ein Leser nur einmal abstimmt, wenn ein Artikel ausreicht, und ich denke, die einfachste Lösung (das ist die DB-Einschränkung). DDD ist ein Lernprozess und wie wir neue Dinge über die Domain lernen wir erkennen die Nutzer Wie treffen kann oder auf einen Artikel Dislike Button so denken wir über Re-Factoring, was wir bisher ein wenig tat

Article.likedBy(aReader) { 
    return Vote.positiveByOn(aReader, this); 
} 

Article.dislikedBy(aReader) { 
    return Vote.negativeByOn(aReader, this); 
} 

wo beide Implementierungen sind:

class Vote { 

    readerId 
    articleId 
    typeId 

    Vote(aReaderId, anArticleId, aType) { 
    readerId = aReaderId 
    articleId = anArticleId 
    type = aType 
    } 

    public Enum VoteType { POSITIVE, NEGATIVE } 

    Vote static positiveByOn(aReader, anArticle) { 
    return new Vote(aReader.id, anArticle.id, POSITIVE); 
    } 

    Vote static negativeByOn(aReader, anArticle) { 
    return new Vote(aReader.id, anArticle.id, NEGATIVE); 
    } 
} 

da auch die likedBy/dislikedBy Factory-Methode auf dem Artikel AR Stimmen Erstellen Sie eine Einschränkung einen Artikel platzieren konnte nicht sagen, stimmten mehr als N Mal werden kann oder andere Geschäftsszenario.

Hoffe es hilft,

Sebastian.

+0

Mit DB Einschränkung meinen Sie während der Repository-Speicheroperation? Und wenn wir keine Datenbank verwenden? –