C
Chuck Remes
I'm working on a somewhat complex project that really begs for a state machine to keep the logic all straight. I've been playing with the state_machine [1] gem the last several days to see if it's suitable. I like the syntax and feature set, but I'm having difficulty mapping its capabilities into code.
The main problem has to do with the relationship between state machines and classes. While a class can have 1 (or more) state machines declared inside of it, a state machine cannot be used across 1 (or more) *classes.*
If I am correct about that limitation, I am wondering how to structure a large and complex state machine. I like to keep my classes small and simple so that they are easy to understand and debug. In the case where a class has many states and events, the business logic attached to the transitions (in my case) are rather complex. The size of the code in the class very quickly balloons (a few hundred lines).
Here's an example.
Assume I am building an application that connects to a web service. The web service is a gateway to other services behind it, but it acts as a broker for all requests. Upon connection to the web service gateway, the gateway can indicate if it is available to forward requests, delayed/behind in forwarding requests, or if the back-end services are offline.
So, I build a machine that has several states along with unique behavior for each one.
State - Starting
Initialize all libraries for connecting to the web service. Upon completion, transition to the Connecting state.
State - Connecting
Open a network connection to the web service. Upon timeout, transition to ConnectionError state. Upon successful connection, transition to the Connected state.
State - Connected
Ask the web service for its current status. The web service can indicate it is in 1 of 3 states itself. Okay, Delayed, or Offline. Depending upon the response, transition to the appropriate state. In the meantime, each of the Okay/Delayed/Offline states can get events indicating the web service's current status. It seems to me like this is appropriately handled by the "Super state" Connected rather than duplicating this functionality across multiple sub states.
As you can imagine from the example given above, jamming all of this functionality into a single class would result in a pretty huge class (hundreds or even thousands of lines).
I would like to offload some of that logic to other classes and have a state transition "hand off" to another class while everything is still controlled by the same overall machine. So, I guess what I want is a machine to be able to encompass multiple classes.
Does anyone else have any experience with this gem and building machines with more complex use-cases than the examples? Am I trying to shoe-horn this gem into a use-case that it isn't suited to solving? Should I consider using a different statemachine gem? Suggestions?
cr
[1] https://github.com/pluginaweek/state_machine
The main problem has to do with the relationship between state machines and classes. While a class can have 1 (or more) state machines declared inside of it, a state machine cannot be used across 1 (or more) *classes.*
If I am correct about that limitation, I am wondering how to structure a large and complex state machine. I like to keep my classes small and simple so that they are easy to understand and debug. In the case where a class has many states and events, the business logic attached to the transitions (in my case) are rather complex. The size of the code in the class very quickly balloons (a few hundred lines).
Here's an example.
Assume I am building an application that connects to a web service. The web service is a gateway to other services behind it, but it acts as a broker for all requests. Upon connection to the web service gateway, the gateway can indicate if it is available to forward requests, delayed/behind in forwarding requests, or if the back-end services are offline.
So, I build a machine that has several states along with unique behavior for each one.
State - Starting
Initialize all libraries for connecting to the web service. Upon completion, transition to the Connecting state.
State - Connecting
Open a network connection to the web service. Upon timeout, transition to ConnectionError state. Upon successful connection, transition to the Connected state.
State - Connected
Ask the web service for its current status. The web service can indicate it is in 1 of 3 states itself. Okay, Delayed, or Offline. Depending upon the response, transition to the appropriate state. In the meantime, each of the Okay/Delayed/Offline states can get events indicating the web service's current status. It seems to me like this is appropriately handled by the "Super state" Connected rather than duplicating this functionality across multiple sub states.
As you can imagine from the example given above, jamming all of this functionality into a single class would result in a pretty huge class (hundreds or even thousands of lines).
I would like to offload some of that logic to other classes and have a state transition "hand off" to another class while everything is still controlled by the same overall machine. So, I guess what I want is a machine to be able to encompass multiple classes.
Does anyone else have any experience with this gem and building machines with more complex use-cases than the examples? Am I trying to shoe-horn this gem into a use-case that it isn't suited to solving? Should I consider using a different statemachine gem? Suggestions?
cr
[1] https://github.com/pluginaweek/state_machine