Your question boils down to "what kind of workflow am I in?" and the traditional way to solve such problems is using object-oriented patterns. Using object-oriented design properly often results in the elimination of conditionals.
Put the methods on a class. You can either pass the "kind of thing it is" at instantiation, or you can model that using inheritance, depending on your needs.
Using a single class and passing the "kind" at instantiation:
class Workflow:
def __init__(self, kind):
self.kind = kind
def f1(self):
self.f2()
def f2(self):
self.f3()
def f3(self):
self.f4()
def f4(self):
print(self.kind)
# now use it
a = Workflow(123)
b = Workflow(456)
a.f1() # prints 123
b.f1() # prints 456
Notice there's no if
involved. There doesn't need to be. Something like this would be missing the point:
def f4(self):
if self.kind == "A":
print(123)
else if self.kind == "B":
print(456)
The distinction is made earlier, when the object is instantiated. Thereafter each instance has its own behavior which is not predicated on anything.
If the two workflows have more complex behavior (e.g. f4()
actually does some significant work) then you probably want inheritance. Define a base class, then subclass it for each kind of thing you want to be able to create.
class WorkflowBase:
def f1(self):
self.f2()
def f2(self):
self.f3()
def f3(self):
self.f4()
def f4(self):
return
class WorkflowA(WorkflowBase):
def f4(self):
print(123)
class WorkflowB(WorkflowBase):
def f4(self):
print(456)
# using them
a = WorkflowA()
b = WorkflowB()
a.f1() # prints 123
b.f1() # prints 456
Here the behavior is baked into either WorkflowA
or WorkflowB
and the fact that you have an instance of one class or the other is what activates the differing result.
It also does not require you to inspect the call stack, which is quite a complicated condition. That is fun to do, I understand the allure well, but it is slow-ish, and it makes your code difficult for others to understand.