【要約】Pythonで理解するDIPとDI [Zenn_Python] | Summary by TechDistill
> Source: Zenn_Python
Execute Primary Source
// Problem
開発者が、業務ロジックの中に具体的な外部ライブラリやAPIクライアントを直接記述してしまう問題。マッチングサービスの実装において、
OpenAiFitAssessorを内部で直接生成した場合、以下の課題に直面する。- ・業務ロジックが特定の技術(OpenAI)に密結合する。
- ・ユニットテスト時にAPIキーやネットワーク、利用料金が必要になる。
- ・LLMの非決定的な出力やレート制限の影響をテストが受ける。
- ・技術的な詳細(モデル名やプロンプト)が業務コードに漏れ出す。
// Approach
設計者が、依存関係の向きを制御するために、DIによる注入とDIPによる抽象化を段階的に適用する。具体的な解決ステップは以下の通りである。
1.DI(依存性注入)の導入:コンストラクタを通じて、依存オブジェクトを外部から受け取るように変更する。
2.DIP(依存性逆転の原則)の適用:
typing.Protocolを用い、利用側が必要とする「能力」を抽象として定義する。3.依存方向の逆転:業務サービスと具体実装の両方が、利用側が定義した抽象(Protocol)へ向かう構造を作る。
4.Composition Rootの設置:アプリケーションの起動時に、具体的な実装を組み立てて注入する場所を設ける。
// Result
適切な設計により、業務ロジックの独立性とテストの品質が劇的に向上する。DIPとDIを組み合わせることで、以下の成果が得られる。
- ・APIやネットワークを必要としない、高速で安定したユニットテストが可能になる。
- ・LLMベンダーの変更や、ルールベースへの切り替えが容易になる。
- ・業務ロジックが、SDKの仕様やプロンプト形式などの技術詳細から完全に分離される。
Senior Engineer Insight
> DIコンテナは組み立てを楽にするが、DIPを保証しない。重要なのは、外部APIやDBなどの境界において、利用側の要求を
Protocolで定義することだ。過剰な抽象化は避けるべきだが、技術詳細を業務ロジックから隔離する設計は、大規模開発の保守性を決定づける。現場では、まず手動DIから始め、複雑性が増した段階でコンテナ導入を検討すべきだ。