10

W jaki sposób ludzie budują swój kod podczas korzystania z biblioteki bezpaństwowej C#?Biblioteka maszyn stanu bezstanowego - właściwy sposób na strukturę?

https://github.com/nblumhardt/stateless

Jestem szczególnie zainteresowany w jaki sposób ten wiąże się z wstrzyknięto zależności i prawidłowe podejście do obowiązków i warstw poprawnie.

Moja obecna struktura obejmuje następujące elementy:

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); 
    } 

} 

powinniśmy realizować wszystkie procesy (wezwanie do usług) w haku OnEntry lub wdrożyć procesy na zewnątrz po przejściu stan został zweryfikowany, że jest może się odbyć? Zastanawiam się, jak zrobić zarządzanie transakcjami, jeśli tak.

Podejrzewam, że to, czego szukam, to najlepsze wskazówki od tych, którzy już wdrożyli coś za pomocą bezpaństwowców i jak podejść do struktury kodu.

+0

Patrząc na to nieco, pochylam się nad wykorzystaniem fabryki wstrzykniętej do usług domenowych do skonstruowania obiektu przepływu pracy, który może przekazywać usługi wymagane przez obiekt przepływu pracy. – dandcg

+0

Nadal poszukuje wskazówek na temat najlepszego podejścia do korzystania z automatu stanów. Załóżmy, że muszę wywołać metodę w usłudze wysyłania wiadomości e-mail, która istnieje przez cały czas trwania żądania internetowego. Powinno to być połączenie w ramach OnEntry lub w metodzie publicznej. Jeśli jest w OnEntry, co się stanie, jeśli wystąpi problem podczas przejścia? Niektóre wskazówki od ludzi, którzy mają zaimplementowanie kodu za pomocą bezpaństwowców i gdzie umieścili kod rzeczywistego działania, byłyby bardzo mile widziane. – dandcg

Odpowiedz

11

Przed omówieniem struktury samą parę Uwagi:

  • OnEntry czynności wykonywane są tylko jeśli spust został z powodzeniem spalać.

  • Uruchomione wyzwalacze, które nie są dozwolone w bieżącym stanie, wyrzucą InvalidOperationException. Rozważ zastąpienie OnUnhandledTrigger, jeśli nie spodziewasz się wyjątku (odkryłem, że logowanie nieobsługiwanych wyzwalaczy jest dobrym sposobem na znalezienie błędów w logice).

Moja zasada dla OnEntry/OnExit strukturyzacji jest, że wszelkie stworzenie i logika zostaną umieszczone OnEntry oraz wszelkie wymagane oczyszczania odbywa OnExit.

W twoim przypadku, biorąc pod uwagę, że używasz wstrzykniętych zależności (i zakładając, że nie przejmujesz ich własności, tj. Ktoś inny będzie zarządzał ich cyklem życia), możesz umieścić całą swoją logikę OnEntry.

Mając to na uwadze, sposób, w jaki twoja maszyna stanowa jest obecnie zorganizowana, jest doskonale w porządku.

Jeszcze jedna uwaga, należy pamiętać, że wyzwalanie wyzwalania z tego samego wątku, który przesuwa automat stanowy i wykonuje logikę automatu stanów, może i będzie prowadzić do wyjątków przepływu stackoverflow (patrz here, jak rozwiązać problem z automatycznym wyprzedzeniem).

+0

Cześć Omni, dziękuję za to. co by się wtedy stało, gdyby wystąpił błąd podczas wdrażania OnEntry - czy stan nadal się zmienia? A także czy zazwyczaj używasz fabryki do utworzenia instancji przepływu pracy?Miałoby to dotyczyć dodawania instancji wf ze stanem początkowym i przekazywaniem zależności wymaganych przez implementację? – dandcg

+0

Witam @dandcg. Przejście stanu następuje przed przetworzeniem 'OnEntry', więc do czasu wyrzucenia wyjątku stan jest już zmieniony. Następnie musisz zdecydować, gdzie zająć się wyjątkiem. Albo wewnątrz 'OnEntry', albo w' machine.Fire (...) ', który przeszedł w stan, który rzucił wyjątek. Nie ma zbyt wiele w używaniu fabryki do stworzenia 'AccountWf', które powiedziałbym. Przydałaby się fabryka, gdyby w zależności od parametrów dysponować różnymi typami maszyn/konfiguracji. – Omni

+0

Powodem, dla którego fabryka jest taka, że ​​nie chcę wstrzykiwać samej instancji przepływu pracy? Ale przypuszczam, że to jest w porządku. Jak grałeś? – dandcg

Powiązane problemy