बड़ी टीमों के लिए 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 और अन्य स्टैटिक विश्लेषण टूल का इस्तेमाल करके, अपनी टीम के लिए तय किए गए कोडिंग स्टैंडर्ड लागू करें. klint, तीसरे पक्ष का Kotlin लिंटर है. यह 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 शून्य नहीं है, तो 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 में, डेलिगेशन के ज़रिए व्यवहार लागू करने की सुविधा पहले से मौजूद है. इससे कंपोज़िशन को आसान बनाने में मदद मिलती है.

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

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

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