Reputation: 149
I'm implementing an "engine" class (described below in detail) and I'm not sure what kind of object to use. I've tried doing a little reading on OO patterns but I'm still not sure. I think my question is language agnostic, but fwiw I'm using Python.
I want to make a class that gets some initialization (e.g. a database connection and some other configuration) and then it can be called repeatedly to process bits of info. For the bits of info, I've broken up my logic into a bunch of methods, but now I have a huge calling signature for each method because I need to pass all kinds of things into each one.
The calling code will look something like this:
db = get_a_db_connection()
my_engine = Engine(db, config)
while True:
my_info = get_info_from_somewhere()
my_engine.process_info(my_info)
And the actual Engine class as I have it looks something like this:
class Engine(object):
def __init__(self, db, config):
self.db = db
# Also store the config - it's a little more complicated than
# this but I am abstracting away details that don't seem needed
self.config = config
def process_info(self, info):
foo = self.method1(info)
bar = self.method2(info, foo)
baz = self.method3(info, bar)
qux = self.method4(info, foo, bar, baz)
bla = self.method5(info, bar, baz, qux)
def method1(self, info):
# Do something and return intermediate info
return some_transformation_on_info
# Definitions for method2 - method5 (and more) follow
def method2(self, info, foo):
...
<snip>
It seems like it'd be nice to be able to store those intermediate things as attributes so I don't need to pass them as parameters every time. But it doesn't seem appropriate to store them as attributes since they are specific to a piece of info and not the class as a whole.
Is this a case where I use the factory pattern to create an intermediate object that actually does the processing of info?
Upvotes: 2
Views: 127
Reputation: 10162
You could pass an environment around:
class Engine(object):
def __init__(self, db, config):
self.db = db
self.config = config
def process_info(self, info):
env = {'info': info}
self.method1(env)
self.method2(env)
self.method3(env)
self.method4(env)
self.method5(env)
def method1(self, env):
env['foo'] = some_transformation_on_info(env['info'])
def method2(self, env):
env['bar'] = something_from(env['foo'])
def method3(self, env):
env['baz'] = my_func(env['bar'])
def method4(self, env):
env['qux'] = your_func(env['foo'], env['bar'], env['baz'])
def method5(self, env):
env['bla'] = your_func(env['bar'], env['baz'], env['qux'])
That way, process_info()
doesn't need to know what's going on in all the methods it calls.
If you don't like the dictionary subscription syntax, you can do this:
class Environment(object):
pass
class Engine(object):
def __init__(self, db, config):
self.db = db
self.config = config
def process_info(self, info):
env = Environment()
env.info = info
self.method1(env)
self.method2(env)
self.method3(env)
self.method4(env)
self.method5(env)
def method1(self, env):
env.foo = some_transformation_on_info(env.info)
def method2(self, env):
env.bar = something_from(env.foo)
def method3(self, env):
env.baz = my_func(env.bar)
def method4(self, env):
env.qux = your_func(env.foo, env.bar, env.baz)
def method5(self, env):
env.bla = your_func(env.bar, env.baz, env.qux)
Upvotes: 0
Reputation: 91017
class EngineInfoProcessor(object):
def __init__(self, engine, info):
self.engine = engine
self.info = info
def process(self):
foo = self.engine.method1(info)
self.foo = foo # if you want
yield foo # if you want
bar = self.method2(info, foo)
self.bar = bar # ...
yield bar # ...
baz = self.method3(info, bar)
self.baz = baz
yield baz
qux = self.method4(info, foo, bar, baz)
self.qux = qux
yield qux
bla = self.method5(info, bar, baz, qux)
self.bla = bla
yield bla
might be what you want.
Upvotes: -1
Reputation: 10162
It much depends on the logic of the parameters. But you can consider defining a binding object which has two attributes: an engine and a info. Then you move all these function on the binding object.
Upvotes: 3