python-statemachine: Consider returning all values from actions for a triggered transition
Currently only before & on callbacks are used for combining a list of returned values for a transition call. I think it makes more sense to (at least) include the after action as well.
This happened because, at the beginning in the primitive versions of the library, there was only one callback for a transition. The showcase was that you could model a state machine much more likely running transitions acting as standard/normal method calls.
The complexity comes when supporting multiple callbacks for the same event, so my evolutionary approach was: When adding more than one callback option if the user of the library implements more than one, It will start receiving a list instead of the plain return.
This worked well because simple use cases are still able to use a simple API, and was also backward compatible.
I think that many use cases more event-oriented don’t even care about the result, but we need to keep a sane default behavior for those who care.
@fgmacedo How about we keep the result as a list, while each item in it represents a ReturnValue object which attaches the value & name of the action & event data(or something similar). Also we provide a optional flag for this dedicated version of result just like you wrote before.
@fgmacedo Sorry for the delay, I needed to take another look at the code.
Not trying to nitpick here, but return EventData seems confusing, as a user I’d wonder why gives me such an object. Plus it contains a bit too much data.
Maybe adding a flag would make things too complicated? I’m not sure, but I understand it’s about backward compatibility here.
In the nested event scenario, I think my concern still stands, particularly for Non-RTC model. The result would be a nested list with the existing logic, which is very natural and understandable. But to improve it, we need identifiers for at least events & callbacks. For example: [('event1.before_transition', 1), ('event1.on_transition', 2), ('event2.on_transition', 3), ...]. And it gets more complex when it comes to something like t1 = a.to(b, after="t1") | b.to(c)(this is from your test code).
I hope I’m making sense here and we are on the same page before talking about next steps.
Hi @iamgodot , you’re right.
This happened because, at the beginning in the primitive versions of the library, there was only one callback for a transition. The showcase was that you could model a state machine much more likely running transitions acting as standard/normal method calls.
Imagine this:
This is more exotic but also supported:
For both cases, you can just call the
Event
like a method, as you’re using normal Python calls:The complexity comes when supporting multiple callbacks for the same event, so my evolutionary approach was: When adding more than one callback option if the user of the library implements more than one, It will start receiving a list instead of the plain
return
.This worked well because simple use cases are still able to use a simple API, and was also backward compatible.
I think that many use cases more event-oriented don’t even care about the result, but we need to keep a sane default behavior for those who care.
@fgmacedo How about we keep the result as a list, while each item in it represents a
ReturnValue
object which attaches the value & name of the action & event data(or something similar). Also we provide a optional flag for this dedicated version of result just like you wrote before.I’ve actually done this in my fork, but didn’t consider creating a PR yet.
Will do, when I’ve merged the (great!) improvements from
2.0.0
😺@fgmacedo Sorry for the delay, I needed to take another look at the code.
EventData
seems confusing, as a user I’d wonder why gives me such an object. Plus it contains a bit too much data.[('event1.before_transition', 1), ('event1.on_transition', 2), ('event2.on_transition', 3), ...]
. And it gets more complex when it comes to something liket1 = a.to(b, after="t1") | b.to(c)
(this is from your test code).I hope I’m making sense here and we are on the same page before talking about next steps.
@oniboni you can change the test, with this new rational, we’ll need a major version bump IMO.
Thanks for the thorough explanation! @fgmacedo
@fgmacedo I just found that when there’s only one value returned, it will be taken out instead of being a list, which seems a bit strange.