परिचय: "स्वच्छ कोड" सौंदर्यशास्त्र के बारे में क्यों नहीं है
\n\nजब आप कोटलिन में लिखना शुरू करते हैं, तो ऐसा लगता है कि भाषा स्वयं आधी समस्याओं का समाधान कर देती है। Java की तरह कोई बॉयलरप्लेट नहीं है। `data class`, लैम्ब्डा, कोरूटीन हैं। लेकिन अगर आप बस "जैसे चले" कोड डाल दें, तो एक महीने बाद आप स्वयं इसे समझ नहीं पाएंगे। और अगर प्रोजेक्ट पर एक टीम काम कर रही है - तो सहकर्मी आपसे नफरत करेंगे (या आप उनसे)।
\n\nकोटलिन में स्वच्छ कोड टैब बनाम स्पेस के बारे में नहीं है। यह संज्ञानात्मक भार को कम करने, तर्क को पारदर्शी बनाने और उन बगों से बचने के बारे में है जो "सुविधाजनक" संरचनाओं में छिपे होते हैं। इस लेख में मैं विशिष्ट तकनीक दिखाऊंगा: nullable के साथ काम करने से लेकर scope functions और sealed क्लासेज के उपयोग तक। बिना पानी, केवल अभ्यास।
\n\n1. Null Safety: "?" और "!!" को कैसे न बढ़ाएं
\n\nकोटलिन को अपनी टाइप सिस्टम पर गर्व है, लेकिन कई लोग ऐसे लिखते हैं जैसे यह "सिंटैक्टिक शुगर" वाला Java हो। मुख्य एंटीपैटर्न `?.let` की श्रृंखलाएं और घबराहट भरे `!!` हैं।
\n\nखराब (पठनीयता प्रभावित होती है):
\nuser?.address?.city?.let { city ->\n println(city)\n} ?: run {\n println("No city")\n}\n\nअच्छा (सुरुचिपूर्ण और स्वच्छ):
\nval city = user?.address?.city\nprintln(city ?: "No city")\n\n`!!` का उपयोग केवल तभी करें जब आप 100% सुनिश्चित हों कि मान null नहीं है (उदाहरण के लिए, परीक्षणों में या `if` में जांच के बाद)। प्रोडक्शन में - यह एक ग्रेनेड है। यदि आपको nullable को non-null में बदलना है और दोनों मामलों को संभालना है - तो when या एल्विस ऑपरेटर का उपयोग करें।
2. Scope Functions: `apply`, `run`, `with`, `let`, `also` — कब क्या?
\n\nयह एक शक्तिशाली उपकरण है, लेकिन इसका अक्सर दुरुपयोग किया जाता है। सुनहरा नियम: scope functions को एक दूसरे के अंदर नेस्ट न करें। यदि आपके पास `list.apply { ... }.let { ... }` है - तो आप सेंवई लिख रहे हैं।
\n\nचयन के नियम:
\n- \n
apply— ऑब्जेक्ट के कॉन्फ़िगरेशन के लिए (स्वयं ऑब्जेक्ट लौटाता है)। बिल्डरों के लिए आदर्श। \n let— non-null मान के साथ क्रिया करने के लिए (अक्सर `?.` के साथ जोड़ी में)। \n run— जब मान की गणना करके परिणाम लौटाना हो। \n with— बिना रिटर्न के एक ऑब्जेक्ट के कॉल को समूहित करने के लिए। \n also— साइड इफेक्ट्स के लिए (लॉगिंग, वैलिडेशन)। \n
स्वच्छ उदाहरण:
\ndata class User(var name: String, var age: Int)\n\nfun createUser(): User = User("Unknown", 0).apply {\n name = "Alice"\n age = 30\n}\n\n`user?.let { it.name }` न लिखें - यह अतिरिक्त है। बस `user?.name` लिखें।
\n\n3. Extension Functions: उपयोगिता वर्ग न बनाएं
\n\nJava में आप `StringUtils.capitalize(str)` लिखेंगे। कोटलिन में - `str.capitalize()`। Extension functions किसी दूसरे वर्ग को इनहेरिट किए बिना उसे "पूरा लिखने" का एक तरीका है।
\n\nउपयोगी extension का उदाहरण:
\nfun String.isValidEmail(): Boolean {\n return this.contains("@") && this.contains(".")\n}\n\nलेकिन अति न करें। यदि extension-function का उपयोग केवल एक स्थान पर होता है - तो संभवतः इसे प्राइवेट होना चाहिए। और `Any` पर extension न बनाएं - यह टाइप सिस्टम को तोड़ता है।
\n\n4. Sealed Classes और When: if-else के बजाय आपका मुख्य उपकरण
\n\nजब आपके पास स्थितियों का एक सीमित सेट हो (उदाहरण के लिए, API अनुरोध का परिणाम), तो sealed class का उपयोग करें। यह गारंटी देता है कि आपने सभी विकल्पों को संभाला है।
सही दृष्टिकोण:
\nsealed class NetworkResult<out T> {\n data class Success<T>(val data: T) : NetworkResult<T>()\n data class Error(val message: String, val code: Int) : NetworkResult<Nothing>()\n object Loading : NetworkResult<Nothing>()\n}\n\nfun handle(result: NetworkResult<String>) {\n when (result) {\n is NetworkResult.Success -> println("Data: ${result.data}")\n is NetworkResult.Error -> println("Error: ${resu