6. Best Practices - iwannabebot/SharpFsm GitHub Wiki

Here are some best practices for defining conditions and side effects in SharpFsm:

Keep conditions pure, side effects focused, use the registry for reuse, name things clearly, handle errors, and test your logic. This leads to maintainable, robust, and readable FSMs in SharpFsm.

Keep Logic Focused and Pure

  • Conditions should be pure functions:
  • They should only inspect the context and return a boolean.
  • Avoid side effects (e.g., logging, modifying state, calling external services) in conditions.
  • Side effects should perform actions but not affect the outcome of the transition itself.

Use the TransitionRegistry for Reusability

  • Register commonly used conditions and side effects in the TransitionRegistry.
  • Reference them by name in your FSM builder for clarity and maintainability.
  • This avoids duplication and centralizes logic.
registry.RegisterCondition("IsAdmin", ctx => ctx.IsAdmin);
registry.RegisterSideEffect("Notify", ctx => notificationService.Notify(ctx.UserId));

Keep Context Objects Cohesive

  • Design your context class to include only the data and services needed for evaluating conditions and executing side effects.
  • Avoid making the context too broad or too tightly coupled to infrastructure.

Name Conditions and Side Effects Clearly

  • Use descriptive names when registering conditions and side effects.
  • This improves readability and makes FSM definitions self-documenting.
registry.RegisterCondition("PaymentReceived", ctx => ctx.PaymentReceived);
registry.RegisterSideEffect("LogTransition", ctx => logger.Log("Transition occurred"));

Handle Exceptions Gracefully

  • Side effects may interact with external systems and can throw exceptions.
  • Consider wrapping side effects in try-catch blocks or handling errors at the FSM level to avoid breaking the FSM flow.

Keep Side Effects Idempotent When Possible

  • Design side effects so that running them multiple times does not cause unintended consequences.
  • This is especially important if transitions may be retried.

Test Conditions and Side Effects Independently

  • Write unit tests for your condition and side effect functions to ensure correctness.
  • This is easy since they are just delegates.

Avoid Heavy Logic in FSM Definitions

  • Keep FSM definitions declarative.
  • Place complex logic in the registry or in well-tested helper methods, not inline in the FSM builder.
// Good practice: Register and reference by name
registry.RegisterCondition("IsEligible", ctx => ctx.Age >= 18 && ctx.HasLicense);
registry.RegisterSideEffect("SendWelcomeEmail", ctx => emailService.Send(ctx.Email, "Welcome!"));

builder.AddTransition(State.Pending, State.Active)
    .When("IsEligible")
    .WithSideEffect("SendWelcomeEmail")
    .Done();
⚠️ **GitHub.com Fallback** ⚠️