dotnet-state-machine / stateless

A simple library for creating state machines in C# code
Other
5.54k stars 766 forks source link

Dependency Injection Recommendation #312

Open MattHartz opened 5 years ago

MattHartz commented 5 years ago

Hi all,

Thanks for the cool SDK! Is there any recommendation on DI best practices?

My goal would be to keep the dependencies on the statemachine kept to a minimum, while giving max flexibility to each trigger to engage in all its needed dependencies.

One idea i have is have 1 dependency that handles all trigger events, and that trigger then has a list of all trigger "handlers" for each state that have their own dependencies.

Would that work? Is there any other ideas?

Thanks!

HenningNT commented 5 years ago

I might be misunderstanding what you are trying to do, but it seems to me that you are trying to do the work of the state machine library.

Are you planning on representing the states as classes?

MattHartz commented 5 years ago

Hi @HenningNT , thanks for the response. Let's say that in State1, we send an email, which means we need an emailsender dependency. Then in State2, we need to write to the database, so we need an ORM dependency. Then in State3, we need to send a text to all recipients, so we need an SMS dependency.

I rather not inject all these dependencies at the creation of the state machine, and would instead like them injected at the state instead.

I haven't played with the code in a few days, but thinking about it, making each state take a function would probably be the least coupled way to do it.

HenningNT commented 5 years ago

This sort of reminds me of the Service Locator pattern, and some would say it's an anti-pattern. I suggest you create a single class that has a state machine, and hide the internals from the caller. Provide all the dependencies at instantiation, and if you find that it require too many dependencies you should think about splitting up the responsibilities of the class into several smaller ones. I think I'd use an event bus to decouple the classes.

dazinator commented 5 years ago

@HenningNT can I just check my understanding. So lets say you have 50 states and a wide variety of actions that require various dependencies.. Rather than inject all dependencies into the service that wraps the state machine and have all action logic directly in that one class, you'd instead just inject an IEventPublisher or something. Then you'd have all the services that need to action things, "Listen" for those published events. I'm assuming synchronously too, as if processing fails you may want to prevent the state transitioning onwards. Finally you'd need some bootstrap code to ensure all services that handle events are created and subscribed before the state machine service starts publishing messages..

If this is the kind of pattern you foresee, are you able to share any recommended in proc event pub / sub libraries for .netstandard that allow synchronous handling of messages that one could leverage? I could see a basic example being very useful.

veraciousnottaken commented 5 years ago

I'm using something similar as @dazinator proposed. In my Machine.Configure().OnEntryAsync() I'm invoking Callback that is processed outside my Machine class. In this way in my Machine class I have only ILog dependency injected.