এআইডিএল স্টাইল গাইড

এখানে বর্ণিত সর্বোত্তম অনুশীলনগুলি কার্যকরভাবে এবং ইন্টারফেসের নমনীয়তার দিকে মনোযোগ সহ AIDL ইন্টারফেসগুলি বিকাশের জন্য একটি নির্দেশিকা হিসাবে কাজ করে, বিশেষত যখন AIDL একটি API সংজ্ঞায়িত করতে বা API পৃষ্ঠের সাথে যোগাযোগ করতে ব্যবহৃত হয়।

এআইডিএল একটি API সংজ্ঞায়িত করতে ব্যবহার করা যেতে পারে যখন অ্যাপ্লিকেশনগুলিকে একটি ব্যাকগ্রাউন্ড প্রক্রিয়াতে একে অপরের সাথে ইন্টারফেস করতে হবে বা সিস্টেমের সাথে ইন্টারফেস করতে হবে। AIDL-এর সাথে অ্যাপে প্রোগ্রামিং ইন্টারফেস তৈরি করার বিষয়ে আরও তথ্যের জন্য, Android ইন্টারফেস ডেফিনিশন ল্যাঙ্গুয়েজ (AIDL) দেখুন। অনুশীলনে এআইডিএল-এর উদাহরণের জন্য, এইচএএল এবং স্থিতিশীল এআইডিএল- এর জন্য এআইডিএল দেখুন।

সংস্করণ করা

একটি AIDL API এর প্রতিটি পিছনের-সামঞ্জস্যপূর্ণ স্ন্যাপশট একটি সংস্করণের সাথে মিলে যায়৷ একটি স্ন্যাপশট নিতে, m <module-name>-freeze-api চালান। যখনই API-এর একটি ক্লায়েন্ট বা সার্ভার প্রকাশিত হয় (যেমন একটি প্রধান লাইন ট্রেনে), আপনাকে একটি স্ন্যাপশট নিতে হবে এবং একটি নতুন সংস্করণ তৈরি করতে হবে। সিস্টেম-টু-ভেন্ডার API-এর জন্য, এটি বার্ষিক প্ল্যাটফর্ম সংশোধনের সাথে হওয়া উচিত।

অনুমোদিত পরিবর্তনের ধরন সম্পর্কে আরও বিশদ এবং তথ্যের জন্য, সংস্করণ ইন্টারফেস দেখুন।

API ডিজাইন নির্দেশিকা

সাধারণ

1. সবকিছু নথিভুক্ত করুন

  • প্রতিটি পদ্ধতির শব্দার্থবিদ্যা, আর্গুমেন্ট, অন্তর্নির্মিত ব্যতিক্রমের ব্যবহার, পরিষেবা নির্দিষ্ট ব্যতিক্রম এবং রিটার্ন মানের জন্য নথিভুক্ত করুন।
  • প্রতিটি ইন্টারফেস এর শব্দার্থবিদ্যার জন্য নথিভুক্ত করুন।
  • enums এবং constants এর শব্দার্থিক অর্থ নথিভুক্ত করুন।
  • একটি বাস্তবায়নকারীর কাছে যা অস্পষ্ট হতে পারে তা নথিভুক্ত করুন।
  • যেখানে প্রাসঙ্গিক উদাহরণ প্রদান করুন.

2. আবরণ

ধরনগুলির জন্য উপরের উটের আবরণ এবং পদ্ধতি, ক্ষেত্র এবং যুক্তিগুলির জন্য নীচের উটের আবরণ ব্যবহার করুন। উদাহরণস্বরূপ, একটি পার্সেলেবল টাইপের জন্য MyParcelable এবং একটি আর্গুমেন্টের জন্য anArgument । সংক্ষিপ্ত শব্দের জন্য, সংক্ষিপ্ত রূপটি একটি শব্দ বিবেচনা করুন ( NFC -> Nfc )।

[-Wconst-name] Enum মান এবং ধ্রুবক ENUM_VALUE এবং CONSTANT_NAME হওয়া উচিত

ইন্টারফেস

1. নামকরণ

[-Winterface-name] একটি ইন্টারফেসের নাম I like IFoo দিয়ে শুরু হওয়া উচিত।

2. আইডি-ভিত্তিক "বস্তু" সহ বড় ইন্টারফেস এড়িয়ে চলুন

একটি নির্দিষ্ট API এর সাথে সম্পর্কিত অনেক কল থাকলে সাব-ইন্টারফেস পছন্দ করুন। এটি নিম্নলিখিত সুবিধাগুলি প্রদান করে: - ক্লায়েন্ট/সার্ভার কোড বোঝা সহজ করে তোলে - বস্তুর জীবনচক্রকে সহজ করে তোলে - বাইন্ডারগুলি অবিস্মরণীয় হওয়ার সুবিধা নেয়৷

