एआईडीएल स्टाइल गाइड

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

एआईडीएल का इस्तेमाल एपीआई तय करने के लिए किया जा सकता है. ऐसा तब किया जा सकता है, जब ऐप्लिकेशन को बैकग्राउंड प्रोसेस में एक-दूसरे के साथ इंटरफ़ेस करना हो या सिस्टम के साथ इंटरफ़ेस करना हो. एआईडीएल की मदद से ऐप्लिकेशन में प्रोग्रामिंग इंटरफ़ेस डेवलप करने के बारे में ज़्यादा जानकारी के लिए, Android इंटरफ़ेस डेफ़िनिशन लैंग्वेज (एआईडीएल) देखें. इस्तेमाल किए जा रहे एआईडीएल के उदाहरण देखने के लिए, एचएएल के लिए एआईडीएल और स्टेबल एआईडीएल देखें.

वर्शन

AIDL API का पुराने सिस्टम के साथ काम करने वाला हर स्नैपशॉट, किसी वर्शन से जुड़ा होता है. स्नैपशॉट लेने के लिए, m <module-name>-freeze-api चलाएं. जब भी एपीआई का कोई क्लाइंट या सर्वर रिलीज़ किया जाता है (उदाहरण के लिए, मेनलाइन ट्रेन में), तो आपको एक स्नैपशॉट लेकर एक नया वर्शन बनाना होगा. सिस्टम-टू-वेंडर एपीआई के लिए, ऐसा हर साल प्लैटफ़ॉर्म में होने वाले बदलावों के हिसाब से होना चाहिए.

अनुमति वाले बदलावों के प्रकार के बारे में ज़्यादा जानकारी और जानकारी के लिए वर्शन इंटरफ़ेस देखें.

एपीआई डिज़ाइन से जुड़े दिशा-निर्देश

सामान्य

1. हर चीज़ के बारे में जानकारी दें

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

2. केसिंग

तरीकों, फ़ील्ड, और तर्क के लिए, ऊंट के ऊपरी और निचले केस का इस्तेमाल करें. उदाहरण के लिए, पार्स किए जा सकने वाले एलिमेंट के लिए MyParcelable और आर्ग्युमेंट के लिए anArgument. शॉर्ट फ़ॉर्म के लिए, शॉर्ट फ़ॉर्म को कोई शब्द समझें (NFC -> Nfc).

[-Wconst-name] Enum की वैल्यू और कॉन्सटेंट, ENUM_VALUE और CONSTANT_NAME होने चाहिए

इंटरफ़ेस

1. इन्हें

[-Winterface-name] इंटरफ़ेस का नाम I से शुरू होना चाहिए, जैसे कि IFoo.

2. आईडी-आधारित "ऑब्जेक्ट" वाले बड़े इंटरफ़ेस का इस्तेमाल करने से बचें

जब किसी खास एपीआई से जुड़े कई कॉल हों, तो सब-इंटरफ़ेस को प्राथमिकता दें. इससे ये फ़ायदे मिलते हैं:

  • इससे क्लाइंट या सर्वर कोड को आसानी से समझा जा सकता है
  • ऑब्जेक्ट के लाइफ़साइकल को आसान बनाता है
  • बड़े न होने वाले बाइंडर का फ़ायदा उठाता है.

इसका सुझाव नहीं दिया जाता: आईडी-आधारित ऑब्जेक्ट वाला एक बड़ा इंटरफ़ेस

interface IManager {
   int getFooId();
   void beginFoo(int id); // clients in other processes can guess an ID
   void opFoo(int id);
   void recycleFoo(int id); // ownership not handled by type
}

सुझाव: अलग-अलग इंटरफ़ेस

interface IManager {
    IFoo getFoo();
}

interface IFoo {
    void begin(); // clients in other processes can't guess a binder
    void op();
}

3. एक-तरफ़ा तरीकों को दो-तरफ़ा तरीकों में इस्तेमाल न करें

