在python应用程序中混合和匹配组件的最佳方法

时间:2011-02-07 20:43:30

标签: python architecture composition

我有一个使用我写的消息队列的简单发布/订阅模块的组件。我想试试像RabbitMQ这样的其他实现。但是,我想使这个后端更改可配置,以便我可以在我的实现和第三方模块之间切换清洁度和测试。

显而易见的答案似乎是:

  1. 阅读配置文件
  2. 创建可修改的设置对象/ dict
  3. 修改目标组件以延迟加载指定的实现。
  4. 类似的东西:

    # component.py
    from test.queues import Queue
    
    class Component:
    
      def __init__(self, Queue=Queue):
          self.queue = Queue()
    
      def publish(self, message):
          self.queue.publish(message)
    
    # queues.py
    import test.settings as settings
    
    def Queue(*args, **kwargs):
      klass = settings.get('queue')
      return klass(*args, **kwargs)
    

    不确定init是否应该接受Queue类,我认为这有助于轻松指定测试时使用的队列。

    我的另一个想法是像http://www.voidspace.org.uk/python/mock/patch.html这样的东西,但似乎会变得混乱。好处是我不必修改代码来支持交换组件。

    任何其他想法或轶事都将受到赞赏。

    编辑:修正缩进。

1 个答案:

答案 0 :(得分:2)

我之前做过的一件事是创建一个每个特定实现继承自的公共类。然后有一个可以轻松遵循的规范,每个实现都可以避免重复他们共享的某些代码。

这是一个不好的例子,但您可以看到如何使saver对象使用指定的任何类,而其余的代码也不关心。

class SaverTemplate(object):
    def __init__(self, name, obj):
        self.name = name
        self.obj = obj

    def save(self):
        raise NotImplementedError


import json
class JsonSaver(SaverTemplate):
    def save(self):
        file = open(self.name + '.json', 'wb')
        json.dump(self.object, file)
        file.close()

import cPickle
class PickleSaver(SaverTemplate):
    def save(self):
        file = open(self.name + '.pickle', 'wb')
        cPickle.dump(self.object, file, protocol=cPickle.HIGHEST_PROTOCOL)
        file.close()

import yaml
class PickleSaver(SaverTemplate):
    def save(self):
        file = open(self.name + '.yaml', 'wb')
        yaml.dump(self.object, file)
        file.close()


saver = PickleSaver('whatever', foo)
saver.save()