Skip to content

Instantly share code, notes, and snippets.

@maheshgawali
Created August 7, 2018 07:36
Show Gist options
  • Save maheshgawali/f6be22d237f4fc061abaaf0d85b9c1aa to your computer and use it in GitHub Desktop.
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
#!/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
@maheshgawali
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment