कोटलिन में डिपेंडेंसी इंजेक्शन का परिचय
कोटलिन में आधुनिक डेवलपमेंट के लिए क्लासेस के बीच डिपेंडेंसी का कुशल प्रबंधन आवश्यक है। Dependency Injection (DI) एक डिज़ाइन पैटर्न है जो किसी ऑब्जेक्ट को उसकी डिपेंडेंसी बाहर से प्रदान करने की अनुमति देता है, न कि उन्हें अंदर बनाने की। इससे कोड का युग्मन कम होता है, परीक्षण सरल होता है और एप्लिकेशन अधिक लचीला बनता है।
इस लेख में, हम समझेंगे कि डिपेंडेंसी इंजेक्शन क्या है, इसकी आवश्यकता क्यों है, और कोटलिन में इसे लागू करने के तीन तरीकों पर विचार करेंगे: मैन्युअल इंजेक्शन, Hilt लाइब्रेरी का उपयोग और हल्के फ्रेमवर्क Koin का उपयोग। यह सामग्री शुरुआती और अनुभवी डेवलपर्स दोनों के लिए उपयोगी होगी जो अपने प्रोजेक्ट्स की आर्किटेक्चर को व्यवस्थित करना चाहते हैं।
डिपेंडेंसी इंजेक्शन के मूल सिद्धांत
DI के बिना समस्या
एक क्लास UserService की कल्पना करें जो सीधे UserRepository का एक इंस्टेंस बनाती है:
class UserService { private val repository = UserRepository() // कठोर युग्मन
fun getUser(id: Int): User { return repository.findById(id) }}ऐसे कोड का परीक्षण करना कठिन है: आप UserRepository को mock-ऑब्जेक्ट से प्रतिस्थापित नहीं कर सकते। इसके अलावा, UserRepository के कंस्ट्रक्टर में बदलाव होने पर, इसे बनाने वाले सभी स्थानों को संशोधित करना होगा।
समाधान: कंस्ट्रक्टर के माध्यम से इंजेक्शन
DI लागू करने का सबसे सरल तरीका कंस्ट्रक्टर के माध्यम से डिपेंडेंसी प्रदान करना है:
class UserService(private val repository: UserRepository) { fun getUser(id: Int): User { return repository.findById(id) }}अब UserService को यह नहीं पता कि UserRepository कैसे बनाया जाता है। आप कोई भी कार्यान्वयन प्रदान कर सकते हैं - वास्तविक डेटाबेस, नकली परत या परीक्षण के लिए mock।
इनवर्जन ऑफ कंट्रोल (IoC)
DI का Inversion of Control (IoC) सिद्धांत से गहरा संबंध है। क्लास द्वारा स्वयं डिपेंडेंसी बनाने के बजाय, नियंत्रण एक बाहरी कंटेनर या फैक्ट्री को सौंप दिया जाता है। यह सिस्टम को कम युग्मित और आसानी से विस्तार योग्य बनाता है।
मैन्युअल डिपेंडेंसी इंजेक्शन (Manual DI)
छोटे प्रोजेक्ट्स या शैक्षिक उद्देश्यों के लिए, फ्रेमवर्क के बिना भी काम चल सकता है। आइए मैन्युअल रूप से एक सरल डिपेंडेंसी कंटेनर बनाएं।
उदाहरण: डिपेंडेंसी कंटेनर
// रिपॉजिटरी का इंटरफ़ेस परिभाषित करेंinterface UserRepository { fun findById(id: Int): User}
// कार्यान्वयनclass UserRepositoryImpl : UserRepository { override fun findById(id: Int): User { // DB से उपयोगकर्ता प्राप्त करने का तर्क return User(id, "User$id") }}
// कंटेनर जो सभी डिपेंडेंसी को एकत्रित करता हैclass AppContainer { val userRepository: UserRepository = UserRepositoryImpl() val userService: UserService by lazy { UserService(userRepository) }}
// उपयोगfun main() { val container = AppContainer() val service = container.userService println(service.getUser(1))}लाभ: पूर्ण नियंत्रण, कोई बाहरी डिपेंडेंसी नहीं, समझने में आसान।
नुकसान: प्रोजेक्ट बढ़ने पर कंटेनर बड़ा हो जाता है, ऑब्जेक्ट्स के जीवनचक्र और उनके स्कोप को प्रबंधित करना कठिन हो जाता है।
Hilt के साथ डिपेंडेंसी इंजेक्शन
Hilt कोटलिन में Android एप्लिकेशन के लिए Google की आधिकारिक DI लाइब्रेरी है। यह Dagger पर आधारित है, लेकिन कॉन्फ़िगर करने में काफी सरल है।
Hilt की स्थापना
build.gradle.kts (प्रोजेक्ट स्तर) में जोड़ें:
plugins { id("com.google.dagger.hilt.android") version "2.48" apply false}एप्लिकेशन मॉड्यूल के build.gradle.kts में:
plugins { id("com.google.dagger.hilt.android")}
dependencies { implementation("com.google.dagger:hilt-android:2.48") kapt("com.google.dagger:hilt-compiler:2.48")\