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

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

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

संस्करण

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

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

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

सामान्य

1. हर चीज़ का दस्तावेजीकरण करें

  • प्रत्येक विधि को उसके शब्दार्थ, तर्क, अंतर्निहित अपवादों के उपयोग, सेवा विशिष्ट अपवादों और रिटर्न मान के लिए दस्तावेज़ित करें।
  • प्रत्येक इंटरफ़ेस को उसके शब्दार्थ के लिए दस्तावेज़ित करें।
  • एनम और स्थिरांक के अर्थपूर्ण अर्थ का दस्तावेजीकरण करें।
  • जो कुछ भी कार्यान्वयनकर्ता के लिए अस्पष्ट हो सकता है उसका दस्तावेजीकरण करें।
  • जहां प्रासंगिक हो वहां उदाहरण प्रदान करें.

2. आवरण

प्रकारों के लिए ऊपरी ऊँट आवरण का उपयोग करें और तरीकों, क्षेत्रों और तर्कों के लिए निचले ऊँट आवरण का उपयोग करें। उदाहरण के लिए, पार्सल करने योग्य प्रकार के लिए MyParcelable और किसी तर्क के लिए एक anArgument । परिवर्णी शब्दों के लिए, परिवर्णी शब्द को एक शब्द मानें ( NFC -> Nfc )।

[-Wconst-name] Enum मान और स्थिरांक ENUM_VALUE और CONSTANT_NAME होने चाहिए

इंटरफेस

1. नामकरण

[-विंटरफेस-नाम] एक इंटरफ़ेस नाम 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. आउटपुट पैरामीटर के रूप में ऐरे को हानिकारक माना जाता है

[-वाउट-एरे] एरे आउटपुट पैरामीटर वाले तरीके, जैसे void foo(out String[] ret) आमतौर पर खराब होते हैं क्योंकि आउटपुट एरे का आकार जावा में क्लाइंट द्वारा घोषित और आवंटित किया जाना चाहिए, और इसलिए एरे आउटपुट का आकार नहीं हो सकता है सर्वर द्वारा चुना जाएगा. यह अवांछनीय व्यवहार इसलिए होता है क्योंकि जावा में ऐरे कैसे काम करते हैं (उन्हें पुनः आवंटित नहीं किया जा सकता है)। इसके बजाय String[] foo() जैसे API को प्राथमिकता दें।

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

[-विनआउट-पैरामीटर] यह ग्राहकों को भ्रमित कर सकता है क्योंकि पैरामीटर in भी पैरामीटर out की तरह दिखते हैं।

7. आउट/इनआउट @शून्य गैर-सरणी पैरामीटर से बचें

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

संरचित पार्सल योग्य वस्तुएँ

1. कब उपयोग करें

जहां आपके पास भेजने के लिए कई डेटा प्रकार हों, वहां संरचित पार्सलेबल्स का उपयोग करें।

या, जब आपके पास वर्तमान में एक ही डेटा प्रकार है लेकिन आप उम्मीद करते हैं कि आपको भविष्य में इसे विस्तारित करने की आवश्यकता होगी। उदाहरण के लिए, String username उपयोग न करें। निम्नलिखित की तरह एक विस्तार योग्य पार्सल का उपयोग करें:

parcelable User {
    String username;
}

ताकि, भविष्य में, आप इसे इस प्रकार बढ़ा सकें:

parcelable User {
    String username;
    int id;
}

2. स्पष्ट रूप से डिफ़ॉल्ट प्रदान करें

[-वेक्सप्लिसिट-डिफॉल्ट, -वेनम-स्पष्ट-डिफॉल्ट] फ़ील्ड के लिए स्पष्ट डिफ़ॉल्ट प्रदान करें।

गैर-संरचित पार्सल योग्य वस्तुएँ

1. कब उपयोग करें

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

स्थिरांक और गणनाएँ

1. बिटफील्ड्स को निरंतर फ़ील्ड्स का उपयोग करना चाहिए

बिटफ़ील्ड को निरंतर फ़ील्ड का उपयोग करना चाहिए (उदाहरण के लिए इंटरफ़ेस में const int FOO = 3; )।

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

Enums बंद सेट होना चाहिए. नोट: केवल इंटरफ़ेस स्वामी ही एनम तत्व जोड़ सकता है। यदि विक्रेताओं या ओईएम को इन क्षेत्रों का विस्तार करने की आवश्यकता है, तो एक वैकल्पिक तंत्र की आवश्यकता है। जब भी संभव हो, अपस्ट्रीमिंग विक्रेता कार्यक्षमता को प्राथमिकता दी जानी चाहिए। हालाँकि, कुछ मामलों में, कस्टम विक्रेता मूल्यों की अनुमति दी जा सकती है (हालांकि, विक्रेताओं के पास इसे संस्करणित करने के लिए एक तंत्र होना चाहिए, शायद एआईडीएल ही, उन्हें एक-दूसरे के साथ संघर्ष करने में सक्षम नहीं होना चाहिए, और ये मूल्य नहीं होने चाहिए तृतीय पक्ष ऐप्स के संपर्क में)।

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

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

अनुशंसित नहीं: क्रमांकित मानों का उपयोग करना

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

4. अनावश्यक उपसर्गों और प्रत्ययों से बचें

[-रेडुंडेंट-नाम] स्थिरांकों और प्रगणकों में अनावश्यक या दोहराव वाले उपसर्गों और प्रत्ययों से बचें।

अनुशंसित नहीं: अनावश्यक उपसर्ग का उपयोग करना

enum MyStatus {
    STATUS_GOOD,
    STATUS_BAD // BAD
}

अनुशंसित: सीधे एनम का नामकरण

enum MyStatus {
    GOOD,
    BAD
}

फाइल डिस्क्रिप्टर

[-Wfile-descriptor] तर्क के रूप में FileDescriptor का उपयोग या AIDL इंटरफ़ेस विधि के रिटर्न मान को अत्यधिक हतोत्साहित किया जाता है। विशेष रूप से, जब एआईडीएल को जावा में लागू किया जाता है, तो यह फ़ाइल डिस्क्रिप्टर लीक का कारण बन सकता है जब तक कि सावधानीपूर्वक संभाला न जाए। मूल रूप से, यदि आप 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;