私のアプリケーションで通常行うことは、ファクトリメソッドを使用してすべてのサービス/ dao/repo /クライアントを作成することです
class Service:
def init(self, db):
self._db = db
@classmethod
def from_env(cls):
return cls(db=PostgresDatabase.from_env())
アプリを作成するとき
service = Service.from_env()
すべての依存関係を作成するもの
実際のデータベースを使用したくない場合のテストでは、DIを実行します
service = Service(db=InMemoryDatabse())
サービスはデータベースの作成方法を知っており、どのデータベースタイプを作成するか(InMemoryDatabseまたはMongoDatabaseでもかまいません)を知っているので、それはクリーン/ 16進数アーキテクチャとはかなり異なると思います。
私はクリーン/ 16進アーキテクチャでは私が持っていると思います
class DatabaseInterface(ABC):
@abstractmethod
def get_user(self, user_id: int) -> User:
pass
import inject
class Service:
@inject.autoparams()
def __init__(self, db: DatabaseInterface):
self._db = db
そして私はインジェクターフレームワークを設定して
# in app
inject.clear_and_configure(lambda binder: binder
.bind(DatabaseInterface, PostgresDatabase()))
# in test
inject.clear_and_configure(lambda binder: binder
.bind(DatabaseInterface, InMemoryDatabse()))
そして私の質問は:
別のデータベースを使用したい場合や、簡単な方法で柔軟に実行したい場合があるため、サービスを構成するには、依存性注入がより良い方法であると考えます
最初の例は、「適切な」クリーン/ヘクスにかなり近いものです。不足しているのはコンポジションルートの考え方であり、インジェクターフレームワークがなくてもクリーン/ヘクスを実行できます。それがなければ、あなたは次のようなことをするでしょう:
class Service:
def __init__(self, db):
self._db = db
# In your app entry point:
service = Service(PostGresDb(config.Host, config.port, config.dbname))
これは、話をする相手に応じて、Pure/Vanilla/Poor ManのDIによって決まります。ダックタイピングや構造タイピングに頼ることができるため、抽象的なインターフェースは絶対に必要というわけではありません。
DIフレームワークを使用するかどうかは、意見と好みの問題ですが、その道を進むことを選択した場合、考慮できるpunqのような注入する他のより簡単な代替手段があります。
https://www.cosmicpython.com/ は、これらの問題を詳細に検討するための優れたリソースです。