10

Wie strukturieren Benutzer ihren Code bei der Verwendung der statusfreien C# -Bibliothek?Zustandslose Maschinenbibliothek - geeignete Struktur?

https://github.com/nblumhardt/stateless

Ich bin besonders daran interessiert, wie diese Beziehungen mit injizierten Abhängigkeiten und ein richtiger Ansatz von Verantwortlichkeiten und richtig Schichtung.

Meine aktuelle Struktur beinhaltet die folgenden:

public class AccountWf 
{ 
    private readonly AspNetUser aspNetUser; 

    private enum State { Unverified, VerificationRequestSent, Verfied, Registered } 
    private enum Trigger { VerificationRequest, VerificationComplete, RegistrationComplete } 

    private readonly StateMachine<State, Trigger> machine; 

    public AccountWf(AspNetUser aspNetUser, AccountWfService userAccountWfService) 
    { 
     this.aspNetUser = aspNetUser; 

     if (aspNetUser.WorkflowState == null) 
     { 
      aspNetUser.WorkflowState = State.Unverified.ToString(); 
     } 

     machine = new StateMachine<State, Trigger>(
     () => (State)Enum.Parse(typeof(State), aspNetUser.WorkflowState), 
     s => aspNetUser.WorkflowState = s.ToString() 
     ); 

     machine.Configure(State.Unverified) 
     .Permit(Trigger.VerificationRequest, State.VerificationRequestSent); 

     machine.Configure(State.VerificationRequestSent) 
     .OnEntry(() => userAccountWfService.SendVerificationRequest(aspNetUser)) 
     .PermitReentry(Trigger.VerificationRequest) 
     .Permit(Trigger.VerificationComplete, State.Verfied); 

     machine.Configure(State.Verfied) 
     .Permit(Trigger.RegistrationComplete, State.Registered); 

    } 

    public void VerificationRequest() 
    { 
     machine.Fire(Trigger.VerificationRequest); 
    } 

    public void VerificationComplete() 
    { 
     machine.Fire(Trigger.VerificationComplete); 
    } 

    public void RegistrationComplete() 
    { 
     machine.Fire(Trigger.RegistrationComplete); 
    } 

} 

Sollten wir alle Prozesse implementieren (auf Dienste nennen) innerhalb des OnEntry Haken oder die Prozesse auf der Außenseite implementieren, nachdem der Zustandsübergang überprüft wurde, dass es darf stattfinden? Ich frage mich, wie man das Transaktionsmanagement tut, wenn es so ist.

Ich denke, was ich suche, ist die beste Anleitung von denen, die bereits etwas mit Stateless implementiert haben und wie man sich der Code-Struktur nähert.

+0

Mit Blick auf diese mehr Ich bin in Richtung auf die Verwendung einer Fabrik in die Domain-Services injiziert, um das Workflow-Objekt zu konstruieren und dies kann die Dienste von den Workflow-Objekt übergeben. – dandcg

+0

Immer noch einige Hinweise auf den besten Ansatz der Verwendung der Zustandsmaschine. Angenommen, ich muss eine Methode für einen Sende-E-Mail-Dienst aufrufen, der für die Lebensdauer der Webanforderung existiert. Sollte dieser Aufruf innerhalb des OnEntry oder innerhalb der public Methode erfolgen? Wenn es im OnEntry ist, was passiert, wenn während des Übergangs ein Problem auftritt? Einige Hinweise von Menschen, die Code mit Stateless implementiert haben und wo sie den eigentlichen Code platziert haben, würden sehr geschätzt werden. – dandcg

Antwort

11

Bevor die Struktur Adressierung selbst ein paar Bemerkungen:

  • OnEntry Aktionen nur ausgeführt werden, wenn der Auslöser erfolgreich abgefeuert wurde.

  • Ausgelöste Trigger, die im aktuellen Status nicht erlaubt sind, werfen eine InvalidOperationException. Erwägen Sie das Überschreiben von OnUnhandledTrigger, wenn Sie keine Ausnahme erwarten (ich habe festgestellt, dass die Protokollierung nicht behandelter Trigger ein guter Ansatz ist, um die Fehler in der Logik zu finden).

Meine Faustregel für die OnEntry/OnExit Strukturierung ist, dass jede Schöpfung und Logik OnEntry und alle erforderlichen Aufräumarbeiten erledigt sind OnExit platziert werden.

Also in Ihrem Fall, da Sie die injizierten Abhängigkeiten verwenden (und vorausgesetzt, Sie übernehmen nicht die Verantwortung für diese, d. H. Jemand anderes wird ihren Lebenszyklus verwalten) können Sie alle Ihre Logik OnEntry.

In diesem Sinne ist die Art, wie Ihre Zustandsmaschine derzeit strukturiert ist, völlig in Ordnung.

Eine letzte Anmerkung, bedenken Sie, dass das Auslösen von Triggern innerhalb des gleichen Threads, der die Zustandsmaschine voranbringt und die Logik der Zustandsmaschine auslöst, zu stackoverflow-Ausnahmen führt (siehe here zur Lösung des Problems der automatischen Vorverlegung).

+0

Hallo Omni, danke dafür. Was würde dann passieren, wenn bei der OnEntry-Implementierung ein Fehler auftrat - würde sich der Zustand noch ändern? Würden Sie in der Regel auch eine Factory zum Erstellen der Workflow-Instanz verwenden?Dies würde bedeuten, die wf-Instanz mit dem Startzustand neu zu erstellen und die von der Implementierung benötigten Abhängigkeiten zu übergeben? – dandcg

+0

Hallo @dandcg. Der Statusübergang findet statt, bevor der OnEntry-Prozess verarbeitet wird. Wenn die Ausnahme ausgelöst wird, ist der Status bereits geändert. Sie müssen dann entscheiden, wo die Ausnahme behandelt werden soll. Entweder im 'OnEntry' oder in' machine.Fire (...) ', die in den Zustand übergegangen sind, der die Ausnahme ausgelöst hat. Es gibt nicht viel in der Verwendung einer Fabrik, um das 'AccountWf' zu erstellen, würde ich sagen. Eine Fabrik wäre nützlich, wenn Sie abhängig von den Parametern verschiedene Arten von Maschinen/Konfigurationen hätten. – Omni

+0

Der Grund für die Fabrik ist, dass ich die Workflow-Instanz nicht selbst injizieren möchte? Aber ich denke, das ist in Ordnung. Wie hast du es gespielt? – dandcg