[-Wmixed-oneway] वन-वे तरीकों को नॉन-वन-वे तरीकों से न मिलाएं. ऐसा करने से, क्लाइंट और सर्वर के लिए थ्रेडिंग मॉडल को समझना मुश्किल हो जाता है. खास तौर पर, किसी खास इंटरफ़ेस का क्लाइंट कोड पढ़ते समय, आपको हर एक तरीके को खोजना होगा कि वह तरीका ब्लॉक होगा या नहीं.

4. स्टेटस कोड दिखाने से बचें

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

5. ऐसी सरणियां जो आउटपुट पैरामीटर के तौर पर, नुकसान पहुंचाने वाले माने जाते हैं

[-Wout-array] अरे आउटपुट पैरामीटर वाले मेथड, जैसे कि void foo(out String[] ret) आम तौर पर खराब होते हैं. ऐसा इसलिए होता है, क्योंकि आउटपुट अरे के साइज़ का एलान करना और उसे Java में क्लाइंट तय करना ज़रूरी है. इसलिए, सर्वर, आउटपुट अरे का साइज़ नहीं चुन सकता. यह अनचाहा व्यवहार Java में अरे के काम करने के तरीके की वजह से होता है (उन्हें फिर से असाइन नहीं किया जा सकता). इसके बजाय, String[] foo() जैसे एपीआई को प्राथमिकता दें.

6. इनआउट पैरामीटर से बचें

[-Winout-parameter] इससे क्लाइंट भ्रमित हो सकते हैं. इसकी वजह यह है कि in पैरामीटर भी out पैरामीटर की तरह दिखते हैं.

7. @nullable नॉन-अरे पैरामीटर को आउट और इनआउट करने से बचें

[-Wout-nullable] Java बैकएंड, @nullable एनोटेशन को हैंडल नहीं करता, जबकि अन्य बैकएंड ऐसा करते हैं. इसलिए, हो सकता है कि out/inout @nullable T की वजह से, बैकएंड में अलग-अलग तरह की गड़बड़ियां दिखें. उदाहरण के लिए, गैर-Java बैकएंड, @nullable पैरामीटर को शून्य (C++ में, उसे std::nullopt के तौर पर सेट करना) पर सेट कर सकता है, लेकिन Java क्लाइंट उसे शून्य के तौर पर नहीं पढ़ सकता.

पार्स किए जा सकने वाले स्ट्रक्चर्ड सामान

1. इसका इस्तेमाल कब करें

स्ट्रक्चर्ड पार्सल का इस्तेमाल करें, जहां आपको कई तरह के डेटा भेजने हों.

इसके अलावा, अगर आपके पास सिर्फ़ एक तरह का डेटा है, लेकिन आपको उम्मीद है कि आने वाले समय में उसका दायरा बढ़ाना होगा. उदाहरण के लिए, String username इस्तेमाल न करें. पार्स किए जा सकने वाले ऐसे लंबे कोड का इस्तेमाल करें जिसका इस्तेमाल किया जा सकता है. जैसे:

parcelable User {
    String username;
}

आने वाले समय में, इसे इस तरह से बढ़ाया जा सके:

parcelable User {
    String username;
    int id;
}

2. साफ़ तौर पर डिफ़ॉल्ट जानकारी दें

[-Wclose-default, -Wenum- जेस्चर-default] फ़ील्ड के लिए साफ़ तौर पर डिफ़ॉल्ट बताएं.

पार्सल नहीं किए जा सकने वाले स्ट्रक्चर्ड डेटा

1. इसका इस्तेमाल कब करें

नॉन-स्ट्रक्चर्ड पार्सल, Java में @JavaOnlyStableParcelable के साथ और एनडीके बैकएंड में @NdkOnlyStableParcelable के साथ उपलब्ध हैं. आम तौर पर, ये पुराने और मौजूदा पार्स किए जा सकने वाले ऐसे पार्स किए जा सकते हैं जिन्हें व्यवस्थित नहीं किया जा सकता.

कॉन्स्टेंट और एनम

1. बिटफ़ील्ड में कॉन्सटैंट फ़ील्ड का इस्तेमाल करना चाहिए

