Suppose you had code like this:
_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()...
To me, this is a bad pattern to follow, some cons:
Doers can be created without its preconditions being satisfied- The code isn’t easily testable because ConnPool can’t be directly mocked out.
Inithas to be called right the first time. If its changed so it can be called multiple times, extra logic has to be added to check if variables are already defined, and lots of NULL values have to be passed around to skip re-initializing.- In the event of threads, the above becomes more complicated by adding locking
- Globals aren’t being used to communicate state (which isn’t strictly bad, but a code smell)
On the other hand, some pros:
- its very convenient to call
Init(5, "user/pass", 2, "user/pass") - It simple and “clean”
Personally, I think the cons outweigh the pros, that is, testability and assured preconditions outweigh simplicity and convenience.
It seems to me that the single problem with this example is the use of global state. So don’t do that.
Seriously- the concerns you’re worried about are solved by passing the appropriate context to the Doer when it comes up. In some cases, “appropriate context” may be a couple of plain arguments (e.g. a list of readers and a list of writers) or it might be a more complicated aggregate object (the “connection manager” which may have connections added and removed external to anyone who’s referencing it).
To explicitly address your cons:
So- it’s not particularly less convenient to do:
So, I don’t know. I don’t see that as particularly less concise or less readable than your example. (Alternatively, you could pass the connection manager to the Read function, that’ll be up to your requirements obviously.)