बड़ी टीमों के लिए Kotlin का इस्तेमाल करना

नई भाषा पर माइग्रेट करना मुश्किल हो सकता है. अपनी टीम को सफलता दिलाने के लिए, धीरे-धीरे माइग्रेट करें. साथ ही, छोटे-छोटे हिस्सों में माइग्रेट करें और बार-बार टेस्ट करें. Kotlin, JVM बाइटकोड में कंपाइल होता है. साथ ही, यह Java के साथ पूरी तरह से इंटरोऑपरेबल है. इससे माइग्रेशन की प्रोसेस आसान हो जाती है.

टीम बनाना

माइग्रेट करने से पहले, अपनी टीम के लिए एक सामान्य बेसलाइन समझ बनाना ज़रूरी है. यहां कुछ सलाह दी गई हैं, जो आपकी टीम के सीखने की प्रोसेस को तेज़ करने में मददगार साबित हो सकती हैं.

स्टडी ग्रुप बनाना

स्टडी ग्रुप, सीखने और याद रखने में मदद करने का एक असरदार तरीका है. स्टडी से पता चलता है कि ग्रुप में सीखी गई चीज़ों को दोहराने से, कॉन्टेंट को याद रखने में मदद मिलती है. ग्रुप के हर सदस्य के लिए, Kotlin की कोई किताब या अन्य स्टडी मटीरियल लें. साथ ही, ग्रुप से हर हफ़्ते दो चैप्टर पढ़ने के लिए कहें. हर मीटिंग के दौरान, ग्रुप को यह तुलना करनी चाहिए कि उन्होंने क्या सीखा है. साथ ही, उन्हें किसी भी सवाल या ऑब्ज़र्वेशन पर चर्चा करनी चाहिए.

सिखाने की संस्कृति बनाना

हालांकि, हर कोई खुद को शिक्षक नहीं मानता, लेकिन हर कोई सिखा सकता है. टेक्नोलॉजी या टीम लीड से लेकर इंडिविजुअल कॉन्ट्रिब्यूटर तक, हर कोई सीखने का ऐसा माहौल बना सकता है जिससे सफलता हासिल करने में मदद मिल सकती है. इसे आसान बनाने का एक तरीका यह है कि समय-समय पर प्रज़ेंटेशन आयोजित किए जाएं. इनमें टीम का कोई एक सदस्य, सीखी गई किसी चीज़ के बारे में बात करे या कोई जानकारी शेयर करे. अपने स्टडी ग्रुप से हर हफ़्ते एक नया चैप्टर प्रज़ेंट करने के लिए वॉलंटियर के बारे में पूछें. ऐसा तब तक करें, जब तक आपकी टीम भाषा के साथ सहज न हो जाए.

किसी सदस्य को चैंपियन बनाना

आखिर में, सीखने की कोशिशों को लीड करने के लिए, किसी सदस्य को चैंपियन बनाएं. यह व्यक्ति, अडॉप्शन की प्रोसेस शुरू करने पर सब्जेक्ट मैटर एक्सपर्ट (एसएमई) के तौर पर काम कर सकता है. इस व्यक्ति को Kotlin से जुड़ी अपनी सभी प्रैक्टिस मीटिंग में शामिल करना ज़रूरी है. आदर्श तौर पर, यह व्यक्ति Kotlin के बारे में पहले से ही उत्साहित है और उसके पास काम करने का कुछ अनुभव है.

धीरे-धीरे इंटिग्रेट करना

धीरे-धीरे शुरुआत करना और अपने इकोसिस्टम के किन हिस्सों को सबसे पहले माइग्रेट करना है, इसके बारे में रणनीति बनाना ज़रूरी है. अक्सर, इसे फ़्लैगशिप ऐप्लिकेशन के बजाय, अपने संगठन के किसी एक ऐप्लिकेशन तक सीमित रखना सबसे अच्छा होता है. चुने गए ऐप्लिकेशन को माइग्रेट करने के मामले में, हर स्थिति अलग होती है. हालांकि, यहां कुछ सामान्य जगहें दी गई हैं जहां से शुरुआत की जा सकती है.

डेटा मॉडल

