dwhall / farc

Framework for state machines with run-to-completion concurrency using asyncio. Python 3.4 or later
MIT License
28 stars 6 forks source link

Create a means for an Ahsm to postFIFO() to an Ahsm in another module #3

Closed dwhall closed 3 years ago

dwhall commented 5 years ago

The implementation of Ahsm.postFIFO() requires the sender to have a reference to the instance of the recipient. If the sender and the recipient are in separate modules, how do they get the reference to the instance? The current workaround is that the sender and receiver must use the pub/sub pattern via Framework.publish().

dwhall commented 3 years ago

The problem is how to do this:

module1.py:
foo = FooAhsm()

module2.py:
bar = BarAhsm()
foo.post_fifo(farc.Event(farc.Signal.BAZ, 'value'))

and there is likely a way to do this (because Python is awesome). But just because we have the power to do something doesn't mean we should do it.

If you have the problem mentioned above, I propose this two-step solution. Step 1, solve your python module dependencies completely ignoring farc and state machines. That is, make it so that wherever you are wanting to call foo.post_fifo(), that you could call foo.any_method().

Step 2, Encapsulate your state machines' Events with a public method in your state machine's class. So, instead of foo.post_fifo(farc.Event(farc.Signal.BAZ, 'value')) in the example above, you should make the following new method in class FooAhsm:

def post_baz(self, value):
    self.post_fifo(farc.Event(farc.Signal.BAZ, value))

This encapsulation is nice because it means if you have a complex value (like a tuple with many fields), you only need to know those details in one module, not the event-poster and event-handler modules. This encapsulation also lets the Python compiler make sure the poster and handler modules have matching signatures.

See post_rx_action() here, for a real-world example.