बिटफ़ील्ड में कॉन्सटैंट फ़ील्ड का इस्तेमाल किया जाना चाहिए (उदाहरण के लिए, किसी इंटरफ़ेस में const int FOO = 3;).

2. Enums बंद सेट होने चाहिए.

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

3. "NUM_ELEMENTS" जैसे मानों से बचें

ईनम का एक वर्शन होता है. इसलिए, ऐसी वैल्यू से बचना चाहिए जो बताती हैं कि कितनी वैल्यू मौजूद हैं. C++ में, enum_range<> के साथ इसका इस्तेमाल किया जा सकता है. रस्ट के लिए, enum_values() का इस्तेमाल करें. Java में अभी तक कोई समाधान उपलब्ध नहीं है.

इसका सुझाव नहीं दिया जाता: नंबर वाली वैल्यू इस्तेमाल करना

@Backing(type="int")
enum FruitType {
    APPLE = 0,
    BANANA = 1,
    MANGO = 2,
    NUM_TYPES, // BAD
}

4. ग़ैर-ज़रूरी प्रीफ़िक्स और सफ़िक्स इस्तेमाल न करें

[-Wredundant-name] कॉन्सटेंट और एन्यूमरेटर में ग़ैर-ज़रूरी या बार-बार आने वाले प्रीफ़िक्स और सफ़िक्स का इस्तेमाल करने से बचें.

इसका सुझाव नहीं दिया जाता: गै़र-ज़रूरी प्रीफ़िक्स का इस्तेमाल करना

enum MyStatus {
    STATUS_GOOD,
    STATUS_BAD // BAD
}

सुझाव: ईनम को सीधे तौर पर नाम देना

enum MyStatus {
    GOOD,
    BAD
}

फ़ाइल वर्णनकर्ता

[-Wfile-descriptor] आर्ग्युमेंट के तौर पर FileDescriptor का इस्तेमाल या एआईडीएल इंटरफ़ेस वाले तरीके की रिटर्न वैल्यू का इस्तेमाल करने की सलाह बिलकुल नहीं दी जाती. खास तौर पर, जब AIDL को Java में लागू किया जाता है, तो इसकी वजह से फ़ाइल डिस्क्रिप्टर लीक हो सकता है. हालांकि, अगर इसे सावधानी से मैनेज किया जाए, तो ऐसा हो सकता है. इसका मतलब है कि अगर FileDescriptor को इस्तेमाल किया जाता है, तो इसका इस्तेमाल न किए जाने पर, आपको इसे मैन्युअल तरीके से बंद करना होगा.

नेटिव बैकएंड के लिए, आप सुरक्षित हैं, क्योंकि FileDescriptor, unique_fd से मैप करता है, जो अपने-आप बंद हो सकता है. आप भले ही किसी भी बैकएंड भाषा का इस्तेमाल करें, FileDescriptor का इस्तेमाल बिलकुल न करें, क्योंकि इससे आने वाले समय में आपको बैकएंड भाषा में बदलाव करने की आज़ादी नहीं मिलेगी.

इसके बजाय, ParcelFileDescriptor का इस्तेमाल करें, जो अपने-आप बंद हो सकता है.

वैरिएबल की इकाइयां

पक्का करें कि नाम में वैरिएबल यूनिट को शामिल किया गया हो, ताकि दस्तावेज़ की ज़रूरत न पड़ने पर, उनकी इकाइयां अच्छी तरह से समझ सकें और समझ सकें

उदाहरण

long duration; // Bad
long durationNsec; // Good
long durationNanos; // Also good

double energy; // Bad
double energyMilliJoules; // Good

int frequency; // Bad
int frequencyHz; // Good

टाइमस्टैंप से उनका रेफ़रंस पता होना चाहिए

टाइमस्टैंप (वास्तव में, सभी इकाइयां!) में उनकी इकाइयां और रेफ़रंस पॉइंट साफ़ तौर पर दिखने चाहिए.

उदाहरण

/**
 * Time since device boot in milliseconds
 */
long timestampMs;

/**
 * UTC time received from the NTP server in units of milliseconds
 * since January 1, 1970
 */
long utcTimeMs;