Библиотека государственной машины без гражданства - соответствующий способ структурирования?
Как люди структурируют свой код при использовании библиотеки С# stateless?
https://github.com/nblumhardt/stateless
Я особенно заинтересован в том, как это связано с инъецированными зависимостями, а правильный подход к ответственности и правильному расслоению.
Моя текущая структура включает в себя следующее:
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);
}
}
Должны ли мы реализовывать все процессы (вызов служб) внутри крюка OnEntry или реализовывать процессы снаружи после проверки состояния, что это разрешено? Мне интересно, как это сделать при управлении транзакциями.
Я предполагаю, что то, что мне нужно, - это лучшее руководство от тех, кто уже реализовал что-то, используя апатрид и как подойти к структуре кода.
Ответы
Ответ 1
Перед рассмотрением самой структуры пара замечает:
-
OnEntry
действия выполняются только , если триггер успешно запущен.
-
Триггеры, которые не разрешены в текущем состоянии, будут бросать InvalidOperationException
. Рассмотрите переопределение OnUnhandledTrigger
, если вы не ожидаете исключения (я обнаружил, что ведение журнала необработанных триггеров - хороший подход к поиску недостатков в логике).
Мое правило для структурирования OnEntry
/OnExit
заключается в том, что любое создание и логика будут размещены OnEntry
, и всякая необходимая очистка выполняется OnExit
.
Итак, в вашем случае, учитывая, что вы используете вложенные зависимости (и предполагая, что вы не властвуете на них, то есть кто-то другой будет управлять своим жизненным циклом), вы можете разместить всю свою логику OnEntry
.
Учитывая это, способ, которым ваш государственный аппарат в настоящее время структурирован, отлично.
В последней заметке помните, что триггеры запуска из одного и того же потока, которые продвигают машину состояний и выполняют логику конечного автомата, могут и будут приводить к исключениям stackoverflow (см. здесь о том, как решить проблему автоматического продвижения).