paint-brush
उपयोग-साइट लक्ष्यों से निपटने के दौरान कोटलन समस्याओं को कैसे ठीक करेंद्वारा@jesperancinha
106 रीडिंग

उपयोग-साइट लक्ष्यों से निपटने के दौरान कोटलन समस्याओं को कैसे ठीक करें

द्वारा João Esperancinha10m2024/03/21
Read on Terminal Reader
Read this story w/o Javascript

बहुत लंबा; पढ़ने के लिए

हमें कोटलिन में उपयोग-साइट लक्ष्यों का उपयोग क्यों और कहां करना चाहिए और स्प्रिंग फ्रेमवर्क जैसे ढांचे का उपयोग करते समय यह कोटलिन में कैसे भिन्न है।
featured image - उपयोग-साइट लक्ष्यों से निपटने के दौरान कोटलन समस्याओं को कैसे ठीक करें
João Esperancinha HackerNoon profile picture
0-item
1-item
2-item
3-item


कोटलिन की सबसे बड़ी ताकतों में से एक इसकी कमजोरी भी हो सकती है। जब हम आज डेटा कक्षाओं के बारे में बात करते हैं, और उसी तरह जावा रिकॉर्ड के बारे में, तो हम बॉयलरप्लेट कोड के पूर्ण उन्मूलन पर ध्यान केंद्रित करते हैं, कम से कम कई लोग जिन्हें मैं जानता हूं। बॉयलरप्लेट कोड कुछ ऐसा है जो सदियों से डेवलपर्स को परेशान कर रहा है। यह न केवल जावा में मौजूद है, बल्कि अन्य भाषाओं में भी मौजूद है। यदि हम किसी भी तरह से डेटा एक्सेस ऑब्जेक्ट बनाने के बारे में सोचते हैं, तो इससे कोई फर्क नहीं पड़ता कि हम इसे कोटलिन या जावा या किसी अन्य भाषा में करते हैं।


अक्सर हम एक ही प्रक्रिया दोहराते हैं: रिपॉजिटरी निर्माण, सेवा और नियंत्रक। हम जो कुछ भी करते हैं वह किसी भी तरह से अभी भी बॉयलरप्लेट है। हालाँकि बॉयलरप्लेट कोड डेटा क्लास या जावा रिकॉर्ड बनाने के निर्णय का एक हिस्सा हो सकता है, सॉफ्टवेयर इंजीनियरिंग का एक अधिक महत्वपूर्ण प्रतिमान इस प्रकार की डेटा संरचनाओं को बनाने का वास्तविक केंद्र बिंदु था।


यह सब अपरिवर्तनीयता या किसी भी मामले में इसकी संभावना पर निर्भर करता है। आइए समय को पीछे ले जाएं और 1995 में वापस जाएं जहां हमने किसी बिंदु पर डेटा संरचनाएं बनाना शुरू किया था जहां हम अलग-अलग चीजें निर्दिष्ट करते थे। हम फ़ील्ड्स, गेटर्स, सेटर्स, प्रॉपर्टीज़, एक्सेसर्स, एट्रिब्यूट्स और पैरामीटर्स को इस तरह से परिभाषित करेंगे कि हम अपने तर्कों को तरीकों, फ़ंक्शंस या कंस्ट्रक्टर्स तक पहुंचाने में सक्षम हो सकें। इस भाग में हमारे पास होगा 80 के दशक के मध्य की श्रृंखला: द गोल्डन गर्ल्स के पात्रों का उपयोग करते हुए कुछ मज़ेदार प्रोग्रामिंग। यह कहने के बाद, आइए देखें कि लगभग 15 वर्षों तक एक कक्षा कैसी दिखेगी:


 public class GoldenGirlsJava { public String goldenGirl1; private final String goldenGirl2; private final String goldenGirl3; private final String goldenGirl4; public GoldenGirlsJava() { this.goldenGirl1 = "Dorothy Zbornak"; this.goldenGirl2 = "Rose Nylund"; this.goldenGirl3 = "Blanche Devereaux"; this.goldenGirl4 = "Sophia Petrillo"; } public GoldenGirlsJava( String goldenGirl1, String goldenGirl2, String goldenGirl3, String goldenGirl4 ) { this.goldenGirl1 = goldenGirl1; this.goldenGirl2 = goldenGirl2; this.goldenGirl3 = goldenGirl3; this.goldenGirl4 = goldenGirl4; } public String getGoldenGirl1() { return goldenGirl1; } public void setGoldenGirl1(String goldenGirl1) { this.goldenGirl1 = goldenGirl1; } public String getGoldenGirl2() { return goldenGirl2; } public String getGoldenGirl3() { return goldenGirl3; } public String getGoldenGirl4() { return goldenGirl4; } @Override public String toString() { return "GoldenGirlsJava{" + "goldenGirl1='" + goldenGirl1 + '\'' + ", goldenGirl2='" + goldenGirl2 + '\'' + ", goldenGirl3='" + goldenGirl3 + '\'' + ", goldenGirl4='" + goldenGirl4 + '\'' + '}'; } }


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


