Created
August 7, 2018 07:36
-
-
Save maheshgawali/f6be22d237f4fc061abaaf0d85b9c1aa to your computer and use it in GitHub Desktop.
a stateful function dispatcher using simple python using chaining vs maintaining a dict
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# OBJECTIVE | |
# 1. script should be able to pick up from where it left off, assume that state is saved extrenally in some datastore | |
# 2. order of execution of methods matters | |
class statefulDispatcherUsingChaining(): | |
def __init__(self, current_state=None): | |
self.current_state = "one" if not current_state else current_state | |
def state_one(self): | |
if not self.current_state == 'one': | |
return self | |
else: | |
# assign the next state | |
self.current_state = 'two' | |
print("state is one") | |
return self | |
def state_two(self): | |
if not self.current_state == 'two': | |
return self | |
else: | |
# assign the next state | |
self.current_state = 'three' | |
print("state is two") | |
return self | |
def state_three(self): | |
if not self.current_state == 'three': | |
return self | |
else: | |
# assign the next state | |
self.current_state = 'done' | |
print("state is three") | |
return self | |
class statefulDispatcherUsingData(): | |
def __init__(self, current_state=None): | |
self.state_map = { | |
"one": { | |
"func": self.state_one, | |
"next_state": "two" | |
}, | |
"two": { | |
"func": self.state_two, | |
"next_state": "three" | |
}, | |
"three": { | |
"func": self.state_three, | |
"next_state": "done" | |
}, | |
"done": { | |
"is_last_state": True | |
} | |
} | |
self.first_state = "one" | |
self.current_state = "one" if not current_state else current_state | |
def state_one(self): | |
print("state is one") | |
def state_two(self): | |
print("state is two") | |
def state_three(self): | |
print("state is three") | |
def executor(self): | |
while not self.state_map[self.current_state].get( | |
'is_last_state', False): | |
self.state_map[self.current_state]["func"]() | |
self.current_state = self.state_map[self.current_state][ | |
"next_state"] | |
def call_using_data(): | |
# data driven approach, where mapping drives it | |
# PROS: all state orchestration is in one place and the individual methods dont need any knowledge of the state | |
# CONS: extra dict is needed to maintain state mapping | |
print("\n===> call_using_data\n") | |
sd = statefulDispatcherUsingData(current_state='one') | |
# sd.current_state = 'two' | |
sd.executor() | |
def call_using_chaining(): | |
# using usual chaining in python | |
# PROS: pythonic way of doing chaining in functions without any additional dict to maintain state mapping | |
# CONS: individual methods need to be aware of the states and code readability is screwed up | |
print("\n===> call_using_chaining\n") | |
sd = statefulDispatcherUsingChaining(current_state='one') | |
# sd.current_state = 'two' | |
# to change order, just change order of chaining | |
sd.state_one().state_two().state_three() | |
call_using_data() | |
call_using_chaining() | |
# output looks like this | |
# ===> call_using_data | |
# state is one | |
# state is two | |
# state is three | |
# ===> call_using_chaining | |
# state is one | |
# state is two | |
# state is three |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
for simplicity I am not doing the storing of state in external datastore here (file-ops / redis / etc),
uncomment
sd.current_state
lines to simulate similar behaviour