I have a big architecture question about how to pass set of configurable / replaceable objects to modules of my project? For example the set may be a bot
, logger
, database
, etc.
Currently I'm just importing they, it make a big problem when you want to replace them during a tests.
Lets' say import app.bot
will hard to test and patch
I had tried a multiple solutions but failed with them:
Option 1:
Create some base class with which will accepts set of such objects (db
, bot
, etc).
Every logic class (who need this set) will inherit this class.
AFAIK the similar approach there in SqlAlchemy ORM.
So the code will looks like:
app.config.py
:
Class Config:
db: DB
...
tests.py
:
import app.config
Config.db = Mock()
create_app.py
:
import app.config
def create_app(db):
app.config.Config.db = db
logic.py
import app.config
User(app.config.Config):
def handle_text(text):
self.db.save_text(text=text)
...
The problem with this case is that most likely you can't importing as from app.config import Config
because it will lead to wrong behavior and this is implicit restriction.
Option 2
Pass this set in __init__
arguments to every instance.
(It's ma be a problem if app has many classes, > 20 like in my app).
User:
def __init__(..., config: ProductionConfig):
...
Option 3
In many backend frameworks (flask for example) there are context
object.
Well we can inject our config into this context during initialization.
usage.py:
my_handler(update, context):
context.user.handle_text(text=update.text, db=context.db)
The problem with this approach is that every time we need to pass context
to access a database in our logic.
Option 4
Create config by condition and import it directly.
This solution may be bad because conditions increases code complexity.
I'm following rule "namespace preferable over conditions".
app.config.py
:
db = get_test_db() if DEBUG else get_production_db()
bot = Mock() if DEBUG else get_production_bot()
P.S. this question isn't "opinion based" because in some point the wrong solutions will leads to bad design and bugs therefore.
Aucun commentaire:
Enregistrer un commentaire