প্রস্তাবিত নয়: আইডি-ভিত্তিক বস্তুর সাথে একটি একক, বড় ইন্টারফেস

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. স্ট্যাটাস কোড ফেরত এড়িয়ে চলুন

পদ্ধতিগুলিকে রিটার্ন মান হিসাবে স্ট্যাটাস কোডগুলি এড়ানো উচিত, যেহেতু সমস্ত AIDL পদ্ধতিতে একটি অন্তর্নিহিত স্থিতি রিটার্ন কোড রয়েছে। ServiceSpecificException বা EX_SERVICE_SPECIFIC দেখুন। নিয়ম অনুসারে, এই মানগুলি একটি AIDL ইন্টারফেসে ধ্রুবক হিসাবে সংজ্ঞায়িত করা হয়। আরও বিস্তারিত তথ্য এআইডিএল ব্যাকএন্ডের ত্রুটি পরিচালনা বিভাগে রয়েছে।

5. ক্ষতিকারক হিসাবে বিবেচিত আউটপুট প্যারামিটার হিসাবে অ্যারে

[-Wout-array] অ্যারে আউটপুট প্যারামিটার থাকা পদ্ধতিগুলি, যেমন void foo(out String[] ret) সাধারণত খারাপ কারণ আউটপুট অ্যারের আকার অবশ্যই জাভাতে ক্লায়েন্ট দ্বারা ঘোষণা এবং বরাদ্দ করা উচিত, এবং তাই অ্যারের আউটপুটের আকার হতে পারে না সার্ভার দ্বারা নির্বাচিত করা হবে। এই অবাঞ্ছিত আচরণটি জাভাতে অ্যারে কীভাবে কাজ করে তার কারণে ঘটে (তারা পুনরায় বরাদ্দ করা যায় না)। পরিবর্তে String[] foo() এর মত API পছন্দ করুন।

6. ইনআউট প্যারামিটার এড়িয়ে চলুন

[-উইনআউট-প্যারামিটার] এটি ক্লায়েন্টদের বিভ্রান্ত করতে পারে কারণ এমনকি in out প্যারামিটারের মতো দেখায়।

7. @nullable নন-অ্যারে প্যারামিটার আউট/ইনআউট এড়িয়ে চলুন

[-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. স্পষ্টভাবে ডিফল্ট প্রদান করুন

[-Wexplicit-default, -Wenum-explicit-default] ক্ষেত্রের জন্য স্পষ্ট ডিফল্ট প্রদান করুন।

অ-গঠিত parcelables

1. কখন ব্যবহার করতে হবে

নন-স্ট্রাকচার্ড পার্সেলেবল বর্তমানে জাভাতে @JavaOnlyStableParcelable এর সাথে এবং NDK ব্যাকএন্ডে @NdkOnlyStableParcelable এর সাথে উপলব্ধ। সাধারণত, এগুলি পুরানো এবং বিদ্যমান পার্সেবল যা সহজে গঠন করা যায় না।

ধ্রুবক এবং Enums

1. Bitfields ধ্রুবক ক্ষেত্র ব্যবহার করা উচিত

Bitfields ধ্রুবক ক্ষেত্র ব্যবহার করা উচিত (যেমন const int FOO = 3; একটি ইন্টারফেসে)।

2. Enums সেট বন্ধ করা উচিত.

Enums সেট বন্ধ করা উচিত. দ্রষ্টব্য: শুধুমাত্র ইন্টারফেসের মালিক enum উপাদান যোগ করতে পারেন। যদি বিক্রেতা বা OEM-দের এই ক্ষেত্রগুলিকে প্রসারিত করতে হয়, তাহলে একটি বিকল্প ব্যবস্থা প্রয়োজন। যখনই সম্ভব, আপস্ট্রিমিং বিক্রেতা কার্যকারিতা পছন্দ করা উচিত। যাইহোক, কিছু ক্ষেত্রে, কাস্টম বিক্রেতার মানগুলি এর মাধ্যমে অনুমোদিত হতে পারে (যদিও, বিক্রেতাদের এটি সংস্করণ করার জন্য একটি ব্যবস্থা থাকা উচিত, সম্ভবত এআইডিএল নিজেই, তারা একে অপরের সাথে বিরোধ করতে সক্ষম হবে না, এবং এই মানগুলি হওয়া উচিত নয় তৃতীয় পক্ষের অ্যাপের সংস্পর্শে আসে)।

3. "NUM_ELEMENTS" এর মত মান এড়িয়ে চলুন

যেহেতু enums সংস্করণ করা হয়, যে মানগুলি নির্দেশ করে যে কতগুলি মান উপস্থিত রয়েছে তা এড়ানো উচিত। 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 নামকরণ

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;