आपके डेटा मॉडल में, कई तरीकों के साथ-साथ, स्टेट की काफ़ी जानकारी भी शामिल हो सकती है. डेटा मॉडल में, toString, equals, और hashCode जैसे सामान्य तरीके भी हो सकते हैं. आम तौर पर, इन तरीकों को माइग्रेट किया जा सकता है और आइसोलेशन में इनकी यूनिट टेस्टिंग की जा सकती है.

उदाहरण के लिए, Java का यह स्निपेट देखें:

public class Person {

   private String firstName;
   private String lastName;
   // ...

   public String getFirstName() {
       return firstName;
   }

   public void setFirstName(String firstName) {
       this.firstName = firstName;
   }

   public String getLastName() {
       return lastName;
   }

   public void setLastName(String lastName) {
       this.lastName = lastName;
   }

   @Override
   public boolean equals(Object o) {
       if (this == o) return true;
       if (o == null || getClass() != o.getClass()) return false;
       Person person = (Person) o;
       return Objects.equals(firstName, person.firstName) &&
               Objects.equals(lastName, person.lastName);
   }

   @Override
   public int hashCode() {
       return Objects.hash(firstName, lastName);
   }

   @Override
   public String toString() {
       return "Person{" +
               "firstName='" + firstName + '\'' +
               ", lastName='" + lastName + '\'' +
               '}';
   }
}

Java क्लास को Kotlin की एक लाइन से बदला जा सकता है. जैसा कि यहां दिखाया गया है:

data class Person(var firstName: String?, var lastName: String?)

इसके बाद, इस कोड की यूनिट टेस्टिंग, मौजूदा टेस्ट सुइट के ख़िलाफ़ की जा सकती है. एक बार में एक मॉडल से शुरुआत करें. साथ ही, उन क्लास को माइग्रेट करें जो मुख्य रूप से स्टेट हैं, न कि बिहेवियर. इस दौरान, बार-बार टेस्ट करें.

टेस्ट माइग्रेट करना

टेस्ट से भी शुरुआत की जा सकती है. इसके लिए, मौजूदा टेस्ट को बदलें और Kotlin में नए टेस्ट लिखें. इससे आपकी टीम को, ऐप्लिकेशन के साथ शिप होने वाला कोड लिखने से पहले, भाषा के साथ सहज होने का समय मिलता है.

यूटिलिटी के तरीकों को एक्सटेंशन फ़ंक्शन में ले जाना

StringUtils, IntegerUtils DateUtils या YourCustomTypeUtils जैसी स्टैटिक यूटिलिटी क्लास को Kotlin एक्सटेंशन फ़ंक्शन के तौर पर दिखाया जा सकता है. साथ ही, इनका इस्तेमाल मौजूदा Java कोडबेस से किया जा सकता है.

उदाहरण के लिए, मान लें कि आपके पास कुछ तरीकों वाली StringUtils क्लास है:

package com.java.project;

public class StringUtils {

   public static String foo(String receiver) {
       return receiver...;  // Transform the receiver in some way
   }

   public static String bar(String receiver) {
       return receiver...;  // Transform the receiver in some way
   }

}

इसके बाद, इन तरीकों का इस्तेमाल आपके ऐप्लिकेशन में कहीं और किया जा सकता है. जैसा कि यहां दिखाया गया है:

...

String myString = ...
String fooString = StringUtils.foo(myString);

...

Kotlin एक्सटेंशन फ़ंक्शन का इस्तेमाल करके, Java कॉलर को वही Utils इंटरफ़ेस दिया जा सकता है. साथ ही, अपने बढ़ते Kotlin कोडबेस के लिए ज़्यादा सटीक एपीआई भी ऑफ़र किया जा सकता है.

ऐसा करने के लिए, आईडीई की ओर से दिए गए ऑटोमैटिक कन्वर्ज़न का इस्तेमाल करके, इस Utils क्लास को Kotlin में बदलकर शुरुआत की जा सकती है. आउटपुट का उदाहरण कुछ ऐसा दिख सकता है:

package com.java.project

object StringUtils {

   fun foo(receiver: String): String {
       return receiver...;  // Transform the receiver in some way
   }

   fun bar(receiver: String): String {
       return receiver...;  // Transform the receiver in some way
   }

}

