假设您有如下代码:

_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()...


对我来说,这是一个不好的模式,有一些缺点:


可以创建Doer而不满足其先决条件
该代码不容易测试,因为不能直接模拟ConnPool。
Init必须在第一次调用。如果更改了它以便可以多次调用,则必须添加额外的逻辑以检查是否已定义变量,并且必须传递大量NULL值以跳过重新初始化。
如果出现线程,则通过添加锁定使上述操作变得更加复杂
全局变量并没有被用来传达状态(严格来说这不是很糟糕,但是有代码的味道)


另一方面,一些优点:


调用Init(5, "user/pass", 2, "user/pass")非常方便
简单而“干净”


就我个人而言,我认为弊大于利,即可测试性和确定的前提条件胜过简单和方便。

最佳答案

在我看来,此示例的唯一问题是使用全局状态。所以不要那样做。

认真地说,当出现问题时,将适当的上下文传递给执行者,即可解决您担心的问题。在某些情况下,“适当的上下文”可能是几个简单的参数(例如,读者列表和作者列表),或者可能是更复杂的集合对象(“连接管理器”,可能在外部添加或删除了连接)给引用它的任何人)。

要明确解决您的缺点:


如果Doer有前提条件,请对其进行验证。如果不符合,请提出例外。
(如果将ConnPool作为参数传递给ctor或worker函数,则可以解决。)
让Init创建要传递给Doer的东西,而不是创建全局数据。对于嘲笑,是否也要通过课程?基本上,使用某种工厂。
如果共享状态,则只需要担心状态中的线程安全。如果每个线程都有自己的连接管理器(例如),那么在此级别没有什么可锁定的。
(如果不使用全局变量,则解决此问题。)


因此,这样做并非特别不方便:

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函数,这显然可以满足您的要求。)

10-04 11:45