2010-04-07 41 views
1

假设你有这样的代码:是什么使静态初始化函数好,坏或其他?

_READERS = None 
_WRITERS = None 

def Init(num_readers, reader_params, num_writers, writer_params, ...args...): 
    ...logic... 
    _READERS = new ReaderPool(num_readers, reader_params) 
    _WRITERS = new WriterPool(num_writers, writer_params) 
    ...more logic... 

class Doer: 
    def __init__(...args...): 
    ... 
    def Read(self, ...args...): 
    c = _READERS.get() 
    try: 
     ...work with conn 
    finally: 
     _READERS.put(c) 
    def Writer(...): 
    ...similar to Read()... 

对我来说,这是一个糟糕的模式可循,一些缺点:

  1. Doer S可没有它的前提条件被满足
  2. 的创建代码不容易测试,因为ConnPool不能直接模拟出来。
  3. Init必须第一次被调用。如果它改变了,所以它可以被多次调用,额外的逻辑必须被添加来检查变量是否已经定义,并且大量的NULL值必须被传递以跳过重新初始化。
  4. 在线程的情况下,上述变通过添加锁定
  5. 全局没有被用于传送状态更复杂(这是不严格坏,但一个代码气味)

在另一方面,一些优点:

  1. 其非常方便的调用Init(5, "user/pass", 2, "user/pass")
  2. 它简单, “干净”

我个人认为利弊大于专业人士,也就是说,可测试性和可靠的先决条件大于简单性和便利性。

回答

2

在我看来,这个例子中的单个问题是使用全局状态。所以不要这样做。

说真的 - 您担心的问题可以通过向Doer传递适当的上下文来解决。在某些情况下,“恰当的上下文”可能是一些简单的参数(例如读者列表和作者列表),或者它可能是一个更复杂的聚合对象(“连接管理器”可能有连接添加和删除外部任何参考它的人)。

明确处理您的缺点:

  1. 如果实干家有前提条件,对其进行验证。如果他们不符合,举一个例外。
  2. (如果ConnPool作为参数传递给ctor或worker函数,则解决。)
  3. 使Init创建您将传递给Doer的东西,而不是创建全局数据。为了嘲弄,还要通过课程来建造?基本上,使用某种工厂。
  4. 如果共享您只需要担心您的状态中的线程安全。如果每个线程都有自己的连接管理器(例如),那么这个级别就没有任何东西可以锁定。
  5. (如果你不使用全局变量,natch解决。)

所以 - 它不是特别少做方便:

class ConnPool: 
    def __init__(self, numReaders, readerParams, numWriters, writerParams): 
     (your InitFunction with a bunch of self. prepending) 

class Doer: 
    def __init__(self, connPool, ...): 
     if not preconditions: 
     raise DoerPreconditionsNotMetError() 
     self.connections = connPool 

    def Read(self): 
     readers, writers = self.connections._READERS, self.connections._WRITERS 
     ... 

所以,我不知道。我不认为这样比你的例子更简洁或更不可读。(或者,您可以将连接管理器传递给Read函数,这将显然符合您的要求。)

+0

Thanks!这证实了我对自己的想法。 – 2010-04-09 18:26:21

相关问题