हालाँकि, और किसी भी मामले में, बॉयलरप्लेट कोड हमेशा कई डेवलपर्स के लिए एक विवादास्पद मुद्दा था और इसलिए 2009 में, लोम्बोक आया और हमारे डेटा संरचनाओं को बनाने के तरीके में क्रांति ला दी। इसने एक एनोटेशन प्रोसेसर का उपयोग करने और विशिष्ट एनोटेशन की व्याख्या करने की अवधारणा पेश की जो हमें हमारी कक्षाओं के लिए आवश्यक गुण प्रदान करेगी और इसलिए एक लोम्बोक एनोटेटेड क्लास इस तरह दिखेगी:

 @Getter @Setter @AllArgsConstructor @ToString public class GoldenGirlsLombok { public String goldenGirl1; private final String goldenGirl2; private final String goldenGirl3; private final String goldenGirl4; public GoldenGirlsLombok() { this.goldenGirl1 = "Dorothy Zbornak"; this.goldenGirl2 = "Rose Nylund"; this.goldenGirl3 = "Blanche Devereaux"; this.goldenGirl4 = "Sophia Petrillo"; } }


और कुछ समय के लिए, लोग लोम्बोक को लेकर बहुत खुश थे! आख़िरकार वह सारा बॉयलरप्लेट कोड बनाने का बोझ ख़त्म हो गया। लेकिन यह गिरावट लगभग 7 वर्षों तक जारी रही, जब एक नया खिलाड़ी आया और इस बार यह कुछ ऐसा था जिसकी सॉफ्टवेयर विकास उद्योग को उम्मीद नहीं थी। इसे कोटलिन कहा जाता था और 2016 में इसकी शुरुआत डेटा कक्षाओं की तत्काल शुरूआत के साथ हुई। कोटलिन में हमारी गोल्डन गर्ल्स कार्यान्वयन अब इस तरह दिखेगी:

 data class GoldenGirls( var goldenGirl1: String = "Dorothy Zbornak", private val goldenGirl2: String = "Rose Nylund", private val goldenGirl3: String = "Blanche Devereaux", private val goldenGirl4: String = "Sophia Petrillo" )


हालाँकि कोटलिन ने धीरे-धीरे प्रशंसकों को इकट्ठा करना शुरू कर दिया, दूसरी ओर जावा को एहसास हुआ कि बाजार में कुछ और भी है और उस तरफ कुछ विकासों ने प्रोजेक्ट लूम की तरह कुछ गति प्राप्त करना शुरू कर दिया, जो कि बन रहा था लेकिन कुछ समय के लिए ठंडे बस्ते में डाल दिया गया था। इसीलिए, 20202 में जावा 14 की रिलीज के साथ, जावा ने जावा रिकॉर्ड पेश किए, और जावा में डेटा संरचनाएं अब इस तरह दिखेंगी:

 public record GoldenGirlsRecord( String goldenGirl1, String goldenGirl2, String goldenGirl3, String goldenGirl4 ) { public GoldenGirlsRecord() { this( "Dorothy Zbornak", "Rose Nylund", "Blanche Devereaux", "Sophia Petrillo" ); } }