इसके बाद, क्लास या ऑब्जेक्ट की परिभाषा हटाएं. साथ ही, हर फ़ंक्शन के नाम के पहले, उस टाइप का नाम जोड़ें जिस पर यह फ़ंक्शन लागू होना चाहिए. इसके अलावा, फ़ंक्शन के अंदर टाइप को रेफ़र करने के लिए इसका इस्तेमाल करें. जैसा कि यहां दिखाया गया है:

package com.java.project

fun String.foo(): String {
    return this...;  // Transform the receiver in some way
}

fun String.bar(): String {
    return this...;  // Transform the receiver in some way
}

आखिर में, कंपाइल किए गए नाम को अपने ऐप्लिकेशन के बाकी हिस्सों के साथ कंपैटिबल बनाने के लिए, सोर्स फ़ाइल के सबसे ऊपर JvmName एनोटेशन जोड़ें. जैसा कि यहां दिखाया गया है:

@file:JvmName("StringUtils")
package com.java.project
...

फ़ाइनल वर्शन कुछ ऐसा दिखना चाहिए:

@file:JvmName("StringUtils")
package com.java.project

fun String.foo(): String {
    return this...;  // Transform `this` string in some way
}

fun String.bar(): String {
    return this...;  // Transform `this` string in some way
}

ध्यान दें कि अब इन फ़ंक्शन को Java या Kotlin का इस्तेमाल करके, हर भाषा के हिसाब से तय किए गए नियमों के मुताबिक कॉल किया जा सकता है.

Kotlin

// ...

val myString: String = "hello"
val fooString = myString.foo()

// ...

Java

...
String myString = ...
String fooString = StringUtils.foo(myString);
...

माइग्रेशन की प्रोसेस पूरी करना

जब आपकी टीम Kotlin के साथ सहज हो जाए और आपने छोटे-छोटे हिस्सों को माइग्रेट कर लिया हो, तब बड़े कॉम्पोनेंट पर माइग्रेट किया जा सकता है. जैसे, फ़्रैगमेंट, ऐक्टिविटी, ViewModel ऑब्जेक्ट, और कारोबारी नियमों से जुड़ी अन्य क्लास.

ज़रूरी बातें

जिस तरह Java का एक खास स्टाइल होता है, उसी तरह Kotlin का भी अपना इडिओमैटिक स्टाइल होता है. इससे Kotlin को सटीक बनाने में मदद मिलती है. हालांकि, शुरुआत में आपको लग सकता है कि आपकी टीम ने Kotlin में जो कोड लिखा है वह Java के उस कोड जैसा दिखता है जिसे वह बदल रही है. जब आपकी टीम को Kotlin का अनुभव मिल जाता है, तो यह बदल जाता है. धीरे-धीरे बदलाव करना, सफलता की कुंजी है.

यहां कुछ तरीके दिए गए हैं, जिनकी मदद से Kotlin कोडबेस को बढ़ने के साथ-साथ एक जैसा रखा जा सकता है:

कोडिंग के सामान्य स्टैंडर्ड

अडॉप्शन की प्रोसेस में शुरुआत में ही, कोडिंग के नियमों का एक स्टैंडर्ड सेट तय करें. Android Kotlin स्टाइल गाइड से अलग, कोडिंग के नियम तय किए जा सकते हैं.

स्टैटिक विश्लेषण के टूल

Android lint और स्टैटिक विश्लेषण के अन्य टूल का इस्तेमाल करके, अपनी टीम के लिए तय किए गए कोडिंग स्टैंडर्ड लागू करें. तीसरे पक्ष का Kotlin लिंटर, ktlint, Kotlin के लिए अतिरिक्त नियम भी उपलब्ध कराता है.

लगातार इंटिग्रेशन करना

कोडिंग के सामान्य स्टैंडर्ड का पालन करें. साथ ही, अपने Kotlin कोड के लिए टेस्ट कवरेज उपलब्ध कराएं. इसे ऑटोमेटेड बिल्ड प्रोसेस का हिस्सा बनाने से, इन स्टैंडर्ड के मुताबिक काम करने और एक जैसा कोड बनाए रखने में मदद मिल सकती है.

इंटरोऑपरेबिलिटी

Kotlin, Java के साथ ज़्यादातर मामलों में आसानी से इंटरोऑपरेट करता है. हालांकि, इन बातों का ध्यान रखें.

शून्यता