और आज तक कोड सरलीकरण और कोड में कमी जारी ही प्रतीत होती है। हालाँकि, बॉयलरप्लेट कोड की कमी के साथ, हमारे दिमाग में फ़ील्ड्स, गेटर्स, सेटर्स, प्रॉपर्टीज़, एक्सेसर्स, एट्रिब्यूट्स और पैरामीटर्स की अवधारणाएँ बहुत कम दृश्यमान हो गईं और मैप करना कम आसान हो गया। चाहे हम इसे पसंद करें या न करें, वे अवधारणाएँ अभी भी यही हैं कि जेवीएम कैसे काम करता है और बाइटकोड के साथ कोड को व्यवस्थित करता है। लेकिन कोड ओवरसिम्प्लीफिकेशन वास्तव में कोड को पढ़ने में आसान बनाने के बारे में है और डेटा क्लास और जावा रिकॉर्ड के मामले में विचार डेटा संरचनाएं बनाने का भी है। जो अपरिवर्तनीय या आंशिक रूप से अपरिवर्तनीय हैं।


जावा रिकॉर्ड वास्तव में इस अर्थ में अपरिवर्तनीय हैं कि इसमें मौजूद सभी मान या इसमें शामिल संदर्भों को संशोधित नहीं किया जा सकता है। कोटलिन डेटा कक्षाएं भी उन्हीं कारणों से वास्तव में अपरिवर्तनीय हो सकती हैं, लेकिन उनमें ऐसा नहीं है जो एक तरह से डेवलपर्स को जटिल और सबसे खराब, परिवर्तनीय कोड बनाने की अनुमति देता है। किसी भी मामले में यह तब तक अच्छा है जब तक हमें इसकी आवश्यकता नहीं होती स्प्रिंग फ्रेमवर्क जैसे फ्रेमवर्क के साथ काम करना, जो एनोटेशन पर बहुत अधिक निर्भर करता है। यहाँ एक उदाहरण है:

 @Entity @Table(name = "shelf_case") data class Case( @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) val id: Long?, var designation: String?, var weight: Long? ) { constructor() : this(0L, null, null) override fun toString(): String { return super.toString() } }


यह उदाहरण ठीक काम करता है. किसी संदेह न करने वाली नज़र के लिए, यहाँ बहुत कुछ विशेष नहीं चल रहा है। यह कोटलिन में ठीक उसी तरह काम करता है जैसे यह जावा में काम करता है। लेकिन अब आइए एक ऐसे ही उदाहरण पर नजर डालें, लेकिन इस बार जैक्सन एनोटेशन के साथ:

 data class AccountNumbersPassiveDto( @NotNull val accountNumberLong: Long?, val accountNumberNullable: Long?, @DecimalMax(value = "10") @DecimalMin(value = "5") val accountNumber: BigDecimal, val accountNumberEven: Int, val accountNumberOdd: Int, @Positive val accountNumberPositive: Int, @Negative val accountNumberNegative: Int, @DecimalMax(value = "5", groups = [LowProfile::class]) @DecimalMax(value = "10", groups = [MiddleProfile::class]) @DecimalMax(value = "15", groups = [HighProfile::class]) @DecimalMax(value = "20") val accountNumberMaxList:Int )


यह उदाहरण विफल हो जाएगा और इसका कारण यह है कि कोटलिन में, कंपाइलर को यह बताने का कोई तरीका नहीं है कि हम वास्तव में अपना एनोटेशन कहां लागू करना चाहते हैं। एनोटेशन @Entity के साथ पिछले उदाहरण में, जो एक जकार्ता दृढ़ता एनोटेशन है, एनोटेशन फ़ील्ड पर सही ढंग से लागू होते हैं। यदि हम उस कोड को डिकंपाइल करें तो हमें यह मिलेगा:

 public final class Case { @Id @GeneratedValue( strategy = GenerationType.SEQUENCE ) @Nullable private final Long id; @Nullable private String designation; @Nullable private Long weight;


लेकिन बाद वाले के लिए, जो जकार्ता सत्यापन उदाहरण है, हम यह पाते हैं:

 public final class AccountNumbersPassiveDto { @Nullable private final Long accountNumberLong; @Nullable private final Long accountNumberNullable; @NotNull private final BigDecimal accountNumber; private final int accountNumberEven; private final int accountNumberOdd;



इसका मतलब यह है कि AccountNumbersDto अपने फ़ील्ड पर उन एनोटेशन से प्रभावित नहीं हुआ है। पहले उदाहरण में हम भाग्यशाली थे। यह वास्तव में विफल भी हो सकता है। यह निर्दिष्ट करने के लिए कि हमारे एनोटेशन को कहाँ जाना है, कोटलिन हमें किसी भी एनोटेशन के उपसर्ग के रूप में उपयोग-साइट लक्ष्य का उपयोग करने की संभावना देता है। निःसंदेह आवश्यकता यह है कि शर्तें पूरी की जाएं। इस मामले में, इसे ठीक करने का एक तरीका यह है कि सभी एनोटेशन के पहले इस तरह @field लगा दिया जाए:

 data class AccountNumbersPassiveDto( @field:NotNull val accountNumberLong: Long?, val accountNumberNullable: Long?, @field:DecimalMax(value = "10") @field:DecimalMin(value = "5") val accountNumber: BigDecimal, val accountNumberEven: Int, val accountNumberOdd: Int, @field:Positive val accountNumberPositive: Int, @field:Negative val accountNumberNegative: Int, @field:DecimalMax(value = "5", groups = [LowProfile::class]) @field:DecimalMax(value = "10", groups = [MiddleProfile::class]) @field:DecimalMax(value = "15", groups = [HighProfile::class]) @field:DecimalMax(value = "20") val accountNumberMaxList:Int )


यदि अब हम IntelliJ का उपयोग करके परिणामी बाइटकोड को डिकंपाइल करने का प्रयास करते हैं, तो हम पाएंगे कि इसका परिणाम जावा में इस कोड में होता है:

 public final class AccountNumbersPassiveDto { @NotNull @Nullable private final Long accountNumberLong; @Nullable private final Long accountNumberNullable; @DecimalMax("10") @DecimalMin("5") @org.jetbrains.annotations.NotNull


इसका मतलब यह है कि एनोटेशन को फ़ील्ड पर लागू कर दिया गया है और हमारा कोड उसी तरह काम करता है जैसा उसे करना चाहिए।


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


सबसे अधिक संभावना यह है कि मेरा सिद्धांत यह है कि डेवलपर्स की नई पीढ़ियाँ संभवतः उन चीजों को देखेंगी जिन्हें मेरी पीढ़ी जटिल नहीं मानती थी और सहजता से सीखी थी, वास्तव में जटिल सामग्री के रूप में। उपयोग-साइट लक्ष्यों के मामले में भी ऐसा ही है। ये ऐसी चीज़ें हुआ करती थीं जिनकी हम बहुत आसानी से कल्पना कर सकते थे। हालाँकि वर्तमान समय में, इससे उत्पन्न भ्रम के कारण कुछ अवसरों पर परियोजनाओं को समय पर विकसित होने में देरी हो रही है। बेशक, मैं सामान्यीकरण नहीं कर पाऊंगा, लेकिन जावा रिकॉर्ड और डेटा क्लास के साथ अच्छे और बुरे की भी संभावना है। डेटा कक्षाएं और रिकॉर्ड हमारे भविष्य को कैसे आकार देंगे, यह बताना मुश्किल है, लेकिन एक बात जो स्पष्ट है वह यह है कि इस समस्याग्रस्त होने के कारण, अन्य ढांचे पूरी तरह से एनोटेशन मुक्त होने पर दांव लगा रहे हैं जैसा कि Ktor के मामले में है।


मैंने इसके बारे में स्क्रिब्ड: फ़ील्ड्स-इन-जावा-एंड-कोटलिन-एंड-व्हाट-टू-एक्सपेक्ट और स्लाइड-शेयर: फ़ील्ड्स-इन-जावा-एंड-कोटलिन-एंड-व्हाट-टू-एक्सपेक्ट पर दस्तावेज़ बनाया है।


आप मेरे द्वारा दिए गए उदाहरण GitHub पर भी पा सकते हैं। गोल्डन गर्ल्स का उदाहरण यहां पाया जा सकता है: जॉर्ज-कोटलिन-टेस्ट-ड्राइव और जकार्ता दृढ़ता और सत्यापन एनोटेशन के उदाहरण यहां पाए जा सकते हैं: https://github.com/jesperancinha/jeorg-spring-master-test-drives


अंततः मैंने YouTube पर इस बारे में एक वीडियो भी बनाया जिसे आप यहीं देख सकते हैं:

यहाँ भी प्रकाशित किया गया है.