Kotlin, कंपाइल किए गए कोड में शून्यता के एनोटेशन पर निर्भर करता है, ताकि Kotlin की ओर से शून्यता का अनुमान लगाया जा सके. अगर एनोटेशन उपलब्ध नहीं कराए जाते हैं, तो Kotlin डिफ़ॉल्ट रूप से प्लैटफ़ॉर्म टाइप का इस्तेमाल करता है. इसे वैल्यू न होने की स्थिति या वैल्यू होने की स्थिति के तौर पर माना जा सकता है. अगर प्लैटफ़ॉर्म टाइप को ध्यान से हैंडल नहीं किया जाता है, तो रनटाइम NullPointerException की समस्याएं हो सकती हैं.

नई सुविधाएं अपनाना

Kotlin, बॉयलरप्लेट को कम करने के लिए, कई नई लाइब्रेरी और सिंटैक्टिक शुगर उपलब्ध कराता है. इससे डेवलपमेंट की स्पीड बढ़ाने में मदद मिलती है. हालांकि, Kotlin की स्टैंडर्ड लाइब्रेरी फ़ंक्शन का इस्तेमाल करते समय सावधानी बरतें और व्यवस्थित तरीके से काम करें. जैसे, कलेक्शन फ़ंक्शन, कोरोटीन, और लैम्डा.

यहां एक सामान्य समस्या दी गई है, जिसका सामना Kotlin में नए डेवलपर करते हैं. Kotlin का यह कोड देखें:

val nullableFoo: Foo? = Foo()

// This lambda executes only if nullableFoo is not null
// and `foo` is of the non-nullable Foo type
nullableFoo?.let { foo ->
    foo.baz()
    foo.zap()
}

इस उदाहरण में, अगर nullableFoo की वैल्यू null नहीं है, तो foo.baz और foo.zap को एक्ज़ीक्यूट करना है. इससे NullPointerException से बचा जा सकता है. हालांकि, यह कोड उम्मीद के मुताबिक काम करता है, लेकिन इसे पढ़ना, वैल्यू न होने की स्थिति की जांच और स्मार्ट कास्टकी तुलना में कम आसान है. जैसा कि यहां दिखाया गया है:

val nullableFoo: Foo? = null
if (nullableFoo != null) {
    nullableFoo.baz() // Using !! or ?. isn't required; the Kotlin compiler infers non-nullability
    nullableFoo.zap() // from guard condition; smart casts nullableFoo to Foo inside this block
}

जांच करना

Kotlin में, क्लास और उनके फ़ंक्शन डिफ़ॉल्ट रूप से एक्सटेंशन के लिए बंद होते हैं. आपको उन क्लास और फ़ंक्शन को साफ़ तौर पर खोलना होगा जिन्हें सबक्लास करना है. Kotlin, इनहेरिटेंस के बजाय कंपोज़िशन को बढ़ावा देने के लिए ऐसा करता है. कंपोज़िशन को आसान बनाने के लिए, Kotlin में डेलिगेशन के ज़रिए बिहेवियर लागू करने की सुविधा पहले से मौजूद है.

इस बिहेवियर से, मॉक फ़्रेमवर्क के लिए समस्या पैदा होती है. जैसे, Mockito. ये फ़्रेमवर्क, टेस्टिंग के दौरान बिहेवियर को ओवरराइड करने के लिए, इंटरफ़ेस लागू करने या इनहेरिटेंस पर निर्भर करते हैं. यूनिट टेस्ट के लिए, Mockito की Mock Maker Inline सुविधा का इस्तेमाल किया जा सकता है. इससे फ़ाइनल क्लास और तरीकों को मॉक किया जा सकता है. इसके अलावा, All-Open कंपाइलर प्लग-इन का इस्तेमाल करके, कंपाइलेशन की प्रोसेस के दौरान, Kotlin की किसी भी क्लास और उसके सदस्यों को खोला जा सकता है. ऐसा उन क्लास और सदस्यों के लिए किया जा सकता है जिनकी आपको जांच करनी है. इस प्लग-इन का इस्तेमाल करने का मुख्य फ़ायदा यह है कि यह यूनिट और इंस्ट्रूमेंटेड, दोनों तरह के टेस्ट के साथ काम करता है.

ज़्यादा जानकारी

Kotlin का इस्तेमाल करने के बारे में ज़्यादा जानने के लिए, ये लिंक देखें: